diff --git a/bson.py b/bson.py index 5f358edc2..8c861ef1d 100644 --- a/bson.py +++ b/bson.py @@ -8,7 +8,7 @@ import struct import random import re -from test import test_data +from test import test_data, qcheck class InvalidBSON(ValueError): """Raised when trying to create a BSON object from invalid data. @@ -328,17 +328,7 @@ class TestBSON(unittest.TestCase): self.assertTrue(is_valid(data)) def test_random_data_is_not_bson(self): - def random_char(size): - return chr(random.randint(0, 255)) - - def random_string(size): - return "".join(random_list(random_char)(size)) - - def random_list(generator): - return lambda size: [generator(size) for _ in range(size)] - - for i in range(100): - self.assertFalse(is_valid(random_string(i))) + qcheck.check_unittest(self, qcheck.isnt(is_valid), qcheck.gen_string(qcheck.gen_range(0, 40))) def test_basic_from_dict(self): self.assertRaises(TypeError, BSON.from_dict, 100) diff --git a/test/qcheck.py b/test/qcheck.py new file mode 100644 index 000000000..0145143f8 --- /dev/null +++ b/test/qcheck.py @@ -0,0 +1,39 @@ +import random + +gen_target = 100 +examples = 5 + +def gen_range(start, stop): + return lambda: random.randint(start, stop) + +def char(): + return chr(random.randint(0, 255)) + +def gen_string(gen_length): + return lambda: "".join(gen_list(char, gen_length)) + +def gen_list(generator, length): + return [generator() for _ in range(length())] + + +def isnt(predicate): + return lambda x: not predicate(x) + + +def check(predicate, generator): + counter_examples = [] + for i in range(gen_target): + case = generator() + if not predicate(case): + counter_examples.append(repr(case)) + return counter_examples + +def check_unittest(test, predicate, generator): + counter_examples = check(predicate, generator) + if counter_examples: + failures = len(counter_examples) + message = "\n".join([" -> %s" % f for f in counter_examples[:examples]]) + message = "found %d counter examples, displaying first %d:\n%s" % (failures, + min(failures, examples), + message) + test.fail(message)