def test_bact_death_z_test(set_params): """ This test is a probabilistic test: It executes dies() N times. The number n of "successes" (dies() returns True) should be distributed according to the binomial distribution B(N, p), where p is short for p_death. For large N, the distribution is approximately normal (law of large numbers) with mean Np and variance Np(1-p). Then, Z = ( n - Np ) / sqrt( N p (1-p) ) is distributed according to the normal distribution with mean 0 and variance 1. Thus, if dies() works correctly, we will observe Z < -Z* or Z > Z* only with probability Phi(-Z*) + ( 1-Phi(Z*) ) = 2 * Phi(-Z*), where equality follows from the symmetry of the normal distribution. This is the probability mass in the tails of the distribution. We can choose a signficance level alpha, e.g. 0.01, and pass the test if 2*Phi(-|Z|) > alpha: The test passes if the probability mass outside (-|Z], |Z]) is at least alpha (the observed value of Z is not in the alpha-tail of the distribution). """ random.seed(SEED) N = 100 p = Bacteria.get_params()['p_death'] # obtain parameter set by fixture b = Bacteria() n = sum(b.dies() for _ in range(N)) # True == 1, False == 0 mean = N * p var = N * p * (1 - p) Z = (n - mean) / math.sqrt(var) phi = 2 * stats.norm.cdf(-abs(Z)) assert phi > ALPHA
def test_death(n_a, n_b, p_death): Bacteria.set_params({'p_death': p_death}) dish = Dish(n_a, n_b) dish.death() died_a = n_a - dish.get_num_a() died_b = n_b - dish.get_num_b() Bacteria.set_params(Bacteria.default_params) assert binom_test(died_a, n_a, p_death) > ALPHA assert binom_test(died_b, n_b, p_death) > ALPHA
def test_bact_certain_survival(set_params): """ This test is *deterministic*: We set death probability to 0, thus the bacterium must never die. We call dies() multiple times to test this. """ b = Bacteria() for _ in range(100): assert not b.dies()
def test_bact_aging(): """ This test is *determinstic*: for each call to ages(), the age must increase by one year. """ b = Bacteria() for n in range(10): b.ages() assert b.age == n + 1
def test_death(self, reset_bacteria_defaults, p_death): Bacteria.set_params({'p_death': p_death}) n_a0 = self.dish.get_num_a() n_b0 = self.dish.get_num_b() self.dish.death() died_a = n_a0 - self.dish.get_num_a() died_b = n_b0 - self.dish.get_num_b() assert binom_test(died_a, n_a0, p_death) > ALPHA assert binom_test(died_b, n_b0, p_death) > ALPHA
def test_bact_certain_death(set_params): """ This test is *deterministic*: We set death probability to 1, thus the bacterium must always die. We call dies() multiple times to test this. Paramterization with a single-element list of parameter values will run this test once. Because we set `indirect=True`, Pytest will first invoke the set_params fixture defined above, passing the dictionary `{'p_death': 1.0}` as `request.param` to the fixture. The fixture then calls `Bacteria.set_params()` and also ensures clean-up after the test. """ b = Bacteria() for _ in range(100): assert b.dies()
def set_params(request): """ Fixture setting class parameters on Bacteria. The fixture sets Bacteria parameters when called for setup, and resets them when called for teardown. This ensures that modified parameters are always reset before leaving a test. This fixture should be called via parametrize with indirect=True. Based on https://stackoverflow.com/a/33879151 Parameters ---------- request Request object automatically provided by pytest. request.param is the parameter dictionary to be passed to Bacteria.set_params() """ Bacteria.set_params(request.param) yield Bacteria.set_params(Bacteria.default_params)
def p_death_one(self): # set death probability to 1 before test (setup) Bacteria.set_params({'p_death': 1}) yield # code after yield executed after test (teardown) Bacteria.set_params(Bacteria.default_params)
def reset_bacteria_defaults(self): # no setup yield # reset class parameters to default values after each test Bacteria.set_params(Bacteria.default_params)
def test_all_die(self, reset_bacteria_defaults): Bacteria.set_params({'p_death': 1.0}) self.dish.death() assert self.dish.get_num_a() == 0 assert self.dish.get_num_b() == 0
def test_bact_create(): """ Test that a new bacterium has age 0. """ b = Bacteria() assert b.age == 0