Skip to content

Commit d248a0e

Browse files
Break down tests having multiple checks and xfail decorated (#4497)
* Break down tests having multiple checks and xfail decorated Xfail is going to care only about the first failed assert statement and ignore all the other ones in the same test. Sometimes xfail is being used to decorate a test or class function calling several other sub-functions. This makes it hard to monitor what is happening for the sub-fuctions that are not failing (given that the failure will take priority and mark the test function as xfailed). By breaking down each function into individual sub-functions it's easier to monitor individual tests behavior * Remove xfail which seems unnecessary Also add comment regarding test with unpredictable outcome * Break down test with multiple sub-checks and xfail where appropriate * Remove Scipy Xfail from tests not using sp.betabinom * Add back xfail to potentially failing test when float32 is used * Temporatily add n_samples=-1 to check tests behavior for all possible parameters * Remove temporary n_samples and a couple more to do some quick tests * Remove unnecessary comments * Replace Xfail with skipif when using Scipy version as condition Given that betabinom won't exist in previous versions, there should be no chance for it's behavior to change, given that it won't exist there is no point in monitoring the outcome of these tests, so it may be worth skipping them. Skipping them should be faster than running them and catching the failures * Add missing n_samples for test_beta_binomial_selfconsistency * Remove all the n_samples=-1 added for verifying tests robustness * Tweak normal_logcdf and moyal tests Temporarily set n_samples=-1 to test all permutations. * Reintroduce 32bit xfail on Moyal logcdf, revert n_samples and merge passing normal tests * Small renaming and reordering * Reintroduce accidentally removed n_samples from binomial test Co-authored-by: Ricardo <[email protected]>
1 parent 34b35c1 commit d248a0e

File tree

5 files changed

+98
-48
lines changed

5 files changed

+98
-48
lines changed

pymc3/tests/test_distributions.py

Lines changed: 82 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -770,9 +770,9 @@ def check_selfconsistency_discrete_logcdf(
770770
err_msg=str(pt),
771771
)
772772

773-
def check_int_to_1(self, model, value, domain, paramdomains):
773+
def check_int_to_1(self, model, value, domain, paramdomains, n_samples=10):
774774
pdf = model.fastfn(exp(model.logpt))
775-
for pt in product(paramdomains, n_samples=10):
775+
for pt in product(paramdomains, n_samples=n_samples):
776776
pt = Point(pt, value=value.tag.test_value, model=model)
777777
bij = DictToVarBijection(value, (), pt)
778778
pdfx = bij.mapf(pdf)
@@ -902,6 +902,7 @@ def test_normal(self):
902902
R,
903903
{"mu": R, "sigma": Rplus},
904904
lambda value, mu, sigma: sp.norm.logcdf(value, mu, sigma),
905+
decimal=select_by_precision(float64=6, float32=2),
905906
)
906907

907908
def test_truncated_normal(self):
@@ -941,25 +942,6 @@ def test_chi_squared(self):
941942
lambda value, nu: sp.chi2.logpdf(value, df=nu),
942943
)
943944

944-
@pytest.mark.xfail(
945-
condition=(aesara.config.floatX == "float32"),
946-
reason="Poor CDF in SciPy. See scipy/scipy#869 for details.",
947-
)
948-
def test_wald_scipy(self):
949-
self.check_logp(
950-
Wald,
951-
Rplus,
952-
{"mu": Rplus, "alpha": Rplus},
953-
lambda value, mu, alpha: sp.invgauss.logpdf(value, mu=mu, loc=alpha),
954-
decimal=select_by_precision(float64=6, float32=1),
955-
)
956-
self.check_logcdf(
957-
Wald,
958-
Rplus,
959-
{"mu": Rplus, "alpha": Rplus},
960-
lambda value, mu, alpha: sp.invgauss.logcdf(value, mu=mu, loc=alpha),
961-
)
962-
963945
@pytest.mark.parametrize(
964946
"value,mu,lam,phi,alpha,logp",
965947
[
@@ -979,7 +961,7 @@ def test_wald_scipy(self):
979961
(50.0, 15.0, None, 0.666666, 10.0, -5.6481874),
980962
],
981963
)
982-
def test_wald(self, value, mu, lam, phi, alpha, logp):
964+
def test_wald_logp_custom_points(self, value, mu, lam, phi, alpha, logp):
983965
# Log probabilities calculated using the dIG function from the R package gamlss.
984966
# See e.g., doi: 10.1111/j.1467-9876.2005.00510.x, or
985967
# http://www.gamlss.org/.
@@ -989,6 +971,27 @@ def test_wald(self, value, mu, lam, phi, alpha, logp):
989971
decimals = select_by_precision(float64=6, float32=1)
990972
assert_almost_equal(model.fastlogp(pt), logp, decimal=decimals, err_msg=str(pt))
991973

974+
def test_wald_logp(self):
975+
self.check_logp(
976+
Wald,
977+
Rplus,
978+
{"mu": Rplus, "alpha": Rplus},
979+
lambda value, mu, alpha: sp.invgauss.logpdf(value, mu=mu, loc=alpha),
980+
decimal=select_by_precision(float64=6, float32=1),
981+
)
982+
983+
@pytest.mark.xfail(
984+
condition=(aesara.config.floatX == "float32"),
985+
reason="Poor CDF in SciPy. See scipy/scipy#869 for details.",
986+
)
987+
def test_wald_logcdf(self):
988+
self.check_logcdf(
989+
Wald,
990+
Rplus,
991+
{"mu": Rplus, "alpha": Rplus},
992+
lambda value, mu, alpha: sp.invgauss.logcdf(value, mu=mu, loc=alpha),
993+
)
994+
992995
def test_beta(self):
993996
self.check_logp(
994997
Beta,
@@ -1256,11 +1259,7 @@ def test_gamma_logcdf(self):
12561259
skip_paramdomain_outside_edge_test=True,
12571260
)
12581261

1259-
@pytest.mark.xfail(
1260-
condition=(aesara.config.floatX == "float32"),
1261-
reason="Fails on float32 due to numerical issues",
1262-
)
1263-
def test_inverse_gamma(self):
1262+
def test_inverse_gamma_logp(self):
12641263
self.check_logp(
12651264
InverseGamma,
12661265
Rplus,
@@ -1269,6 +1268,14 @@ def test_inverse_gamma(self):
12691268
)
12701269
# pymc-devs/aesara#224: skip_paramdomain_outside_edge_test has to be set
12711270
# True to avoid triggering a C-level assertion in the Aesara GammaQ function
1271+
1272+
@pytest.mark.xfail(
1273+
condition=(aesara.config.floatX == "float32"),
1274+
reason="Fails on float32 due to numerical issues",
1275+
)
1276+
def test_inverse_gamma_logcdf(self):
1277+
# pymc-devs/aesara#224: skip_paramdomain_outside_edge_test has to be set
1278+
# True to avoid triggering a C-level assertion in the Aesara GammaQ function
12721279
# in gamma.c file. Can be set back to False (default) once that issue is solved
12731280
self.check_logcdf(
12741281
InverseGamma,
@@ -1313,13 +1320,19 @@ def test_pareto(self):
13131320
condition=(aesara.config.floatX == "float32"),
13141321
reason="Fails on float32 due to inf issues",
13151322
)
1316-
def test_weibull(self):
1323+
def test_weibull_logp(self):
13171324
self.check_logp(
13181325
Weibull,
13191326
Rplus,
13201327
{"alpha": Rplusbig, "beta": Rplusbig},
13211328
lambda value, alpha, beta: sp.exponweib.logpdf(value, 1, alpha, scale=beta),
13221329
)
1330+
1331+
@pytest.mark.xfail(
1332+
condition=(aesara.config.floatX == "float32"),
1333+
reason="Fails on float32 due to inf issues",
1334+
)
1335+
def test_weibull_logcdf(self):
13231336
self.check_logcdf(
13241337
Weibull,
13251338
Rplus,
@@ -1368,27 +1381,37 @@ def test_binomial(self):
13681381

13691382
# Too lazy to propagate decimal parameter through the whole chain of deps
13701383
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
1371-
@pytest.mark.xfail(
1372-
condition=(SCIPY_VERSION < parse("1.4.0")), reason="betabinom is new in Scipy 1.4.0"
1373-
)
1374-
def test_beta_binomial(self):
1384+
def test_beta_binomial_distribution(self):
13751385
self.checkd(
13761386
BetaBinomial,
13771387
Nat,
13781388
{"alpha": Rplus, "beta": Rplus, "n": NatSmall},
13791389
)
1390+
1391+
@pytest.mark.skipif(
1392+
condition=(SCIPY_VERSION < parse("1.4.0")), reason="betabinom is new in Scipy 1.4.0"
1393+
)
1394+
def test_beta_binomial_logp(self):
13801395
self.check_logp(
13811396
BetaBinomial,
13821397
Nat,
13831398
{"alpha": Rplus, "beta": Rplus, "n": NatSmall},
13841399
lambda value, alpha, beta, n: sp.betabinom.logpmf(value, a=alpha, b=beta, n=n),
13851400
)
1401+
1402+
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
1403+
@pytest.mark.skipif(
1404+
condition=(SCIPY_VERSION < parse("1.4.0")), reason="betabinom is new in Scipy 1.4.0"
1405+
)
1406+
def test_beta_binomial_logcdf(self):
13861407
self.check_logcdf(
13871408
BetaBinomial,
13881409
Nat,
13891410
{"alpha": Rplus, "beta": Rplus, "n": NatSmall},
13901411
lambda value, alpha, beta, n: sp.betabinom.logcdf(value, a=alpha, b=beta, n=n),
13911412
)
1413+
1414+
def test_beta_binomial_selfconsistency(self):
13921415
self.check_selfconsistency_discrete_logcdf(
13931416
BetaBinomial,
13941417
Nat,
@@ -1475,27 +1498,37 @@ def test_constantdist(self):
14751498
self.check_logp(Constant, I, {"c": I}, lambda value, c: np.log(c == value))
14761499

14771500
# Too lazy to propagate decimal parameter through the whole chain of deps
1478-
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
1479-
def test_zeroinflatedpoisson(self):
1501+
@pytest.mark.xfail(
1502+
condition=(aesara.config.floatX == "float32"),
1503+
reason="Fails on float32 due to inf issues",
1504+
)
1505+
def test_zeroinflatedpoisson_distribution(self):
14801506
self.checkd(
14811507
ZeroInflatedPoisson,
14821508
Nat,
14831509
{"theta": Rplus, "psi": Unit},
14841510
)
1511+
1512+
def test_zeroinflatedpoisson_logcdf(self):
14851513
self.check_selfconsistency_discrete_logcdf(
14861514
ZeroInflatedPoisson,
14871515
Nat,
14881516
{"theta": Rplus, "psi": Unit},
14891517
)
14901518

14911519
# Too lazy to propagate decimal parameter through the whole chain of deps
1492-
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
1493-
def test_zeroinflatednegativebinomial(self):
1520+
@pytest.mark.xfail(
1521+
condition=(aesara.config.floatX == "float32"),
1522+
reason="Fails on float32 due to inf issues",
1523+
)
1524+
def test_zeroinflatednegativebinomial_distribution(self):
14941525
self.checkd(
14951526
ZeroInflatedNegativeBinomial,
14961527
Nat,
14971528
{"mu": Rplusbig, "alpha": Rplusbig, "psi": Unit},
14981529
)
1530+
1531+
def test_zeroinflatednegativebinomial_logcdf(self):
14991532
self.check_selfconsistency_discrete_logcdf(
15001533
ZeroInflatedNegativeBinomial,
15011534
Nat,
@@ -1504,13 +1537,14 @@ def test_zeroinflatednegativebinomial(self):
15041537
)
15051538

15061539
# Too lazy to propagate decimal parameter through the whole chain of deps
1507-
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
1508-
def test_zeroinflatedbinomial(self):
1540+
def test_zeroinflatedbinomial_distribution(self):
15091541
self.checkd(
15101542
ZeroInflatedBinomial,
15111543
Nat,
15121544
{"n": NatSmall, "p": Unit, "psi": Unit},
15131545
)
1546+
1547+
def test_zeroinflatedbinomial_logcdf(self):
15141548
self.check_selfconsistency_discrete_logcdf(
15151549
ZeroInflatedBinomial,
15161550
Nat,
@@ -2279,14 +2313,21 @@ def test_rice(self):
22792313
lambda value, b, sigma: sp.rice.logpdf(value, b=b, loc=0, scale=sigma),
22802314
)
22812315

2282-
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
2283-
def test_moyal(self):
2316+
def test_moyal_logp(self):
2317+
# Using a custom domain, because the standard `R` domain undeflows with scipy in float64
2318+
value_domain = Domain([-inf, -1.5, -1, -0.01, 0.0, 0.01, 1, 1.5, inf])
22842319
self.check_logp(
22852320
Moyal,
2286-
R,
2321+
value_domain,
22872322
{"mu": R, "sigma": Rplusbig},
22882323
lambda value, mu, sigma: floatX(sp.moyal.logpdf(value, mu, sigma)),
22892324
)
2325+
2326+
@pytest.mark.xfail(
2327+
condition=(aesara.config.floatX == "float32"),
2328+
reason="Pymc3 underflows earlier than scipy on float32",
2329+
)
2330+
def test_moyal_logcdf(self):
22902331
self.check_logcdf(
22912332
Moyal,
22922333
R,

pymc3/tests/test_examples.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ def build_disaster_model(masked=False):
192192
return model
193193

194194

195-
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
196195
class TestDisasterModel(SeededTest):
196+
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
197197
# Time series of recorded coal mining disasters in the UK from 1851 to 1962
198198
def test_disaster_model(self):
199199
model = build_disaster_model(masked=False)
@@ -205,6 +205,7 @@ def test_disaster_model(self):
205205
tr = pm.sample(500, tune=50, start=start, step=step, chains=2)
206206
az.summary(tr)
207207

208+
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
208209
def test_disaster_model_missing(self):
209210
model = build_disaster_model(masked=True)
210211
with model:

pymc3/tests/test_models_utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def test_pandas_init(self):
4040
m, l = utils.any_to_tensor_and_labels(self.data, labels=["x2", "x3"])
4141
self.assertMatrixLabels(m, l, lt=["x2", "x3"])
4242

43-
@pytest.mark.xfail
4443
def test_dict_input(self):
4544
m, l = utils.any_to_tensor_and_labels(self.data.to_dict("dict"))
4645
self.assertMatrixLabels(m, l, mt=self.data[l].values, lt=l)
@@ -51,6 +50,8 @@ def test_dict_input(self):
5150
m, l = utils.any_to_tensor_and_labels(self.data.to_dict("list"))
5251
self.assertMatrixLabels(m, l, mt=self.data[l].values, lt=l)
5352

53+
@pytest.mark.xfail
54+
def test_dict_input_pandas_series(self):
5455
inp = {k: aet.as_tensor_variable(v.values) for k, v in self.data.to_dict("series").items()}
5556
m, l = utils.any_to_tensor_and_labels(inp)
5657
self.assertMatrixLabels(m, l, mt=self.data[l].values, lt=l)

pymc3/tests/test_step.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -957,8 +957,8 @@ def test_custom_proposal_dist(self):
957957
pass
958958

959959

960-
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
961960
class TestNutsCheckTrace:
961+
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
962962
def test_multiple_samplers(self, caplog):
963963
with Model():
964964
prob = Beta("prob", alpha=5.0, beta=3.0)

pymc3/tests/test_transforms.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,22 @@ def test_ordered():
235235
close_to_logical(np.diff(vals) >= 0, True, tol)
236236

237237

238+
def test_chain_values():
239+
chain_tranf = tr.Chain([tr.logodds, tr.ordered])
240+
vals = get_values(chain_tranf, Vector(R, 5), aet.dvector, np.zeros(5))
241+
close_to_logical(np.diff(vals) >= 0, True, tol)
242+
243+
238244
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
239-
def test_chain():
245+
def test_chain_vector_transform():
240246
chain_tranf = tr.Chain([tr.logodds, tr.ordered])
241247
check_vector_transform(chain_tranf, UnitSortedVector(3))
242248

243-
check_jacobian_det(chain_tranf, Vector(R, 4), aet.dvector, np.zeros(4), elemwise=False)
244249

245-
vals = get_values(chain_tranf, Vector(R, 5), aet.dvector, np.zeros(5))
246-
close_to_logical(np.diff(vals) >= 0, True, tol)
250+
@pytest.mark.xfail(condition=(aesara.config.floatX == "float32"), reason="Fails on float32")
251+
def test_chain_jacob_det():
252+
chain_tranf = tr.Chain([tr.logodds, tr.ordered])
253+
check_jacobian_det(chain_tranf, Vector(R, 4), aet.dvector, np.zeros(4), elemwise=False)
247254

248255

249256
class TestElementWiseLogp(SeededTest):

0 commit comments

Comments
 (0)