Regression tests


In [1]:
import tohu
from tohu import *
from utils import print_generated_sequence

In [2]:
print(f"Tohu version: {tohu.__version__}")


Tohu version: v0.5.0+105.g2cc7248.dirty

Resetting one generator should not reset others of the same type

Let's create two generators of the same type.


In [3]:
class FoobarGenerator(CustomGenerator):
    a = Integer(low=1000, high=3000)
    b = Sequential(prefix="Foo_", digits=2)
    c = Float(low=1.0, high=4.0)

In [4]:
g1 = FoobarGenerator()
g2 = FoobarGenerator()

The random generators which produce the attributes of items generated by g1 and g2 must be independent of each other. This regression test checks this by making sure that g1.reset() does not interfere with g2.reset(). In particular, the two outputs below should be identical (because the final call g1.reset(12345) should not interfere with the previous call g2.reset(9999)).


In [5]:
g1.reset(seed=12345)
g2.reset(seed=9999)
print_generated_sequence(g1, num=3, sep='\n')
print_generated_sequence(g2, num=3, sep='\n')

print("-------------------------------------------------")

g1.reset(seed=12345)
g2.reset(seed=9999)
g1.reset(seed=12345)
print_generated_sequence(g1, num=3, sep='\n')
print_generated_sequence(g2, num=3, sep='\n')


Generated sequence:
Foobar(a=1045, b='Foo_01', c=3.981821390172517)
Foobar(a=2036, b='Foo_02', c=3.1203779928265845)
Foobar(a=2683, b='Foo_03', c=2.1856939785831426)
Generated sequence:
Foobar(a=1569, b='Foo_01', c=1.9575884431178854)
Foobar(a=1177, b='Foo_02', c=1.2926182380299613)
Foobar(a=1952, b='Foo_03', c=1.0735376232596)
-------------------------------------------------
Generated sequence:
Foobar(a=1045, b='Foo_01', c=3.981821390172517)
Foobar(a=2036, b='Foo_02', c=3.1203779928265845)
Foobar(a=2683, b='Foo_03', c=2.1856939785831426)
Generated sequence:
Foobar(a=1569, b='Foo_01', c=1.9575884431178854)
Foobar(a=1177, b='Foo_02', c=1.2926182380299613)
Foobar(a=1952, b='Foo_03', c=1.0735376232596)

Sub-generators of custom generator should be initialised with separate seeds

Each custom generator can be re-initialised using a given seed. Internally, this re-initialises each of the constituent generators. This test checks that different seeds are used for each of the individual generators, even if they are of the same type (otherwise the values produced for each attribute would be the same). In particular, the sequences produced for a1, a2, a3 below should be different (and similarly for (b1, b2, b3).


In [6]:
class FoobarGenerator(CustomGenerator):
    a1 = HashDigest(length=8)
    a2 = HashDigest(length=8)
    a3 = HashDigest(length=8)
    
    b1 = Integer(low=0, high=1000)
    b2 = Integer(low=0, high=1000)
    b3 = Integer(low=0, high=1000)

In [7]:
g = FoobarGenerator()

In [8]:
g.reset(seed=99999)
print_generated_sequence(g, num=10, sep='\n')


Generated sequence:
Foobar(a1='A146C763', a2='550617D4', a3='AFD21424', b1=528, b2=920, b3=680)
Foobar(a1='B76B3878', a2='61EC7221', a3='4240C882', b1=593, b2=664, b3=789)
Foobar(a1='B04AFF7A', a2='B5FB5E55', a3='25DA8E7D', b1=498, b2=749, b3=722)
Foobar(a1='563A075E', a2='539FF2E9', a3='A6EB1F61', b1=860, b2=888, b3=131)
Foobar(a1='F83A44C7', a2='4668DCF9', a3='A4954A36', b1=726, b2=752, b3=839)
Foobar(a1='8C549486', a2='1DDAB699', a3='EB82C079', b1=558, b2=934, b3=179)
Foobar(a1='0E887F50', a2='CBAAAFF0', a3='A05D4BB2', b1=391, b2=327, b3=132)
Foobar(a1='2EF9CDCB', a2='82509560', a3='B32010DA', b1=222, b2=215, b3=912)
Foobar(a1='C295D37C', a2='15EEFF82', a3='5961A909', b1=356, b2=341, b3=474)
Foobar(a1='9565BCCD', a2='104D7BB8', a3='A11CC345', b1=354, b2=16, b3=692)

NumpyRandomGenerator

This is a quick sanity check that resetting a NumpyRandomGenerator really fully resets the state and leads to independent runs.


In [9]:
g = NumpyRandomGenerator(method="normal", loc=3.0, scale=5.0)
g.reset(seed=12345); print_generated_sequence(g, num=4)
g.reset(seed=99999); print_generated_sequence(g, num=4)


Generated sequence: 1.9764617025764353, 5.394716690287741, 0.40280642471630923, 0.22134847826254989
Generated sequence: 6.120470228691696, 9.374815429760194, -5.298018043341111, 5.539749427572133

In [10]:
g1 = NumpyRandomGenerator(method="normal", loc=3.0, scale=5.0)
g2 = NumpyRandomGenerator(method="normal", loc=3.0, scale=5.0)
g1.reset(seed=12345)
g2.reset(seed=99999)
print_generated_sequence(g1, num=4)
print_generated_sequence(g2, num=4)


Generated sequence: 1.9764617025764353, 5.394716690287741, 0.40280642471630923, 0.22134847826254989
Generated sequence: 6.120470228691696, 9.374815429760194, -5.298018043341111, 5.539749427572133

Zip should use different seeds internally to reset its input generators


In [11]:
g1 = Integer(0, 100)
g2 = Integer(0, 100)
g1.reset(12345)
g2.reset(12345)

print_generated_sequence(g1, num=10)
print_generated_sequence(g2, num=10)


Generated sequence: 53, 93, 1, 38, 47, 24, 34, 72, 55, 20
Generated sequence: 53, 93, 1, 38, 47, 24, 34, 72, 55, 20

In [12]:
z = Zip(g1, g2)
h1, h2 = Split(z)

If .reset() is called on a Zip generator, it should use different seeds internally to reset each of its constituent input generators. In particular, the output of h1 and h2 below should be different.


In [13]:
z.reset(seed=12345)
print_generated_sequence(h1, num=10)
print_generated_sequence(h2, num=10)


Generated sequence: 2, 64, 18, 85, 82, 24, 49, 58, 0, 60
Generated sequence: 55, 24, 17, 70, 18, 56, 58, 17, 84, 77

Multiple FakerGenerator instances should be independent


In [14]:
g1 = FakerGenerator(method="name")
g2 = FakerGenerator(method="name")
g1.reset(seed=12345)
g2.reset(seed=12345)

print_generated_sequence(g1, num=5)
print_generated_sequence(g2, num=5)


Generated sequence: Adam Bryan, Jacob Lee, Candice Martinez, Justin Thompson, Heather Rubio
Generated sequence: Adam Bryan, Jacob Lee, Candice Martinez, Justin Thompson, Heather Rubio

In [ ]: