def test_printErrorsVerbose3(self): """ printErrors() looks correct in verbose=3 mode. """ try: raise Exception except: err = sys.exc_info() self.args.verbose = 3 self.args.termcolor = False gtr = GreenTestResult(self.args, GreenStream(self.stream)) gtr.addError(MyProtoTest(), proto_error(err)) gtr.printErrors() self.assertIn("\n\n", self.stream.getvalue()) self.assertIn("my_module.MyClass.myMethod", self.stream.getvalue()) self.assertIn("test_printErrorsVerbose3", self.stream.getvalue()) self.assertIn("raise Exception", self.stream.getvalue()) self.assertIn("Error", self.stream.getvalue())
def test_reportOutcomeCursorUp(self): """ _reportOutcome moves the cursor up when it needs to. """ self.args.verbose = 2 def isatty(): return True gs = GreenStream(self.stream) gs.isatty = isatty gtr = GreenTestResult(self.args, gs) r = 'a fake reason' t = MagicMock() t.__str__.return_value = 'x' * 1000 gtr._reportOutcome(t, '.', lambda x: x, None, r) self.assertIn(r, self.stream.getvalue()) self.assertLess(len(self.stream.getvalue()), 2000)
def test_printErrors_Py2Unicode(self): """ printErrors() doesn't crash in Python 2 when tracebacks contain unicode """ try: raise Exception("Das Böse ist immer und überall") except: err = sys.exc_info() self.args.verbose = 1 self.args.termcolor = False gtr = GreenTestResult(self.args, GreenStream(self.stream)) gtr.addError(MyProtoTest(), proto_error(err)) gtr.printErrors() # We shouldn't hit an exception here self.assertIn("\n\n", self.stream.getvalue()) self.assertIn("my_module.MyClass.myMethod", self.stream.getvalue()) self.assertIn("raise Exception", self.stream.getvalue()) self.assertIn("Error", self.stream.getvalue()) self.assertIn("Böse", self.stream.getvalue())
def test_printErrorsDots(self): """ printErrors() looks correct in verbose=1 (dots) mode. """ try: raise Exception except: err = sys.exc_info() self.args.verbose = 1 self.args.termcolor = False gtr = GreenTestResult(self.args, GreenStream(self.stream)) gtr.addError(MyProtoTest(), proto_error(err)) gtr.printErrors() self.assertIn('\n\n', self.stream.getvalue()) self.assertIn('my_module.MyClass.myMethod', self.stream.getvalue()) self.assertIn('test_printErrorsDots', self.stream.getvalue()) self.assertIn('raise Exception', self.stream.getvalue()) self.assertIn('Error', self.stream.getvalue())
def test_stopTestRun(self, mock_printErrors): """ We ignore coverage's error about not having anything to cover. """ try: from coverage.misc import CoverageException except: self.skipTest("Coverage needs to be installed for this test.") self.args.cov = MagicMock() self.args.cov.stop = MagicMock( side_effect=CoverageException('Different Exception')) self.args.run_coverage = True gtr = GreenTestResult(self.args, GreenStream(self.stream)) gtr.startTestRun() self.assertRaises(CoverageException, gtr.stopTestRun) self.args.cov.stop = MagicMock( side_effect=CoverageException('No data to report'))
def test_printErrorsStdoutQuietStdoutOnError(self): """ printErrors() prints out the captured stdout except when quiet_stdout is set to True for successful tests, but here we are on a failing test. """ self.args.quiet_stdout = True try: raise Exception except: err = sys.exc_info() gtr = GreenTestResult(self.args, GreenStream(self.stream)) pt = MyProtoTest() output = 'this is what the test should spit out to stdout' gtr.recordStdout(pt, output) gtr.addError(pt, proto_error(err)) gtr.printErrors() self.assertIn(output, self.stream.getvalue())
def test_printErrorsVerbose4(self): """ printErrors() looks correct in verbose=4 mode """ try: raise Exception except: err = sys.exc_info() self.args.verbose = 4 self.args.termcolor = False gtr = GreenTestResult(self.args, GreenStream(self.stream)) gtr.addError(MyProtoTest(), err) gtr.printErrors() self.assertIn('\n\n', self.stream.getvalue()) self.assertIn('(most recent call last)', self.stream.getvalue()) self.assertIn('my_module.MyClass.myMethod', self.stream.getvalue()) self.assertIn('test_printErrorsVerbose4', self.stream.getvalue()) self.assertIn('raise Exception', self.stream.getvalue()) self.assertIn('Error', self.stream.getvalue())
def test_reportOutcomeVerbose(self, mock_proto_test): """ _reportOutcome contains output we expect in verbose mode. """ mockProtoTest = MagicMock() mockProtoTest.getDescription.return_value = 'a description' mock_proto_test.return_value = mockProtoTest self.args.verbose = 2 def isatty(): return True gs = GreenStream(self.stream) gs.isatty = isatty gtr = GreenTestResult(self.args, gs) r = 'a fake reason' t = MagicMock() t.__str__.return_value = 'junk' gtr._reportOutcome(t, '.', lambda x: x, None, r) self.assertIn(r, self.stream.getvalue())
def test_reportOutcomeCursorUp(self, mock_proto_test): """ _reportOutcome moves the cursor up when it needs to. """ mockProtoTest = MagicMock() mockProtoTest.getDescription.return_value = "a description" mock_proto_test.return_value = mockProtoTest self.args.verbose = 2 def isatty(): return True gs = GreenStream(self.stream) gs.isatty = isatty gtr = GreenTestResult(self.args, gs) r = "a fake reason" t = MagicMock() t.__str__.return_value = "x" * 1000 gtr._reportOutcome(t, ".", lambda x: x, None, r) self.assertIn(r, self.stream.getvalue()) self.assertLess(len(self.stream.getvalue()), 2000)
def run_tests(self, test_labels, extra_tests=None, **kwargs): """ Run the unit tests for all the test labels in the provided list. Test labels should be dotted Python paths to test modules, test classes, or test methods. A list of 'extra' tests may also be provided; these tests will be added to the test suite. Returns the number of tests that failed. """ # Django setup self.setup_test_environment() django_db = self.setup_databases() # Green if type(test_labels) == tuple: test_labels = list(test_labels) else: raise ValueError("test_labels should be a tuple of strings") if not test_labels: test_labels = ["."] args = mergeConfig(Namespace()) if self.verbose != -1: args.verbose = self.verbose args.targets = test_labels stream = GreenStream(sys.stdout) suite = self.loader.loadTargets(args.targets) if not suite: suite = GreenTestSuite() result = run(suite, stream, args) # Django teardown self.teardown_databases(django_db) self.teardown_test_environment() return self.suite_result(suite, result)
def test_tryRecordingStdoutStderr(self): """ Recording stdout and stderr works correctly. """ gtr = GreenTestResult(self.args, GreenStream(self.stream)) gtr.recordStdout = MagicMock() gtr.recordStderr = MagicMock() output = 'apple' test1 = MagicMock() ptr1 = MagicMock() ptr1.stdout_output = {test1: output} ptr1.stderr_errput = {} errput = 'banana' test2 = MagicMock() ptr2 = MagicMock() ptr2.stdout_output = {} ptr2.stderr_errput = {test2: errput} gtr.tryRecordingStdoutStderr(test1, ptr1) gtr.recordStdout.assert_called_with(test1, output) gtr.tryRecordingStdoutStderr(test2, ptr2) gtr.recordStderr.assert_called_with(test2, errput)
def run(suite, stream, args, testing=False): """ Run the given test case or test suite with the specified arguments. Any args.stream passed in will be wrapped in a GreenStream """ # check if the kubefwd is running, then stop the run if check_kubefwd_running(): return GreenTestResult(args, stream) if not issubclass(GreenStream, type(stream)): stream = GreenStream( stream, disable_windows=args.disable_windows, disable_unidecode=args.disable_unidecode, ) result = GreenTestResult(args, stream) # Note: Catching SIGINT isn't supported by Python on windows (python # "WONTFIX" issue 18040) installHandler() registerResult(result) with warnings.catch_warnings(): if args.warnings: # pragma: no cover # if args.warnings is set, use it to filter all the warnings warnings.simplefilter(args.warnings) # if the filter is 'default' or 'always', special-case the # warnings from the deprecated unittest methods to show them # no more than once per module, because they can be fairly # noisy. The -Wd and -Wa flags can be used to bypass this # only when args.warnings is None. if args.warnings in ["default", "always"]: warnings.filterwarnings( "module", category=DeprecationWarning, message="Please use assert\w+ instead.", ) result.startTestRun() # The call to toParallelTargets needs to happen before pool stuff so we can crash if there # are, for example, syntax errors in the code to be loaded. parallel_targets = toParallelTargets(suite, args.targets) pool = LoggingDaemonlessPool( processes=args.processes or None, initializer=InitializerOrFinalizer(args.initializer), finalizer=InitializerOrFinalizer(args.finalizer), ) manager = multiprocessing.Manager() targets = [(target, manager.Queue()) for target in parallel_targets] if targets: for index, (target, queue) in enumerate(targets): if args.run_coverage: coverage_number = index + 1 else: coverage_number = None debug("Sending {} to poolRunner {}".format(target, poolRunner)) pool.apply_async( poolRunner, ( target, queue, coverage_number, args.omit_patterns, args.cov_config_file, ), ) pool.close() for target, queue in targets: abort = False while True: msg = queue.get() # Sentinel value, we're done if not msg: debug("runner.run(): received sentinal, breaking.", 3) break else: debug("runner.run(): start test: {}".format(msg)) # Result guaranteed after this message, we're # currently waiting on this test, so print out # the white 'processing...' version of the output result.startTest(msg) proto_test_result = queue.get() debug( "runner.run(): received proto test result: {}". format(str(proto_test_result)), 3, ) result.addProtoTestResult(proto_test_result) if result.shouldStop: debug("runner.run(): shouldStop encountered, breaking", 3) abort = True break if abort: break pool.close() pool.join() result.stopTestRun() removeResult(result) return result
def setUp(self): self.stream = StringIO() self.args = copy.deepcopy(default_args) self.args.verbose = 0 self.gtr = GreenTestResult(self.args, GreenStream(self.stream)) self.gtr._reportOutcome = MagicMock()
def run(self, result): """ Emulate unittest's behavior, with Green-specific changes. """ topLevel = False if getattr(result, "_testRunEntered", False) is False: result._testRunEntered = topLevel = True for index, test in enumerate(self): if result.shouldStop: break if _isnotsuite(test): self._tearDownPreviousClass(test, result) self._handleModuleFixture(test, result) self._handleClassSetUp(test, result) result._previousTestClass = test.__class__ if getattr(test.__class__, "_classSetupFailed", False) or getattr( result, "_moduleSetUpFailed", False): continue if not self.allow_stdout: captured_stdout = StringIO() captured_stderr = StringIO() saved_stdout = sys.stdout saved_stderr = sys.stderr sys.stdout = GreenStream(captured_stdout) sys.stderr = GreenStream(captured_stderr) test(result) if _isnotsuite(test): if not self.allow_stdout: sys.stdout = saved_stdout sys.stderr = saved_stderr result.recordStdout(test, captured_stdout.getvalue()) result.recordStderr(test, captured_stderr.getvalue()) # Since we're intercepting the stdout/stderr out here at the # suite level, we need to poke the test result and let it know # when we're ready to transmit results back up to the parent # process. I would rather just do it automatically at test # stop time, but we don't have the captured stuff at that # point. Messy...but the only other alternative I can think of # is monkey-patching loaded TestCases -- which could be from # unittest or twisted or some other custom subclass. result.finalize() self._removeTestAtIndex(index) # Green's subprocesses have handled all actual tests and sent up the # result, but unittest expects to be able to add teardown errors to # the result still, so we'll need to watch for that ourself. errors_before = len(result.errors) if topLevel: self._tearDownPreviousClass(None, result) self._handleModuleTearDown(result) result._testRunEntered = False # Special handling for class/module tear-down errors. startTest() and # finalize() both trigger communication between the subprocess and # the runner process. addError() if errors_before != len(result.errors): difference = len(result.errors) - errors_before result.errors, new_errors = ( result.errors[:-difference], result.errors[-difference:], ) for (test, err) in new_errors: # test = ProtoTest() test.module = result._previousTestClass.__module__ test.class_name = result._previousTestClass.__name__ # test.method_name = 'some method name' test.is_class_or_module_teardown_error = True test.name = "Error in class or module teardown" # test.docstr_part = 'docstr part' # error_holder.description result.startTest(test) result.addError(test, err) result.stopTest(test) result.finalize() return result
def run(suite, stream, args, testing=False): """ Run the given test case or test suite with the specified arguments. Any args.stream passed in will be wrapped in a GreenStream """ if not issubclass(GreenStream, type(stream)): stream = GreenStream(stream, disable_windows=args.disable_windows) result = GreenTestResult(args, stream) # Note: Catching SIGINT isn't supported by Python on windows (python # "WONTFIX" issue 18040) installHandler() registerResult(result) with warnings.catch_warnings(): if args.warnings: # pragma: no cover # if args.warnings is set, use it to filter all the warnings warnings.simplefilter(args.warnings) # if the filter is 'default' or 'always', special-case the # warnings from the deprecated unittest methods to show them # no more than once per module, because they can be fairly # noisy. The -Wd and -Wa flags can be used to bypass this # only when args.warnings is None. if args.warnings in ['default', 'always']: warnings.filterwarnings( 'module', category=DeprecationWarning, message='Please use assert\w+ instead.') result.startTestRun() pool = LoggingDaemonlessPool( processes=args.processes or None, initializer=InitializerOrFinalizer(args.initializer), finalizer=InitializerOrFinalizer(args.finalizer)) manager = multiprocessing.Manager() targets = [(target, manager.Queue()) for target in toParallelTargets(suite, args.targets)] if targets: for index, (target, queue) in enumerate(targets): if args.run_coverage: coverage_number = index + 1 else: coverage_number = None debug("Sending {} to runner {}".format(target, poolRunner)) pool.apply_async( poolRunner, (target, queue, coverage_number, args.omit_patterns)) pool.close() for target, queue in targets: abort = False while True: msg = queue.get() # Sentinel value, we're done if not msg: break else: # Result guaranteed after this message, we're # currently waiting on this test, so print out # the white 'processing...' version of the output result.startTest(msg) proto_test_result = queue.get() result.addProtoTestResult(proto_test_result) if result.shouldStop: abort = True break if abort: break pool.close() pool.join() result.stopTestRun() removeResult(result) return result
def _main(argv, testing): args = config.parseArguments(argv) args = config.mergeConfig(args, testing) if args.shouldExit: return args.exitCode # Clear out all the passed-in-options just in case someone tries to run a # test that assumes sys.argv is clean. I can't guess at the script name # that they want, though, so we'll just leave ours. sys.argv = sys.argv[:1] # Set up our various main objects from green.loader import GreenTestLoader, getCompletions from green.runner import run from green.output import GreenStream, debug import green.output from green.suite import GreenTestSuite GreenTestSuite.args = args if args.debug: green.output.debug_level = args.debug stream = GreenStream(sys.stdout, disable_windows=args.disable_windows) # Location of shell completion file if args.completion_file: print(os.path.join(os.path.dirname(__file__), "shell_completion.sh")) return 0 # Argument-completion for bash and zsh (for test-target completion) if args.completions: print(getCompletions(args.targets)) return 0 # Option-completion for bash and zsh if args.options: print("\n".join(sorted(args.store_opt.options))) return 0 # Add debug logging for stuff that happened before this point here if config.files_loaded: debug("Loaded config file(s): {}".format(", ".join( config.files_loaded))) # Discover/Load the test suite if testing: test_suite = None else: # pragma: no cover loader = GreenTestLoader() test_suite = loader.loadTargets(args.targets, file_pattern=args.file_pattern) # We didn't even load 0 tests... if not test_suite: debug( "No test loading attempts succeeded. Created an empty test suite." ) test_suite = GreenTestSuite() # Actually run the test_suite result = run(test_suite, stream, args, testing) # Generate a test report if required if args.junit_report: from green.junit import JUnitXML adapter = JUnitXML() with open(args.junit_report, "w") as report_file: adapter.save_as(result, report_file) return int(not result.wasSuccessful())
def setUp(self): self.s = StringIO() self.gs = GreenStream(self.s) saved_stdout = config.sys.stdout config.sys.stdout = self.gs self.addCleanup(setattr, config.sys, 'stdout', saved_stdout)