def __call__(self, specifier, settings=None): from hypothesis.searchstrategy.strategies import SearchStrategy if isinstance(specifier, SearchStrategy): return specifier self.load_deprecated_api() if settings is None: settings = Settings() try: result = super(StrategyExtMethod, self).__call__( specifier, settings) except NotImplementedError: quiet_raise(NotImplementedError(( 'Expected a SearchStrategy but got %r of type %s. ' 'Note: This is a NotImplementedError for legacy reasons and ' 'will become an InvalidArgumentError in Hypothesis 2.0.' ) % (specifier, type(specifier).__name__))) note_deprecation(( 'Conversion of %r to strategy is deprecated ' 'and will be removed in Hypothesis 2.0. Use %r instead.') % ( specifier, result ), settings) assert isinstance(result, SearchStrategy) return result
def basic( basic=None, generate_parameter=None, generate=None, simplify=None, copy=None ): """Provides a facility to write your own strategies with significantly less work. See documentation for more details. """ note_deprecation( 'basic() is deprecated as Hypothesis will be moving to a new ' 'model that cannot support it. There is probably no one-size fits all ' 'replacement solution here. If you can\'t figure out a good ' 'solution, please ask.' ) from hypothesis.searchstrategy.basic import basic_strategy, BasicStrategy from copy import deepcopy if basic is not None: if isinstance(basic, type): basic = basic() check_type(BasicStrategy, basic) generate_parameter = generate_parameter or basic.generate_parameter generate = generate or basic.generate simplify = simplify or basic.simplify copy = copy or basic.copy return basic_strategy( parameter=generate_parameter, generate=generate, simplify=simplify, copy=copy or deepcopy )
def strategy(spec, settings=None): from hypothesis.settings import note_deprecation note_deprecation( 'The strategy function is deprecated and will be removed in Hypothesis' ' 2.0. Please use the hypothesis.strategies module to construct your ' 'strategies', settings) return _strategy(spec, settings)
def unicode_safe_repr(x): try: r = repr(x) except UnicodeEncodeError: r = type(x).__repr__(x) from hypothesis.settings import note_deprecation note_deprecation( ('Type %s has a broken repr implementation. Calling __repr__ ' 'on it returned %r, which cannot be represented as ASCII ' 'text. This is not permitted in Python 2. Hypothesis is ' 'currently working around this, but will stop doing so in ' 'Hypothesis 2.0. You should fix your code.') % (type(x).__name__, r)) if isinstance(r, unicode): return r else: return r.decode(a_good_encoding())
def __call__(self, specifier, settings=None): if isinstance(specifier, SearchStrategy): return specifier if settings is None: settings = Settings() note_deprecation(( u'Calling strategy with non-strategy object %s is deprecated ' u'and will be removed in Hypothesis 2.0. Use the functions in ' u'hypothesis.strategies instead.') % ( repr(specifier), ), settings) result = super(StrategyExtMethod, self).__call__(specifier, settings) assert isinstance(result, SearchStrategy) return result
def __call__(self, specifier, settings=None): from hypothesis.searchstrategy.strategies import SearchStrategy if isinstance(specifier, SearchStrategy): return specifier self.load_deprecated_api() if settings is None: settings = Settings() result = super(StrategyExtMethod, self).__call__(specifier, settings) note_deprecation( ('Conversion of %r to strategy is deprecated ' 'and will be removed in Hypothesis 2.0. Use %r instead.') % (specifier, result), settings) assert isinstance(result, SearchStrategy) return result
def accept(f): parent_rule = getattr(f, RULE_MARKER, None) if parent_rule is not None: note_deprecation( 'Applying the rule decorator to a function that is already ' 'decorated by rule is deprecated. Please assign the result ' 'of the rule function to separate names in your class.', Settings.default, ) precondition = getattr(f, PRECONDITION_MARKER, None) rule = Rule(targets=tuple(converted_targets), arguments=kwargs, function=f, precondition=precondition, parent_rule=parent_rule) @proxies(f) def rule_wrapper(*args, **kwargs): return f(*args, **kwargs) setattr(rule_wrapper, RULE_MARKER, rule) return rule_wrapper
def __call__(self, specifier, settings=None): from hypothesis.searchstrategy.strategies import SearchStrategy if isinstance(specifier, SearchStrategy): return specifier self.load_deprecated_api() if settings is None: settings = Settings() result = super(StrategyExtMethod, self).__call__(specifier, settings) note_deprecation(( 'Conversion of %r to strategy is deprecated ' 'and will be removed in Hypothesis 2.0. Use %r instead.') % ( specifier, result ), settings) assert isinstance(result, SearchStrategy) return result
def unicode_safe_repr(x): try: r = repr(x) except UnicodeEncodeError: r = type(x).__repr__(x) from hypothesis.settings import note_deprecation note_deprecation( ( "Type %s has a broken repr implementation. Calling __repr__ " "on it returned %r, which cannot be represented as ASCII " "text. This is not permitted in Python 2. Hypothesis is " "currently working around this, but will stop doing so in " "Hypothesis 2.0. You should fix your code." ) % (type(x).__name__, r) ) if isinstance(r, unicode): return r else: return r.decode(a_good_encoding())
def load_entry_points(name=None): for entry_point in pkg_resources.iter_entry_points( group=u('hypothesis.extra'), name=name ): if entry_point.name in ( u('hypothesisdatetime'), u('hypothesisdjango'), u('hypothesisfakefactory'), u('hypothesisnumpy') ): base_name = entry_point.name.replace(u('hypothesis'), u('')) note_deprecation( u('Ignoring obsolete extra package hypothesis-%s. This ' 'functionality is now included in hypothesis core. You ' 'should uninstall the extra package.') % (base_name,), Settings.default ) continue elif entry_point.name == u('hypothesispytest'): note_deprecation( u('You have an obsolete version of the hypothesis-pytest ' 'plugin installed. Please update to a more recent version.'), Settings.default ) continue else: note_deprecation( u('The extra package mechanism is deprecated and will go away ') "in Hypothesis 2.0. Just write a normal package and don't " 'have it in the Hypothesis namespace.'), Settings.default ) package = entry_point.load() # pragma: no cover if package not in loaded: loaded.add(package) __path__.extend(package.__path__) package.load()
def is_template_example(xs): if perform_health_check and not warned_random[0]: initial_state = getglobalrandomstate() record_repr = [None] try: result = test_runner(reify_and_execute( search_strategy, xs, test, record_repr=record_repr, )) if result is not None: note_deprecation(( 'Tests run under @given should return None, but ' '%s returned %r instead.' 'In Hypothesis 2.0 this will become an error.' ) % (test.__name__, result), settings) return False except HypothesisDeprecationWarning: raise except UnsatisfiedAssumption as e: raise e except Exception as e: last_exception[0] = traceback.format_exc() repr_for_last_exception[0] = record_repr[0] verbose_report(last_exception[0]) return True finally: if ( not warned_random[0] and perform_health_check and getglobalrandomstate() != initial_state ): warned_random[0] = True fail_health_check( 'Your test used the global random module. ' 'This is unlikely to work correctly. You should ' 'consider using the randoms() strategy from ' 'hypothesis.strategies instead. Alternatively, ' 'you can use the random_module() strategy to ' 'explicitly seed the random module.' )
def is_template_example(xs): if perform_health_check and not warned_random[0]: initial_state = getglobalrandomstate() record_repr = [None] try: result = test_runner( reify_and_execute( search_strategy, xs, test, record_repr=record_repr, )) if result is not None: note_deprecation( ('Tests run under @given should return None, but ' '%s returned %r instead.' 'In Hypothesis 2.0 this will become an error.') % (test.__name__, result), settings) return False except HypothesisDeprecationWarning: raise except UnsatisfiedAssumption as e: raise e except Exception as e: last_exception[0] = traceback.format_exc() repr_for_last_exception[0] = record_repr[0] verbose_report(last_exception[0]) return True finally: if (not warned_random[0] and perform_health_check and getglobalrandomstate() != initial_state): warned_random[0] = True fail_health_check( 'Your test used the global random module. ' 'This is unlikely to work correctly. You should ' 'consider using the randoms() strategy from ' 'hypothesis.strategies instead. Alternatively, ' 'you can use the random_module() strategy to ' 'explicitly seed the random module.')
def wrapped_test(*arguments, **kwargs): if settings.derandomize: random = Random(function_digest(test)) else: random = provided_random or new_random() import hypothesis.strategies as sd from hypothesis.internal.strategymethod import strategy selfy = None arguments, kwargs = convert_positional_arguments( wrapped_test, arguments, kwargs) for arg in hypothesis_owned_arguments: try: value = kwargs[arg] except KeyError: continue if not isinstance(value, HypothesisProvided): note_deprecation( 'Passing in explicit values to override Hypothesis ' 'provided values is deprecated and will no longer ' 'work in Hypothesis 2.0. If you need to do this, ' 'extract a common function and call that from a ' 'Hypothesis based test.', settings) # Anything in unused_kwargs hasn't been injected through # argspec.defaults, so we need to add them. for k in unused_kwargs: if k not in kwargs: kwargs[k] = unused_kwargs[k] # If the test function is a method of some kind, the bound object # will be the first named argument if there are any, otherwise the # first vararg (if any). if argspec.args: selfy = kwargs.get(argspec.args[0]) elif arguments: selfy = arguments[0] if isinstance(selfy, HypothesisProvided): selfy = None test_runner = executor(selfy) for example in reversed( getattr(wrapped_test, u'hypothesis_explicit_examples', ())): if example.args: example_kwargs = dict( zip(argspec.args[-len(example.args):], example.args)) else: example_kwargs = dict(example.kwargs) for k, v in kwargs.items(): if not isinstance(v, HypothesisProvided): example_kwargs[k] = v # Note: Test may mutate arguments and we can't rerun explicit # examples, so we have to calculate the failure message at this # point rather than than later. message_on_failure = u'Falsifying example: %s(%s)' % ( test.__name__, arg_string(test, arguments, example_kwargs)) try: with BuildContext() as b: test_runner(lambda: test(*arguments, **example_kwargs)) except BaseException: report(message_on_failure) for n in b.notes: report(n) raise if not any( isinstance(x, HypothesisProvided) for xs in (arguments, kwargs.values()) for x in xs): # All arguments have been satisfied without needing to invoke # hypothesis test_runner(lambda: test(*arguments, **kwargs)) return def convert_to_specifier(v): if isinstance(v, HypothesisProvided): return strategy(v.value, settings) else: return sd.just(v) given_specifier = sd.tuples( sd.tuples(*map(convert_to_specifier, arguments)), sd.fixed_dictionaries( dict((k, convert_to_specifier(v)) for (k, v) in kwargs.items()))) def fail_health_check(message): message += ( '\nSee http://hypothesis.readthedocs.org/en/latest/health' 'checks.html for more information about this.') if settings.strict: raise FailedHealthCheck(message) else: warnings.warn(FailedHealthCheck(message)) search_strategy = strategy(given_specifier, settings) search_strategy.validate() if settings.database: storage = settings.database.storage(fully_qualified_name(test)) else: storage = None start = time.time() warned_random = [False] perform_health_check = settings.perform_health_check if Settings.default is not None: perform_health_check &= Settings.default.perform_health_check if perform_health_check: initial_state = getglobalrandomstate() health_check_random = Random(random.getrandbits(128)) count = 0 bad_draws = 0 filtered_draws = 0 errors = 0 while (count < 10 and time.time() < start + 1 and filtered_draws < 50 and bad_draws < 50): try: with Settings(settings, verbosity=Verbosity.quiet): test_runner( reify_and_execute( search_strategy, search_strategy.draw_template( health_check_random, search_strategy.draw_parameter( health_check_random, )), lambda *args, **kwargs: None, )) count += 1 except BadTemplateDraw: bad_draws += 1 except UnsatisfiedAssumption: filtered_draws += 1 except Exception: if errors == 0: report(traceback.format_exc()) errors += 1 if test_runner is default_executor: fail_health_check( 'An exception occurred during data ' 'generation in initial health check. ' 'This indicates a bug in the strategy. ' 'This could either be a Hypothesis bug or ' "an error in a function you've passed to " 'it to construct your data.') else: fail_health_check( 'An exception occurred during data ' 'generation in initial health check. ' 'This indicates a bug in the strategy. ' 'This could either be a Hypothesis bug or ' 'an error in a function you\'ve passed to ' 'it to construct your data. Additionally, ' 'you have a custom executor, which means ' 'that this could be your executor failing ' 'to handle a function which returns None. ') if filtered_draws >= 50: fail_health_check(( 'It looks like your strategy is filtering out a lot ' 'of data. Health check found %d filtered examples but ' 'only %d good ones. This will make your tests much ' 'slower, and also will probably distort the data ' 'generation quite a lot. You should adapt your ' 'strategy to filter less.') % (filtered_draws, count)) if bad_draws >= 50: fail_health_check( 'Hypothesis is struggling to generate examples. ' 'This is often a sign of a recursive strategy which ' 'fans out too broadly. If you\'re using recursive, ' 'try to reduce the size of the recursive step or ' 'increase the maximum permitted number of leaves.') runtime = time.time() - start if runtime > 1.0 or count < 10: fail_health_check( ('Data generation is extremely slow: Only produced ' '%d valid examples in %.2f seconds. Try decreasing ' "size of the data you're generating (with e.g." 'average_size or max_leaves parameters).') % (count, runtime)) if getglobalrandomstate() != initial_state: warned_random[0] = True fail_health_check( 'Data generation depends on global random module. ' 'This makes results impossible to replay, which ' 'prevents Hypothesis from working correctly. ' 'If you want to use methods from random, use ' 'randoms() from hypothesis.strategies to get an ' 'instance of Random you can use. Alternatively, you ' 'can use the random_module() strategy to explicitly ' 'seed the random module.') last_exception = [None] repr_for_last_exception = [None] def is_template_example(xs): if perform_health_check and not warned_random[0]: initial_state = getglobalrandomstate() record_repr = [None] try: result = test_runner( reify_and_execute( search_strategy, xs, test, record_repr=record_repr, )) if result is not None: note_deprecation( ('Tests run under @given should return None, but ' '%s returned %r instead.' 'In Hypothesis 2.0 this will become an error.') % (test.__name__, result), settings) return False except HypothesisDeprecationWarning: raise except UnsatisfiedAssumption as e: raise e except Exception as e: last_exception[0] = traceback.format_exc() repr_for_last_exception[0] = record_repr[0] verbose_report(last_exception[0]) return True finally: if (not warned_random[0] and perform_health_check and getglobalrandomstate() != initial_state): warned_random[0] = True fail_health_check( 'Your test used the global random module. ' 'This is unlikely to work correctly. You should ' 'consider using the randoms() strategy from ' 'hypothesis.strategies instead. Alternatively, ' 'you can use the random_module() strategy to ' 'explicitly seed the random module.') is_template_example.__name__ = test.__name__ is_template_example.__qualname__ = qualname(test) falsifying_template = None try: falsifying_template = best_satisfying_template( search_strategy, random, is_template_example, settings, storage, start_time=start, ) except NoSuchExample: return assert last_exception[0] is not None with settings: test_runner( reify_and_execute(search_strategy, falsifying_template, test, print_example=True, is_final=True)) report( u'Failed to reproduce exception. Expected: \n' + last_exception[0], ) test_runner( reify_and_execute(search_strategy, falsifying_template, test_is_flaky( test, repr_for_last_exception[0]), print_example=True, is_final=True))
def wrapped_test(*arguments, **kwargs): if settings.derandomize: random = Random(function_digest(test)) else: random = provided_random or new_random() import hypothesis.strategies as sd from hypothesis.internal.strategymethod import strategy selfy = None arguments, kwargs = convert_positional_arguments( wrapped_test, arguments, kwargs) for arg in hypothesis_owned_arguments: try: value = kwargs[arg] except KeyError: continue if not isinstance(value, HypothesisProvided): note_deprecation( 'Passing in explicit values to override Hypothesis ' 'provided values is deprecated and will no longer ' 'work in Hypothesis 2.0. If you need to do this, ' 'extract a common function and call that from a ' 'Hypothesis based test.', settings ) # Anything in unused_kwargs hasn't been injected through # argspec.defaults, so we need to add them. for k in unused_kwargs: if k not in kwargs: kwargs[k] = unused_kwargs[k] # If the test function is a method of some kind, the bound object # will be the first named argument if there are any, otherwise the # first vararg (if any). if argspec.args: selfy = kwargs.get(argspec.args[0]) elif arguments: selfy = arguments[0] if isinstance(selfy, HypothesisProvided): selfy = None test_runner = executor(selfy) for example in reversed(getattr( wrapped_test, u'hypothesis_explicit_examples', () )): if example.args: example_kwargs = dict(zip( argspec.args[-len(example.args):], example.args )) else: example_kwargs = dict(example.kwargs) for k, v in kwargs.items(): if not isinstance(v, HypothesisProvided): example_kwargs[k] = v # Note: Test may mutate arguments and we can't rerun explicit # examples, so we have to calculate the failure message at this # point rather than than later. message_on_failure = u'Falsifying example: %s(%s)' % ( test.__name__, arg_string(test, arguments, example_kwargs) ) try: with BuildContext() as b: test_runner( lambda: test(*arguments, **example_kwargs) ) except BaseException: report(message_on_failure) for n in b.notes: report(n) raise if not any( isinstance(x, HypothesisProvided) for xs in (arguments, kwargs.values()) for x in xs ): # All arguments have been satisfied without needing to invoke # hypothesis test_runner(lambda: test(*arguments, **kwargs)) return def convert_to_specifier(v): if isinstance(v, HypothesisProvided): return strategy(v.value, settings) else: return sd.just(v) given_specifier = sd.tuples( sd.tuples(*map(convert_to_specifier, arguments)), sd.fixed_dictionaries(dict( (k, convert_to_specifier(v)) for (k, v) in kwargs.items())) ) def fail_health_check(message): message += ( '\nSee http://hypothesis.readthedocs.org/en/latest/health' 'checks.html for more information about this.' ) if settings.strict: raise FailedHealthCheck(message) else: warnings.warn(FailedHealthCheck(message)) search_strategy = strategy(given_specifier, settings) search_strategy.validate() if settings.database: storage = settings.database.storage( fully_qualified_name(test)) else: storage = None start = time.time() warned_random = [False] perform_health_check = settings.perform_health_check if Settings.default is not None: perform_health_check &= Settings.default.perform_health_check if perform_health_check: initial_state = getglobalrandomstate() health_check_random = Random(random.getrandbits(128)) count = 0 bad_draws = 0 filtered_draws = 0 errors = 0 while ( count < 10 and time.time() < start + 1 and filtered_draws < 50 and bad_draws < 50 ): try: with Settings(settings, verbosity=Verbosity.quiet): test_runner(reify_and_execute( search_strategy, search_strategy.draw_template( health_check_random, search_strategy.draw_parameter( health_check_random, )), lambda *args, **kwargs: None, )) count += 1 except BadTemplateDraw: bad_draws += 1 except UnsatisfiedAssumption: filtered_draws += 1 except Exception: if errors == 0: report(traceback.format_exc()) errors += 1 if test_runner is default_executor: fail_health_check( 'An exception occurred during data ' 'generation in initial health check. ' 'This indicates a bug in the strategy. ' 'This could either be a Hypothesis bug or ' "an error in a function you've passed to " 'it to construct your data.' ) else: fail_health_check( 'An exception occurred during data ' 'generation in initial health check. ' 'This indicates a bug in the strategy. ' 'This could either be a Hypothesis bug or ' 'an error in a function you\'ve passed to ' 'it to construct your data. Additionally, ' 'you have a custom executor, which means ' 'that this could be your executor failing ' 'to handle a function which returns None. ' ) if filtered_draws >= 50: fail_health_check(( 'It looks like your strategy is filtering out a lot ' 'of data. Health check found %d filtered examples but ' 'only %d good ones. This will make your tests much ' 'slower, and also will probably distort the data ' 'generation quite a lot. You should adapt your ' 'strategy to filter less.') % ( filtered_draws, count )) if bad_draws >= 50: fail_health_check( 'Hypothesis is struggling to generate examples. ' 'This is often a sign of a recursive strategy which ' 'fans out too broadly. If you\'re using recursive, ' 'try to reduce the size of the recursive step or ' 'increase the maximum permitted number of leaves.' ) runtime = time.time() - start if runtime > 1.0 or count < 10: fail_health_check(( 'Data generation is extremely slow: Only produced ' '%d valid examples in %.2f seconds. Try decreasing ' "size of the data you're generating (with e.g." 'average_size or max_leaves parameters).' ) % (count, runtime)) if getglobalrandomstate() != initial_state: warned_random[0] = True fail_health_check( 'Data generation depends on global random module. ' 'This makes results impossible to replay, which ' 'prevents Hypothesis from working correctly. ' 'If you want to use methods from random, use ' 'randoms() from hypothesis.strategies to get an ' 'instance of Random you can use. Alternatively, you ' 'can use the random_module() strategy to explicitly ' 'seed the random module.' ) last_exception = [None] repr_for_last_exception = [None] def is_template_example(xs): if perform_health_check and not warned_random[0]: initial_state = getglobalrandomstate() record_repr = [None] try: result = test_runner(reify_and_execute( search_strategy, xs, test, record_repr=record_repr, )) if result is not None: note_deprecation(( 'Tests run under @given should return None, but ' '%s returned %r instead.' 'In Hypothesis 2.0 this will become an error.' ) % (test.__name__, result), settings) return False except HypothesisDeprecationWarning: raise except UnsatisfiedAssumption as e: raise e except Exception as e: last_exception[0] = traceback.format_exc() repr_for_last_exception[0] = record_repr[0] verbose_report(last_exception[0]) return True finally: if ( not warned_random[0] and perform_health_check and getglobalrandomstate() != initial_state ): warned_random[0] = True fail_health_check( 'Your test used the global random module. ' 'This is unlikely to work correctly. You should ' 'consider using the randoms() strategy from ' 'hypothesis.strategies instead. Alternatively, ' 'you can use the random_module() strategy to ' 'explicitly seed the random module.' ) is_template_example.__name__ = test.__name__ is_template_example.__qualname__ = qualname(test) falsifying_template = None try: falsifying_template = best_satisfying_template( search_strategy, random, is_template_example, settings, storage, start_time=start, ) except NoSuchExample: return assert last_exception[0] is not None with settings: test_runner(reify_and_execute( search_strategy, falsifying_template, test, print_example=True, is_final=True )) report( u'Failed to reproduce exception. Expected: \n' + last_exception[0], ) test_runner(reify_and_execute( search_strategy, falsifying_template, test_is_flaky(test, repr_for_last_exception[0]), print_example=True, is_final=True ))
def given(*generator_arguments, **generator_kwargs): """A decorator for turning a test function that accepts arguments into a randomized test. This is the main entry point to Hypothesis. See the full tutorial for details of its behaviour. """ # Keyword only arguments but actually supported in the full range of # pythons Hypothesis handles. pop so we don't later pick these up as # if they were keyword specifiers for data to pass to the test. provided_random = generator_kwargs.pop(u'random', None) settings = generator_kwargs.pop(u'settings', None) or Settings.default if (provided_random is not None) and settings.derandomize: raise InvalidArgument( u'Cannot both be derandomized and provide an explicit random') if not (generator_arguments or generator_kwargs): raise InvalidArgument( u'given must be called with at least one argument') if generator_arguments and generator_kwargs: note_deprecation( u'Mixing positional and keyword arguments in a call to given is ' u'deprecated. Use one or the other.', settings) def run_test_with_generator(test): if settings.derandomize: assert provided_random is None random = Random(function_digest(test)) else: random = provided_random or Random() original_argspec = getargspec(test) if generator_arguments and original_argspec.varargs: raise InvalidArgument( u'varargs are not supported with positional arguments to ' u'@given') extra_kwargs = [ k for k in generator_kwargs if k not in original_argspec.args ] if extra_kwargs and not original_argspec.keywords: raise InvalidArgument( u'%s() got an unexpected keyword argument %r' % (test.__name__, extra_kwargs[0])) if (len(generator_arguments) > len(original_argspec.args)): raise InvalidArgument( (u'Too many positional arguments for %s() (got %d but' u' expected at most %d') % (test.__name__, len(generator_arguments), len(original_argspec.args))) arguments = original_argspec.args specifiers = list(generator_arguments) seen_kwarg = None for a in arguments: if isinstance(a, list): # pragma: no cover raise InvalidArgument( (u'Cannot decorate function %s() because it has ' u'destructuring arguments') % (test.__name__, )) if a in generator_kwargs: seen_kwarg = seen_kwarg or a specifiers.append(generator_kwargs[a]) else: if seen_kwarg is not None: raise InvalidArgument( (u'Argument %s comes after keyword %s which has been ' u'specified, but does not itself have a ' u'specification') % (a, seen_kwarg)) argspec = inspect.ArgSpec(args=arguments, keywords=original_argspec.keywords, varargs=original_argspec.varargs, defaults=tuple( map(HypothesisProvided, specifiers))) unused_kwargs = {} for k in extra_kwargs: unused_kwargs[k] = HypothesisProvided(generator_kwargs[k]) @impersonate(test) @copy_argspec(test.__name__, argspec) def wrapped_test(*arguments, **kwargs): import hypothesis.strategies as sd from hypothesis.internal.strategymethod import strategy selfy = None arguments, kwargs = convert_positional_arguments( wrapped_test, arguments, kwargs) # Anything in unused_kwargs hasn't been injected through # argspec.defaults, so we need to add them. for k in unused_kwargs: if k not in kwargs: kwargs[k] = unused_kwargs[k] # If the test function is a method of some kind, the bound object # will be the first named argument if there are any, otherwise the # first vararg (if any). if argspec.args: selfy = kwargs.get(argspec.args[0]) elif arguments: selfy = arguments[0] if isinstance(selfy, HypothesisProvided): selfy = None test_runner = executor(selfy) for example in getattr(wrapped_test, u'hypothesis_explicit_examples', ()): if example.args: example_kwargs = dict( zip(argspec.args[-len(example.args):], example.args)) else: example_kwargs = dict(example.kwargs) for k, v in kwargs.items(): if not isinstance(v, HypothesisProvided): example_kwargs[k] = v # Note: Test may mutate arguments and we can't rerun explicit # examples, so we have to calculate the failure message at this # point rather than than later. message_on_failure = u'Falsifying example: %s(%s)' % ( test.__name__, arg_string(test, arguments, example_kwargs)) try: test_runner(lambda: test(*arguments, **example_kwargs)) except BaseException: report(message_on_failure) raise if not any( isinstance(x, HypothesisProvided) for xs in (arguments, kwargs.values()) for x in xs): # All arguments have been satisfied without needing to invoke # hypothesis test_runner(lambda: test(*arguments, **kwargs)) return def convert_to_specifier(v): if isinstance(v, HypothesisProvided): return strategy(v.value, settings) else: return sd.just(v) given_specifier = sd.tuples( sd.tuples(*map(convert_to_specifier, arguments)), sd.fixed_dictionaries( dict((k, convert_to_specifier(v)) for (k, v) in kwargs.items()))) search_strategy = strategy(given_specifier, settings) if settings.database: storage = settings.database.storage(fully_qualified_name(test)) else: storage = None last_exception = [None] repr_for_last_exception = [None] def is_template_example(xs): record_repr = [None] try: test_runner( reify_and_execute( search_strategy, xs, test, always_print=settings.max_shrinks <= 0, record_repr=record_repr, )) return False except UnsatisfiedAssumption as e: raise e except Exception as e: if settings.max_shrinks <= 0: raise e last_exception[0] = traceback.format_exc() repr_for_last_exception[0] = record_repr[0] verbose_report(last_exception[0]) return True is_template_example.__name__ = test.__name__ is_template_example.__qualname__ = qualname(test) falsifying_template = None try: falsifying_template = best_satisfying_template( search_strategy, random, is_template_example, settings, storage) except NoSuchExample: return assert last_exception[0] is not None with settings: test_runner( reify_and_execute(search_strategy, falsifying_template, test, print_example=True, is_final=True)) report( u'Failed to reproduce exception. Expected: \n' + last_exception[0], ) test_runner( reify_and_execute(search_strategy, falsifying_template, test_is_flaky( test, repr_for_last_exception[0]), print_example=True, is_final=True)) for attr in dir(test): if attr[0] != '_' and not hasattr(wrapped_test, attr): setattr(wrapped_test, attr, getattr(test, attr)) wrapped_test.is_hypothesis_test = True return wrapped_test return run_test_with_generator
def given(*generator_arguments, **generator_kwargs): """A decorator for turning a test function that accepts arguments into a randomized test. This is the main entry point to Hypothesis. See the full tutorial for details of its behaviour. """ # Keyword only arguments but actually supported in the full range of # pythons Hypothesis handles. pop so we don't later pick these up as # if they were keyword specifiers for data to pass to the test. provided_random = generator_kwargs.pop(u'random', None) settings = generator_kwargs.pop(u'settings', None) or Settings.default if (provided_random is not None) and settings.derandomize: raise InvalidArgument( u'Cannot both be derandomized and provide an explicit random') if not (generator_arguments or generator_kwargs): raise InvalidArgument( u'given must be called with at least one argument') if generator_arguments and generator_kwargs: note_deprecation( u'Mixing positional and keyword arguments in a call to given is ' u'deprecated. Use one or the other.', settings ) def run_test_with_generator(test): if settings.derandomize: assert provided_random is None random = Random(function_digest(test)) else: random = provided_random or Random() original_argspec = getargspec(test) if generator_arguments and original_argspec.varargs: raise InvalidArgument( u'varargs are not supported with positional arguments to ' u'@given' ) extra_kwargs = [ k for k in generator_kwargs if k not in original_argspec.args] if extra_kwargs and not original_argspec.keywords: raise InvalidArgument( u'%s() got an unexpected keyword argument %r' % ( test.__name__, extra_kwargs[0] )) if ( len(generator_arguments) > len(original_argspec.args) ): raise InvalidArgument(( u'Too many positional arguments for %s() (got %d but' u' expected at most %d') % ( test.__name__, len(generator_arguments), len(original_argspec.args))) arguments = original_argspec.args specifiers = list(generator_arguments) seen_kwarg = None for a in arguments: if isinstance(a, list): # pragma: no cover raise InvalidArgument(( u'Cannot decorate function %s() because it has ' u'destructuring arguments') % ( test.__name__, )) if a in generator_kwargs: seen_kwarg = seen_kwarg or a specifiers.append(generator_kwargs[a]) else: if seen_kwarg is not None: raise InvalidArgument(( u'Argument %s comes after keyword %s which has been ' u'specified, but does not itself have a ' u'specification') % ( a, seen_kwarg )) argspec = inspect.ArgSpec( args=arguments, keywords=original_argspec.keywords, varargs=original_argspec.varargs, defaults=tuple(map(HypothesisProvided, specifiers)) ) unused_kwargs = {} for k in extra_kwargs: unused_kwargs[k] = HypothesisProvided(generator_kwargs[k]) @impersonate(test) @copy_argspec( test.__name__, argspec ) def wrapped_test(*arguments, **kwargs): import hypothesis.strategies as sd from hypothesis.internal.strategymethod import strategy selfy = None arguments, kwargs = convert_positional_arguments( wrapped_test, arguments, kwargs) # Anything in unused_kwargs hasn't been injected through # argspec.defaults, so we need to add them. for k in unused_kwargs: if k not in kwargs: kwargs[k] = unused_kwargs[k] # If the test function is a method of some kind, the bound object # will be the first named argument if there are any, otherwise the # first vararg (if any). if argspec.args: selfy = kwargs.get(argspec.args[0]) elif arguments: selfy = arguments[0] if isinstance(selfy, HypothesisProvided): selfy = None test_runner = executor(selfy) for example in getattr( wrapped_test, u'hypothesis_explicit_examples', () ): if example.args: example_kwargs = dict(zip( argspec.args[-len(example.args):], example.args )) else: example_kwargs = dict(example.kwargs) for k, v in kwargs.items(): if not isinstance(v, HypothesisProvided): example_kwargs[k] = v # Note: Test may mutate arguments and we can't rerun explicit # examples, so we have to calculate the failure message at this # point rather than than later. message_on_failure = u'Falsifying example: %s(%s)' % ( test.__name__, arg_string(test, arguments, example_kwargs) ) try: test_runner( lambda: test(*arguments, **example_kwargs) ) except BaseException: report(message_on_failure) raise if not any( isinstance(x, HypothesisProvided) for xs in (arguments, kwargs.values()) for x in xs ): # All arguments have been satisfied without needing to invoke # hypothesis test_runner(lambda: test(*arguments, **kwargs)) return def convert_to_specifier(v): if isinstance(v, HypothesisProvided): return strategy(v.value, settings) else: return sd.just(v) given_specifier = sd.tuples( sd.tuples(*map(convert_to_specifier, arguments)), sd.fixed_dictionaries(dict( (k, convert_to_specifier(v)) for (k, v) in kwargs.items())) ) search_strategy = strategy(given_specifier, settings) if settings.database: storage = settings.database.storage( fully_qualified_name(test)) else: storage = None last_exception = [None] repr_for_last_exception = [None] def is_template_example(xs): record_repr = [None] try: test_runner(reify_and_execute( search_strategy, xs, test, always_print=settings.max_shrinks <= 0, record_repr=record_repr, )) return False except UnsatisfiedAssumption as e: raise e except Exception as e: if settings.max_shrinks <= 0: raise e last_exception[0] = traceback.format_exc() repr_for_last_exception[0] = record_repr[0] verbose_report(last_exception[0]) return True is_template_example.__name__ = test.__name__ is_template_example.__qualname__ = qualname(test) falsifying_template = None try: falsifying_template = best_satisfying_template( search_strategy, random, is_template_example, settings, storage ) except NoSuchExample: return assert last_exception[0] is not None with settings: test_runner(reify_and_execute( search_strategy, falsifying_template, test, print_example=True, is_final=True )) report( u'Failed to reproduce exception. Expected: \n' + last_exception[0], ) test_runner(reify_and_execute( search_strategy, falsifying_template, test_is_flaky(test, repr_for_last_exception[0]), print_example=True, is_final=True )) for attr in dir(test): if attr[0] != '_' and not hasattr(wrapped_test, attr): setattr(wrapped_test, attr, getattr(test, attr)) wrapped_test.is_hypothesis_test = True return wrapped_test return run_test_with_generator
def given(*generator_arguments, **generator_kwargs): """A decorator for turning a test function that accepts arguments into a randomized test. This is the main entry point to Hypothesis. See the full tutorial for details of its behaviour. """ # Keyword only arguments but actually supported in the full range of # pythons Hypothesis handles. pop so we don't later pick these up as # if they were keyword specifiers for data to pass to the test. provided_random = generator_kwargs.pop(u'random', None) settings = generator_kwargs.pop(u'settings', None) or Settings.default if generator_arguments and generator_kwargs: note_deprecation( u'Mixing positional and keyword arguments in a call to given is ' u'deprecated. Use one or the other.', settings ) def run_test_with_generator(test): original_argspec = getargspec(test) def invalid(message): def wrapped_test(*arguments, **kwargs): raise InvalidArgument(message) return wrapped_test if (provided_random is not None) and settings.derandomize: return invalid( u'Cannot both be derandomized and provide an explicit random') if not (generator_arguments or generator_kwargs): return invalid( u'given must be called with at least one argument') if generator_arguments and original_argspec.varargs: return invalid( u'varargs are not supported with positional arguments to ' u'@given' ) extra_kwargs = [ k for k in generator_kwargs if k not in original_argspec.args] if extra_kwargs and not original_argspec.keywords: return invalid( u'%s() got an unexpected keyword argument %r' % ( test.__name__, extra_kwargs[0] )) if ( len(generator_arguments) > len(original_argspec.args) ): return invalid(( u'Too many positional arguments for %s() (got %d but' u' expected at most %d') % ( test.__name__, len(generator_arguments), len(original_argspec.args))) arguments = original_argspec.args specifiers = list(generator_arguments) seen_kwarg = None for a in arguments: if isinstance(a, list): # pragma: no cover return invalid(( u'Cannot decorate function %s() because it has ' u'destructuring arguments') % ( test.__name__, )) if a in generator_kwargs: seen_kwarg = seen_kwarg or a specifiers.append(generator_kwargs[a]) else: if seen_kwarg is not None: return invalid(( u'Argument %s comes after keyword %s which has been ' u'specified, but does not itself have a ' u'specification') % ( a, seen_kwarg )) argspec = inspect.ArgSpec( args=arguments, keywords=original_argspec.keywords, varargs=original_argspec.varargs, defaults=tuple(map(HypothesisProvided, specifiers)) ) unused_kwargs = {} for k in extra_kwargs: unused_kwargs[k] = HypothesisProvided(generator_kwargs[k]) hypothesis_owned_arguments = [ argspec.args[-1 - i] for i in hrange(len(argspec.defaults)) ] + list(unused_kwargs) @impersonate(test) @copy_argspec( test.__name__, argspec ) def wrapped_test(*arguments, **kwargs): if settings.derandomize: random = Random(function_digest(test)) else: random = provided_random or new_random() import hypothesis.strategies as sd from hypothesis.internal.strategymethod import strategy selfy = None arguments, kwargs = convert_positional_arguments( wrapped_test, arguments, kwargs) for arg in hypothesis_owned_arguments: try: value = kwargs[arg] except KeyError: continue if not isinstance(value, HypothesisProvided): note_deprecation( 'Passing in explicit values to override Hypothesis ' 'provided values is deprecated and will no longer ' 'work in Hypothesis 2.0. If you need to do this, ' 'extract a common function and call that from a ' 'Hypothesis based test.', settings ) # Anything in unused_kwargs hasn't been injected through # argspec.defaults, so we need to add them. for k in unused_kwargs: if k not in kwargs: kwargs[k] = unused_kwargs[k] # If the test function is a method of some kind, the bound object # will be the first named argument if there are any, otherwise the # first vararg (if any). if argspec.args: selfy = kwargs.get(argspec.args[0]) elif arguments: selfy = arguments[0] if isinstance(selfy, HypothesisProvided): selfy = None test_runner = executor(selfy) for example in reversed(getattr( wrapped_test, u'hypothesis_explicit_examples', () )): if example.args: example_kwargs = dict(zip( argspec.args[-len(example.args):], example.args )) else: example_kwargs = dict(example.kwargs) for k, v in kwargs.items(): if not isinstance(v, HypothesisProvided): example_kwargs[k] = v # Note: Test may mutate arguments and we can't rerun explicit # examples, so we have to calculate the failure message at this # point rather than than later. message_on_failure = u'Falsifying example: %s(%s)' % ( test.__name__, arg_string(test, arguments, example_kwargs) ) try: with BuildContext() as b: test_runner( lambda: test(*arguments, **example_kwargs) ) except BaseException: report(message_on_failure) for n in b.notes: report(n) raise if not any( isinstance(x, HypothesisProvided) for xs in (arguments, kwargs.values()) for x in xs ): # All arguments have been satisfied without needing to invoke # hypothesis test_runner(lambda: test(*arguments, **kwargs)) return def convert_to_specifier(v): if isinstance(v, HypothesisProvided): return strategy(v.value, settings) else: return sd.just(v) given_specifier = sd.tuples( sd.tuples(*map(convert_to_specifier, arguments)), sd.fixed_dictionaries(dict( (k, convert_to_specifier(v)) for (k, v) in kwargs.items())) ) def fail_health_check(message): message += ( '\nSee http://hypothesis.readthedocs.org/en/latest/health' 'checks.html for more information about this.' ) if settings.strict: raise FailedHealthCheck(message) else: warnings.warn(FailedHealthCheck(message)) search_strategy = strategy(given_specifier, settings) search_strategy.validate() if settings.database: storage = settings.database.storage( fully_qualified_name(test)) else: storage = None start = time.time() warned_random = [False] perform_health_check = settings.perform_health_check if Settings.default is not None: perform_health_check &= Settings.default.perform_health_check if perform_health_check: initial_state = getglobalrandomstate() health_check_random = Random(random.getrandbits(128)) count = 0 bad_draws = 0 filtered_draws = 0 errors = 0 while ( count < 10 and time.time() < start + 1 and filtered_draws < 50 and bad_draws < 50 ): try: with Settings(settings, verbosity=Verbosity.quiet): test_runner(reify_and_execute( search_strategy, search_strategy.draw_template( health_check_random, search_strategy.draw_parameter( health_check_random, )), lambda *args, **kwargs: None, )) count += 1 except BadTemplateDraw: bad_draws += 1 except UnsatisfiedAssumption: filtered_draws += 1 except Exception: if errors == 0: report(traceback.format_exc()) errors += 1 if test_runner is default_executor: fail_health_check( 'An exception occurred during data ' 'generation in initial health check. ' 'This indicates a bug in the strategy. ' 'This could either be a Hypothesis bug or ' "an error in a function you've passed to " 'it to construct your data.' ) else: fail_health_check( 'An exception occurred during data ' 'generation in initial health check. ' 'This indicates a bug in the strategy. ' 'This could either be a Hypothesis bug or ' 'an error in a function you\'ve passed to ' 'it to construct your data. Additionally, ' 'you have a custom executor, which means ' 'that this could be your executor failing ' 'to handle a function which returns None. ' ) if filtered_draws >= 50: fail_health_check(( 'It looks like your strategy is filtering out a lot ' 'of data. Health check found %d filtered examples but ' 'only %d good ones. This will make your tests much ' 'slower, and also will probably distort the data ' 'generation quite a lot. You should adapt your ' 'strategy to filter less.') % ( filtered_draws, count )) if bad_draws >= 50: fail_health_check( 'Hypothesis is struggling to generate examples. ' 'This is often a sign of a recursive strategy which ' 'fans out too broadly. If you\'re using recursive, ' 'try to reduce the size of the recursive step or ' 'increase the maximum permitted number of leaves.' ) runtime = time.time() - start if runtime > 1.0 or count < 10: fail_health_check(( 'Data generation is extremely slow: Only produced ' '%d valid examples in %.2f seconds. Try decreasing ' "size of the data you're generating (with e.g." 'average_size or max_leaves parameters).' ) % (count, runtime)) if getglobalrandomstate() != initial_state: warned_random[0] = True fail_health_check( 'Data generation depends on global random module. ' 'This makes results impossible to replay, which ' 'prevents Hypothesis from working correctly. ' 'If you want to use methods from random, use ' 'randoms() from hypothesis.strategies to get an ' 'instance of Random you can use. Alternatively, you ' 'can use the random_module() strategy to explicitly ' 'seed the random module.' ) last_exception = [None] repr_for_last_exception = [None] def is_template_example(xs): if perform_health_check and not warned_random[0]: initial_state = getglobalrandomstate() record_repr = [None] try: result = test_runner(reify_and_execute( search_strategy, xs, test, record_repr=record_repr, )) if result is not None: note_deprecation(( 'Tests run under @given should return None, but ' '%s returned %r instead.' 'In Hypothesis 2.0 this will become an error.' ) % (test.__name__, result), settings) return False except HypothesisDeprecationWarning: raise except UnsatisfiedAssumption as e: raise e except Exception as e: last_exception[0] = traceback.format_exc() repr_for_last_exception[0] = record_repr[0] verbose_report(last_exception[0]) return True finally: if ( not warned_random[0] and perform_health_check and getglobalrandomstate() != initial_state ): warned_random[0] = True fail_health_check( 'Your test used the global random module. ' 'This is unlikely to work correctly. You should ' 'consider using the randoms() strategy from ' 'hypothesis.strategies instead. Alternatively, ' 'you can use the random_module() strategy to ' 'explicitly seed the random module.' ) is_template_example.__name__ = test.__name__ is_template_example.__qualname__ = qualname(test) with settings: falsifying_template = None try: falsifying_template = best_satisfying_template( search_strategy, random, is_template_example, settings, storage, start_time=start, ) except NoSuchExample: return assert last_exception[0] is not None try: test_runner(reify_and_execute( search_strategy, falsifying_template, test, print_example=True, is_final=True )) except UnsatisfiedAssumption: report(traceback.format_exc()) raise Flaky( 'Unreliable assumption: An example which satisfied ' 'assumptions on the first run now fails it.' ) report( u'Failed to reproduce exception. Expected: \n' + last_exception[0], ) try: test_runner(reify_and_execute( search_strategy, falsifying_template, test_is_flaky(test, repr_for_last_exception[0]), print_example=True, is_final=True )) except UnsatisfiedAssumption: raise Flaky( 'Unreliable test data: Failed to reproduce a failure ' 'and then when it came to recreating the example in ' 'order to print the test data with a flaky result ' 'the example was filtered out (by e.g. a ' 'call to filter in your strategy) when we didn\'t ' 'expect it to be.' ) for attr in dir(test): if attr[0] != '_' and not hasattr(wrapped_test, attr): setattr(wrapped_test, attr, getattr(test, attr)) wrapped_test.is_hypothesis_test = True return wrapped_test return run_test_with_generator