You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2022/11/21 19:23:14 UTC

[commons-statistics] 01/12: Convert to parameterized tests

This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-statistics.git

commit a7153c2343a70665ca8b45dbbc45f66be0bac7be
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Mon Nov 21 16:57:12 2022 +0000

    Convert to parameterized tests
---
 .../distribution/GammaDistributionTest.java        | 264 +++++++++------------
 1 file changed, 116 insertions(+), 148 deletions(-)

diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java
index 7c5ae4b..3d9c73c 100644
--- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java
@@ -25,9 +25,9 @@ import java.util.stream.Stream;
 import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
 import org.apache.commons.numbers.gamma.LanczosApproximation;
 import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.CsvSource;
 import org.junit.jupiter.params.provider.MethodSource;
 
 /**
@@ -80,114 +80,111 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
         );
     }
 
-    @Test
-    void testAdditionalCumulativeProbability() {
-        checkCumulativeProbability(-1.000, 4.0, 2.0, 0.0);
-        checkCumulativeProbability(15.501, 4.0, 2.0, 0.94989465156755404);
-        checkCumulativeProbability(0.504, 4.0, 1.0, 0.0018026739713985257);
-        checkCumulativeProbability(10.011, 1.0, 2.0, 0.99329900998454213);
-        checkCumulativeProbability(5.000, 2.0, 2.0, 0.71270250481635422);
-    }
-
-    private void checkCumulativeProbability(double x, double a, double b, double expected) {
-        final GammaDistribution distribution = GammaDistribution.of(a, b);
-        final double actual = distribution.cumulativeProbability(x);
+    @ParameterizedTest
+    @CsvSource({
+        "4.0, 2.0, -1.0, 0.0",
+        "4.0, 2.0, 15.501, 0.94989465156755404",
+        "4.0, 1.0, 0.504, 0.0018026739713985257",
+        "1.0, 2.0, 10.011, 0.99329900998454213",
+        "2.0, 2.0, 5.000, 0.71270250481635422",
+    })
+    void testAdditionalCumulativeProbability(double a, double b, double x, double expected) {
+        final GammaDistribution dist = GammaDistribution.of(a, b);
+        final double actual = dist.cumulativeProbability(x);
         Assertions.assertEquals(expected, actual, expected * 1e-15, () -> "probability for " + x);
     }
 
-    @Test
-    void testAdditionalInverseCumulativeProbability() {
-        checkInverseCumulativeProbability(15.501, 4.0, 2.0, 0.94989465156755404);
-        checkInverseCumulativeProbability(0.504, 4.0, 1.0, 0.0018026739713985257);
-        checkInverseCumulativeProbability(10.011, 1.0, 2.0, 0.99329900998454213);
-        checkInverseCumulativeProbability(5.000, 2.0, 2.0, 0.71270250481635422);
-    }
-
-    private void checkInverseCumulativeProbability(double expected, double a, double b, double p) {
-        final GammaDistribution distribution = GammaDistribution.of(a, b);
-        final double actual = distribution.inverseCumulativeProbability(p);
-        Assertions.assertEquals(expected, actual, expected * 1e-10, () -> "critical value for " + p);
+    @ParameterizedTest
+    @CsvSource({
+        "4.0, 2.0, 0.94989465156755404, 15.501",
+        "4.0, 1.0, 0.0018026739713985257, 0.504",
+        "1.0, 2.0, 0.99329900998454213, 10.011",
+        "2.0, 2.0, 0.71270250481635422, 5.0",
+    })
+    void testAdditionalInverseCumulativeProbability(double a, double b, double p, double expected) {
+        final GammaDistribution dist = GammaDistribution.of(a, b);
+        final double actual = dist.inverseCumulativeProbability(p);
+        Assertions.assertEquals(expected, actual, expected * 5e-15, () -> "critical value for " + p);
     }
 
-    @Test
-    void testAdditionalDensity() {
-        final double[] x = new double[]{-0.1, 1e-6, 0.5, 1, 2, 5};
-        // R2.5: print(dgamma(x, shape=1, rate=1), digits=10)
-        checkDensity(1, 1, x, new double[]{0.000000000000, 0.999999000001, 0.606530659713, 0.367879441171, 0.135335283237, 0.006737946999});
-        // R2.5: print(dgamma(x, shape=2, rate=1), digits=10)
-        checkDensity(2, 1, x, new double[]{0.000000000000, 0.000000999999, 0.303265329856, 0.367879441171, 0.270670566473, 0.033689734995});
-        // R2.5: print(dgamma(x, shape=4, rate=1), digits=10)
-        checkDensity(4, 1, x, new double[]{0.000000000e+00, 1.666665000e-19, 1.263605541e-02, 6.131324020e-02, 1.804470443e-01, 1.403738958e-01});
-        // R2.5: print(dgamma(x, shape=4, rate=10), digits=10)
-        checkDensity(4, 10, x, new double[]{0.000000000e+00, 1.666650000e-15, 1.403738958e+00, 7.566654960e-02, 2.748204830e-05, 4.018228850e-17});
-        // R2.5: print(dgamma(x, shape=.1, rate=10), digits=10)
-        checkDensity(0.1, 10, x, new double[]{0.000000000e+00, 3.323953832e+04, 1.663849010e-03, 6.007786726e-06, 1.461647647e-10, 5.996008322e-24});
-        // R2.5: print(dgamma(x, shape=.1, rate=20), digits=10)
-        checkDensity(0.1, 20, x, new double[]{0.000000000e+00, 3.562489883e+04, 1.201557345e-05, 2.923295295e-10, 3.228910843e-19, 1.239484589e-45});
-        // R2.5: print(dgamma(x, shape=.1, rate=4), digits=10)
-        checkDensity(0.1, 4, x, new double[]{0.000000000e+00, 3.032938388e+04, 3.049322494e-02, 2.211502311e-03, 2.170613371e-05, 5.846590589e-11});
-        // R2.5: print(dgamma(x, shape=.1, rate=1), digits=10)
-        checkDensity(0.1, 1, x, new double[]{0.000000000e+00, 2.640334143e+04, 1.189704437e-01, 3.866916944e-02, 7.623306235e-03, 1.663849010e-04});
-        // To force overflow condition
-        // R2.5: print(dgamma(x, shape=1000, rate=100), digits=10)
-        checkDensity(1000, 100, x, new double[]{0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 3.304830256e-84});
+    @ParameterizedTest
+    @MethodSource
+    void testAdditionalDensity(double alpha, double rate, double[] x, double[] expected) {
+        final GammaDistribution dist = GammaDistribution.of(alpha, 1 / rate);
+        testDensity(dist, x, expected, DoubleTolerances.relative(1e-9));
     }
 
-    /**
-     * Test a shape far below 1. Support for very small shape parameters
-     * was fixed in STATISTICS-39.
-     */
-    @Test
-    void testShapeBelow1() {
-        // R2.5: print(dgamma(x, shape=0.05, rate=1), digits=20)
-        final double[] x = new double[]{1e-100, 1e-10, 1e-5, 0.1};
-        checkDensity(0.05, 1, x, new double[] {
-            5.1360843263583843333e+93, 1.6241724724359893799e+08,
-            2.8882035841935007738e+03, 4.1419294512123655538e-01
-        });
+    static Stream<Arguments> testAdditionalDensity() {
+        final double[] x = {-0.1, 1e-6, 0.5, 1, 2, 5};
+        final double[] x1 = new double[]{1e-100, 1e-10, 1e-5, 0.1};
+        return Stream.of(
+            // R2.5: print(dgamma((x, shape=1, rate=1), digits=10)
+            Arguments.of(1, 1, x, new double[]{0.000000000000, 0.999999000001, 0.606530659713, 0.367879441171, 0.135335283237, 0.006737946999}),
+            // R2.5: print(dgamma((x, shape=2, rate=1), digits=10)
+            Arguments.of(2, 1, x, new double[]{0.000000000000, 0.000000999999, 0.303265329856, 0.367879441171, 0.270670566473, 0.033689734995}),
+            // R2.5: print(dgamma((x, shape=4, rate=1), digits=10)
+            Arguments.of(4, 1, x, new double[]{0.000000000e+00, 1.666665000e-19, 1.263605541e-02, 6.131324020e-02, 1.804470443e-01, 1.403738958e-01}),
+            // R2.5: print(dgamma((x, shape=4, rate=10), digits=10)
+            Arguments.of(4, 10, x, new double[]{0.000000000e+00, 1.666650000e-15, 1.403738958e+00, 7.566654960e-02, 2.748204830e-05, 4.018228850e-17}),
+            // R2.5: print(dgamma((x, shape=.1, rate=10), digits=10)
+            Arguments.of(0.1, 10, x, new double[]{0.000000000e+00, 3.323953832e+04, 1.663849010e-03, 6.007786726e-06, 1.461647647e-10, 5.996008322e-24}),
+            // R2.5: print(dgamma((x, shape=.1, rate=20), digits=10)
+            Arguments.of(0.1, 20, x, new double[]{0.000000000e+00, 3.562489883e+04, 1.201557345e-05, 2.923295295e-10, 3.228910843e-19, 1.239484589e-45}),
+            // R2.5: print(dgamma((x, shape=.1, rate=4), digits=10)
+            Arguments.of(0.1, 4, x, new double[]{0.000000000e+00, 3.032938388e+04, 3.049322494e-02, 2.211502311e-03, 2.170613371e-05, 5.846590589e-11}),
+            // R2.5: print(dgamma((x, shape=.1, rate=1), digits=10)
+            Arguments.of(0.1, 1, x, new double[]{0.000000000e+00, 2.640334143e+04, 1.189704437e-01, 3.866916944e-02, 7.623306235e-03, 1.663849010e-04}),
+            // To force overflow condition
+            // R2.5: print(dgamma((x, shape=1000, rate=100), digits=10)
+            Arguments.of(1000, 100, x, new double[]{0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 3.304830256e-84}),
+
+            // Test a shape far below 1.
+            // Support for very small shape parameters was fixed in STATISTICS-39.
+            // R2.5: print(dgamma((x1, shape=0.05, rate=1), digits=20)
+            Arguments.of(0.05, 1, x1,
+                new double[] {
+                    5.1360843263583843333e+93, 1.6241724724359893799e+08,
+                    2.8882035841935007738e+03, 4.1419294512123655538e-01
+                })
+        );
     }
 
-    private void checkDensity(double alpha, double rate, double[] x, double[] expected) {
+    @ParameterizedTest
+    @MethodSource
+    void testAdditionalLogDensity(double alpha, double rate, double[] x, double[] expected) {
         final GammaDistribution dist = GammaDistribution.of(alpha, 1 / rate);
-        for (int i = 0; i < x.length; i++) {
-            Assertions.assertEquals(expected[i], dist.density(x[i]), Math.abs(expected[i]) * 1e-9);
-        }
+        testLogDensity(dist, x, expected, DoubleTolerances.relative(1e-9));
     }
 
-    @Test
-    void testAdditionalLogDensity() {
-        final double[] x = new double[]{-0.1, 1e-6, 0.5, 1, 2, 5};
-        final double inf = Double.POSITIVE_INFINITY;
-        // R2.5: print(dgamma(x, shape=1, rate=1, log=TRUE), digits=10)
-        checkLogDensity(1, 1, x, new double[]{-inf, -1e-06, -5e-01, -1e+00, -2e+00, -5e+00});
-        // R2.5: print(dgamma(x, shape=2, rate=1, log=TRUE), digits=10)
-        checkLogDensity(2, 1, x, new double[]{-inf, -13.815511558, -1.193147181, -1.000000000, -1.306852819, -3.390562088});
-        // R2.5: print(dgamma(x, shape=4, rate=1, log=TRUE), digits=10)
-        checkLogDensity(4, 1, x, new double[]{-inf, -43.238292143, -4.371201011, -2.791759469, -1.712317928, -1.963445732});
-        // R2.5: print(dgamma(x, shape=4, rate=10, log=TRUE), digits=10)
-        checkLogDensity(4, 10, x, new double[]{-inf, -34.0279607711, 0.3391393611, -2.5814190973, -10.5019775556, -37.7531053599});
-        // R2.5: print(dgamma(x, shape=.1, rate=10, log=TRUE), digits=10)
-        checkLogDensity(0.1, 10, x, new double[]{-inf, 10.41149536, -6.39862168, -12.02245414, -22.64628660, -53.47094826});
-        // R2.5: print(dgamma(x, shape=.1, rate=20, log=TRUE), digits=10)
-        checkLogDensity(0.1, 20, x, new double[]{-inf, 10.48080008, -11.32930696, -21.95313942, -42.57697189, -103.40163355});
-        // R2.5: print(dgamma(x, shape=.1, rate=4, log=TRUE), digits=10)
-        checkLogDensity(0.1, 4, x, new double[]{-inf, 10.319872287, -3.490250753, -6.114083216, -10.737915678, -23.562577337});
-        // R2.5: print(dgamma(x, shape=.1, rate=1, log=TRUE), digits=10)
-        checkLogDensity(0.1, 1, x, new double[]{-inf, 10.181245850, -2.128880189, -3.252712652, -4.876545114, -8.701206773});
-        // To force overflow condition to pdf=zero
-        // R2.5: print(dgamma(x, shape=1000, rate=100, log=TRUE), digits=10)
-        checkLogDensity(1000, 100, x, new double[]{-inf, -15101.7453846, -2042.5042706, -1400.0502372, -807.5962038, -192.2217627});
-        // To force overflow condition to pdf=infinity
+    static Stream<Arguments> testAdditionalLogDensity() {
+        final double[] x = {-0.1, 1e-6, 0.5, 1, 2, 5};
         final double[] x1 = {1e-315, 1e-320, 1e-323};
-        // scipy.stats gamma(1e-2).logpdf(x1)
-        checkLogDensity(0.01, 1, x1, new double[]{713.46168137365419, 724.85948860402209, 731.70997561537104});
-    }
-
-    private void checkLogDensity(double alpha, double rate, double[] x, double[] expected) {
-        final GammaDistribution dist = GammaDistribution.of(alpha, 1 / rate);
-        for (int i = 0; i < x.length; i++) {
-            Assertions.assertEquals(expected[i], dist.logDensity(x[i]), Math.abs(expected[i]) * 1e-9);
-        }
+        final double inf = Double.POSITIVE_INFINITY;
+        return Stream.of(
+            // R2.5: print(dgamma((x, shape=1, rate=1, log=TRUE), digits=10)
+            Arguments.of(1, 1, x, new double[]{-inf, -1e-06, -5e-01, -1e+00, -2e+00, -5e+00}),
+            // R2.5: print(dgamma((x, shape=2, rate=1, log=TRUE), digits=10)
+            Arguments.of(2, 1, x, new double[]{-inf, -13.815511558, -1.193147181, -1.000000000, -1.306852819, -3.390562088}),
+            // R2.5: print(dgamma((x, shape=4, rate=1, log=TRUE), digits=10)
+            Arguments.of(4, 1, x, new double[]{-inf, -43.238292143, -4.371201011, -2.791759469, -1.712317928, -1.963445732}),
+            // R2.5: print(dgamma((x, shape=4, rate=10, log=TRUE), digits=10)
+            Arguments.of(4, 10, x, new double[]{-inf, -34.0279607711, 0.3391393611, -2.5814190973, -10.5019775556, -37.7531053599}),
+            // R2.5: print(dgamma((x, shape=.1, rate=10, log=TRUE), digits=10)
+            Arguments.of(0.1, 10, x, new double[]{-inf, 10.41149536, -6.39862168, -12.02245414, -22.64628660, -53.47094826}),
+            // R2.5: print(dgamma((x, shape=.1, rate=20, log=TRUE), digits=10)
+            Arguments.of(0.1, 20, x, new double[]{-inf, 10.48080008, -11.32930696, -21.95313942, -42.57697189, -103.40163355}),
+            // R2.5: print(dgamma((x, shape=.1, rate=4, log=TRUE), digits=10)
+            Arguments.of(0.1, 4, x, new double[]{-inf, 10.319872287, -3.490250753, -6.114083216, -10.737915678, -23.562577337}),
+            // R2.5: print(dgamma((x, shape=.1, rate=1, log=TRUE), digits=10)
+            Arguments.of(0.1, 1, x, new double[]{-inf, 10.181245850, -2.128880189, -3.252712652, -4.876545114, -8.701206773}),
+            // To force overflow condition to pdf=zero
+            // R2.5: print(dgamma((x, shape=1000, rate=100, log=TRUE), digits=10)
+            Arguments.of(1000, 100, x, new double[]{-inf, -15101.7453846, -2042.5042706, -1400.0502372, -807.5962038, -192.2217627}),
+            // To force overflow condition to pdf=infinity
+            // scipy.stats gamma(1e-2).logpdf(x1)
+            Arguments.of(0.01, 1, x1,
+                new double[]{713.46168137365419, 724.85948860402209, 731.70997561537104})
+        );
     }
 
     private static double logGamma(double x) {
@@ -205,9 +202,9 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
             HALF_LOG_2_PI + Math.log(sum / x);
     }
 
-    private static double density(final double x,
-                                  final double shape,
-                                  final double scale) {
+    private static double density(double x,
+                                  double shape,
+                                  double scale) {
         /*
          * This is a copy of
          * double GammaDistribution.density(double)
@@ -234,11 +231,13 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
      * @param resourceName Resource name containing a pair of comma separated values for the
      * random variable x and the expected value of the gamma distribution: x, gamma(x; shape, scale=1)
      */
-    private void doTestMath753(final double shape,
-                               final double meanNoOF, final double sdNoOF,
-                               final double meanOF, final double sdOF,
-                               final String resourceName) {
-        final GammaDistribution distribution = GammaDistribution.of(shape, 1.0);
+    @ParameterizedTest
+    @MethodSource
+    void testMath753(double shape,
+                     double meanNoOF, double sdNoOF,
+                     double meanOF, double sdOF,
+                     String resourceName) {
+        final GammaDistribution dist = GammaDistribution.of(shape, 1.0);
         final SummaryStatistics statOld = new SummaryStatistics();
         // statNewNoOF = No overflow of old function
         // statNewOF   = Overflow of old function
@@ -261,7 +260,7 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
                 final double expected = Double.parseDouble(tokens[1]);
                 final double ulp = Math.ulp(expected);
                 final double actualOld = density(x, shape, 1.0);
-                final double actualNew = distribution.density(x);
+                final double actualNew = dist.density(x);
                 final double errOld = Math.abs((actualOld - expected) / ulp);
                 final double errNew = Math.abs((actualNew - expected) / ulp);
 
@@ -333,48 +332,17 @@ class GammaDistributionTest extends BaseContinuousDistributionTest {
         }
     }
 
-    @Test
-    void testMath753Shape025() {
-        doTestMath753(0.25, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.25.csv");
-    }
-
-    @Test
-    void testMath753Shape05() {
-        doTestMath753(0.5, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.5.csv");
-    }
-
-    @Test
-    void testMath753Shape075() {
-        doTestMath753(0.75, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.75.csv");
-    }
-
-    @Test
-    void testMath753Shape1() {
-        doTestMath753(1.0, 1.0, 0.5, 0.0, 0.0, "gamma-distribution-shape-1.csv");
-    }
-
-    @Test
-    void testMath753Shape8() {
-        doTestMath753(8.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-8.csv");
-    }
-
-    @Test
-    void testMath753Shape10() {
-        doTestMath753(10.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-10.csv");
-    }
-
-    @Test
-    void testMath753Shape100() {
-        doTestMath753(100.0, 2.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-100.csv");
-    }
-
-    @Test
-    void testMath753Shape142() {
-        doTestMath753(142.0, 1.5, 1.0, 40.0, 40.0, "gamma-distribution-shape-142.csv");
-    }
-
-    @Test
-    void testMath753Shape1000() {
-        doTestMath753(1000.0, 1.0, 1.0, 160.0, 200.0, "gamma-distribution-shape-1000.csv");
+    static Stream<Arguments> testMath753() {
+        return Stream.of(
+            Arguments.of(0.25, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.25.csv"),
+            Arguments.of(0.5, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.5.csv"),
+            Arguments.of(0.75, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.75.csv"),
+            Arguments.of(1.0, 1.0, 0.5, 0.0, 0.0, "gamma-distribution-shape-1.csv"),
+            Arguments.of(8.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-8.csv"),
+            Arguments.of(10.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-10.csv"),
+            Arguments.of(100.0, 2.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-100.csv"),
+            Arguments.of(142.0, 1.5, 1.0, 40.0, 40.0, "gamma-distribution-shape-142.csv"),
+            Arguments.of(1000.0, 1.0, 1.0, 160.0, 200.0, "gamma-distribution-shape-1000.csv")
+        );
     }
 }