def simplify_template_such_that( search_strategy, random, t, f, tracker, settings, start_time ): """Perform a greedy search to produce a "simplest" version of a template that satisfies some predicate. Care is taken to avoid cycles in simplify. f should produce the same result deterministically. This function may raise an error given f such that f(t) returns False sometimes and True some other times. If f throws UnsatisfiedAssumption this will be treated the same as if it returned False. """ assert isinstance(random, Random) yield t successful_shrinks = 0 changed = True while changed and successful_shrinks < settings.max_shrinks: changed = False for simplify in search_strategy.simplifiers(random, t): debug_report('Applying simplification pass %s' % ( simplify.__name__, )) while True: simpler = simplify(random, t) for s in simpler: if tracker.track(s) > 1: continue try: if f(s): successful_shrinks += 1 changed = True yield s t = s break except UnsatisfiedAssumption: pass if time_to_call_it_a_day(settings, start_time): return else: break if successful_shrinks >= settings.max_shrinks: break
def find_satisfying_template( search_strategy, random, condition, tracker, settings, storage=None, max_parameter_tries=None, ): """Attempt to find a template for search_strategy such that condition is truthy. Exceptions other than UnsatisfiedAssumption will be immediately propagated. UnsatisfiedAssumption will indicate that similar examples should be avoided in future. Returns such a template as soon as it is found, otherwise stops after settings.max_examples examples have been considered or settings.timeout seconds have passed (if settings.timeout > 0). May raise a variety of exceptions depending on exact circumstances, but these will all subclass either Unsatisfiable (to indicate not enough examples were found which did not raise UnsatisfiedAssumption to consider this a valid test) or NoSuchExample (to indicate that this probably means that condition is true with very high probability). """ satisfying_examples = 0 examples_considered = 0 timed_out = False max_iterations = max(settings.max_iterations, settings.max_examples) max_examples = min(max_iterations, settings.max_examples) min_satisfying_examples = min( settings.min_satisfying_examples, max_examples, ) start_time = time.time() if storage: for example in storage.fetch(search_strategy): if examples_considered >= max_iterations: break examples_considered += 1 if time_to_call_it_a_day(settings, start_time): break tracker.track(example) try: if condition(example): return example satisfying_examples += 1 except UnsatisfiedAssumption: pass if satisfying_examples >= max_examples: break parameter_source = ParameterSource( random=random, strategy=search_strategy, max_tries=max_parameter_tries, ) assert search_strategy.template_upper_bound >= 0 if isinstance(search_strategy.template_upper_bound, float): assert math.isinf(search_strategy.template_upper_bound) else: assert isinstance(search_strategy.template_upper_bound, int) for parameter in parameter_source: # pragma: no branch if len(tracker) >= search_strategy.template_upper_bound: break if examples_considered >= max_iterations: break if satisfying_examples >= max_examples: break if time_to_call_it_a_day(settings, start_time): break examples_considered += 1 try: example = search_strategy.draw_template( random, parameter ) except BadTemplateDraw: debug_report(u'Failed attempt to draw a template') parameter_source.mark_bad() continue if tracker.track(example) > 1: debug_report(u'Skipping duplicate example') parameter_source.mark_bad() continue try: if condition(example): return example except UnsatisfiedAssumption: parameter_source.mark_bad() continue satisfying_examples += 1 run_time = time.time() - start_time timed_out = settings.timeout >= 0 and run_time >= settings.timeout if ( satisfying_examples and len(tracker) >= search_strategy.template_upper_bound ): raise DefinitelyNoSuchExample( get_pretty_function_description(condition), satisfying_examples, ) elif satisfying_examples < min_satisfying_examples: if timed_out: raise Timeout(( u'Ran out of time before finding a satisfying example for ' u'%s. Only found %d examples (%d satisfying assumptions) in ' + u'%.2fs.' ) % ( get_pretty_function_description(condition), len(tracker), satisfying_examples, run_time )) else: raise Unsatisfiable(( u'Unable to satisfy assumptions of hypothesis %s. ' + u'Only %d out of %d examples considered satisfied assumptions' ) % ( get_pretty_function_description(condition), satisfying_examples, len(tracker))) else: raise NoSuchExample(get_pretty_function_description(condition))
def simplify_template_such_that( search_strategy, random, t, f, tracker, settings, start_time ): """Perform a greedy search to produce a "simplest" version of a template that satisfies some predicate. Care is taken to avoid cycles in simplify. f should produce the same result deterministically. This function may raise an error given f such that f(t) returns False sometimes and True some other times. If f throws UnsatisfiedAssumption this will be treated the same as if it returned False. """ assert isinstance(random, Random) yield t successful_shrinks = 0 changed = True max_warmup = 5 warmup = 0 while ( (changed or warmup < max_warmup) and successful_shrinks < settings.max_shrinks ): changed = False warmup += 1 if warmup < max_warmup: debug_report(u'Running warmup simplification round %d' % ( warmup )) elif warmup == max_warmup: debug_report(u'Warmup is done. Moving on to fully simplifying') any_simplifiers = False for simplify in search_strategy.simplifiers(random, t): debug_report(u'Applying simplification pass %s' % ( simplify.__name__, )) any_simplifiers = True any_shrinks = False while True: simpler = simplify(random, t) if warmup < max_warmup: simpler = islice(simpler, warmup) for s in simpler: any_shrinks = True if time_to_call_it_a_day(settings, start_time): return if tracker.track(s) > 1: debug_report( u'Skipping simplifying to duplicate %s' % ( unicode_safe_repr(s), )) continue try: if f(s): successful_shrinks += 1 changed = True yield s t = s break else: yield t except UnsatisfiedAssumption: pass else: break if not any_shrinks: debug_report(u'No shrinks possible') if successful_shrinks >= settings.max_shrinks: break if not any_simplifiers: debug_report(u'No simplifiers for template %s' % ( unicode_safe_repr(t), )) break
def test_does_print_debug_in_debug(): with settings(verbosity=Verbosity.debug): with capture_out() as o: debug_report(u'Hi') assert u'Hi' in o.getvalue()
def test_does_not_print_debug_in_verbose(): with settings(verbosity=Verbosity.verbose): with capture_out() as o: debug_report(u'Hi') assert not o.getvalue()
def debug(self, message): with self.settings: debug_report(message)
def f(x): debug_report('Hi')
def debug(self, message): with local_settings(self.settings): debug_report(message)
def f(x): debug_report("Hi")
def find_satisfying_template( search_strategy, random, condition, tracker, settings, storage=None, max_parameter_tries=None, ): """Attempt to find a template for search_strategy such that condition is truthy. Exceptions other than UnsatisfiedAssumption will be immediately propagated. UnsatisfiedAssumption will indicate that similar examples should be avoided in future. Returns such a template as soon as it is found, otherwise stops after settings.max_examples examples have been considered or settings.timeout seconds have passed (if settings.timeout > 0). May raise a variety of exceptions depending on exact circumstances, but these will all subclass either Unsatisfiable (to indicate not enough examples were found which did not raise UnsatisfiedAssumption to consider this a valid test) or NoSuchExample (to indicate that this probably means that condition is true with very high probability). """ satisfying_examples = 0 examples_considered = 0 timed_out = False max_iterations = max(settings.max_iterations, settings.max_examples) max_examples = min(max_iterations, settings.max_examples) min_satisfying_examples = min( settings.min_satisfying_examples, max_examples, ) start_time = time.time() if storage: for example in storage.fetch(search_strategy): if examples_considered >= max_iterations: break examples_considered += 1 if time_to_call_it_a_day(settings, start_time): break tracker.track(example) try: if condition(example): return example satisfying_examples += 1 except UnsatisfiedAssumption: pass if satisfying_examples >= max_examples: break parameter_source = ParameterSource( random=random, strategy=search_strategy, max_tries=max_parameter_tries, ) assert search_strategy.template_upper_bound >= 0 if isinstance(search_strategy.template_upper_bound, float): assert math.isinf(search_strategy.template_upper_bound) else: assert isinstance(search_strategy.template_upper_bound, int) for parameter in parameter_source: # pragma: no branch if len(tracker) >= search_strategy.template_upper_bound: break if examples_considered >= max_iterations: break if satisfying_examples >= max_examples: break if time_to_call_it_a_day(settings, start_time): break examples_considered += 1 try: example = search_strategy.draw_template(random, parameter) except BadTemplateDraw: debug_report('Failed attempt to draw a template') parameter_source.mark_bad() continue if tracker.track(example) > 1: debug_report('Skipping duplicate example') parameter_source.mark_bad() continue try: if condition(example): return example except UnsatisfiedAssumption: parameter_source.mark_bad() continue satisfying_examples += 1 run_time = time.time() - start_time timed_out = settings.timeout >= 0 and run_time >= settings.timeout if (satisfying_examples and len(tracker) >= search_strategy.template_upper_bound): raise DefinitelyNoSuchExample( get_pretty_function_description(condition), satisfying_examples, ) elif satisfying_examples < min_satisfying_examples: if timed_out: raise Timeout( ('Ran out of time before finding a satisfying example for ' '%s. Only found %d examples (%d satisfying assumptions) in ' + '%.2fs.') % (get_pretty_function_description(condition), len(tracker), satisfying_examples, run_time)) else: raise Unsatisfiable( ('Unable to satisfy assumptions of hypothesis %s. ' + 'Only %d out of %d examples considered satisfied assumptions') % (get_pretty_function_description(condition), satisfying_examples, len(tracker))) else: raise NoSuchExample(get_pretty_function_description(condition))
def simplify_template_such_that(search_strategy, random, t, f, tracker, settings, start_time): """Perform a greedy search to produce a "simplest" version of a template that satisfies some predicate. Care is taken to avoid cycles in simplify. f should produce the same result deterministically. This function may raise an error given f such that f(t) returns False sometimes and True some other times. If f throws UnsatisfiedAssumption this will be treated the same as if it returned False. """ yield t try: if settings.max_shrinks <= 0 or not f(t): return except UnsatisfiedAssumption: return successful_shrinks = 0 changed = True max_warmup = 5 warmup = 0 while ((changed or warmup < max_warmup) and successful_shrinks < settings.max_shrinks): changed = False warmup += 1 if warmup < max_warmup: debug_report('Running warmup simplification round %d' % (warmup)) elif warmup == max_warmup: debug_report('Warmup is done. Moving on to fully simplifying') any_simplifiers = False for simplify in search_strategy.simplifiers(random, t): debug_report('Applying simplification pass %s' % (simplify.__name__, )) any_simplifiers = True any_shrinks = False while successful_shrinks < settings.max_shrinks: simpler = simplify(random, t) if warmup < max_warmup: simpler = islice(simpler, warmup) for s in simpler: any_shrinks = True if time_to_call_it_a_day(settings, start_time): return if tracker.track(s) > 1: debug_report('Skipping simplifying to duplicate %s' % (repr(s), )) continue try: if f(s): successful_shrinks += 1 changed = True yield s t = s break else: yield t except UnsatisfiedAssumption: pass else: break if not any_shrinks: debug_report('No shrinks possible') if not any_simplifiers: debug_report('No simplifiers for template %s' % (repr(t), )) break