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 int(self.verbose) in (1,2,3): args.verbose = int(self.verbose) args.targets = test_labels stream = GreenStream(sys.stdout) suite = 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 _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 loadTarget(target, file_pattern='test*.py'): """ """ debug("Attempting to load target '{}' with file_pattern '{}'".format( target, file_pattern)) loader = unittest.TestLoader() loader.suiteClass = GreenTestSuite # For a test loader, we want to always the current working directory to be # the first item in sys.path, just like when a python interpreter is loaded # interactively. See also # https://docs.python.org/3.4/library/sys.html#sys.path if sys.path[0] != '': sys.path.insert(0, '') # DIRECTORY VARIATIONS - These will discover all tests in a directory # structure, whether or not they are accessible by the root package. # some/real/dir bare_dir = target # some.real.dir if ('.' in target) and (len(target) > 1): dot_dir = target[0] + target[1:].replace('.', os.sep) else: dot_dir = None # pyzmq.tests (Package (=dir) in PYTHONPATH, including installed ones) pkg_in_path_dir = None if target and (target[0] != '.'): try: filename = importlib.import_module(target).__file__ if '__init__.py' in filename: pkg_in_path_dir = os.path.dirname(filename) except: pkg_in_path_dir = None # => DISCOVER DIRS tests = None for candidate in [bare_dir, dot_dir, pkg_in_path_dir]: if (candidate is None) or (not os.path.isdir(candidate)): continue tests = discover(candidate, file_pattern=file_pattern) if tests and tests.countTestCases(): debug("Load method: DISCOVER - {}".format(candidate)) return tests # DOTTED OBJECT - These will discover a specific object if it is # globally importable or importable from the current working directory. # Examples: pkg, pkg.module, pkg.module.class, pkg.module.class.func tests = None if target and (target[0] != '.'): # We don't handle relative dot objects try: tests = loader.loadTestsFromName(target) for index, test in enumerate(tests): if test.__class__.__name__ == '_FailedTest': # pragma: no cover del (tests._tests[index]) except Exception as e: debug("IGNORED exception: {}".format(e)) if tests and tests.countTestCases(): debug("Load method: DOTTED OBJECT - {}".format(target)) return tests # FILE VARIATIONS - These will import a specific file and any tests # accessible from its scope. # some/file.py bare_file = target # some/file pyless_file = target + '.py' for candidate in [bare_file, pyless_file]: if (candidate is None) or (not os.path.isfile(candidate)): continue need_cleanup = False cwd = os.getcwd() if cwd != sys.path[0]: need_cleanup = True sys.path.insert(0, cwd) try: dotted_path = target.replace('.py', '').replace(os.sep, '.') tests = loader.loadTestsFromName(dotted_path) except: # Any exception could occur here # TODO: #25 - Right now this mimics the behavior in unittest. Lets # refactor it and simplify it after we make sure it works. # This is a cause of the traceback mangling I observed. try: message = ('Failed to import "{}":\n{}').format( dotted_path, traceback.format_exc()) # If the line that caused the exception has unicode literals in it # anywhere, then python 2.7 will crash on traceback.format_exc(). # Python 3 is ok. except UnicodeDecodeError: # pragma: no cover message = ('Failed to import "{}", and the import traceback ' 'has a unicode decode error, so I can\'t display ' 'it.'.format(dotted_path)) def testFailure(self): raise ImportError(message) TestClass = type(str("ModuleImportFailure"), (unittest.case.TestCase, ), {dotted_path: testFailure}) return GreenTestSuite((TestClass(dotted_path), )) if need_cleanup: sys.path.remove(cwd) if tests and tests.countTestCases(): debug("Load method: FILE - {}".format(candidate)) return tests return None
debug("Test case names: {}".format(test_case_names)) test_case_names.sort( key=functools.cmp_to_key(lambda x, y: (x > y) - (x < y))) if not test_case_names and hasattr(test_case_class, 'runTest'): test_case_names = ['runTest'] return GreenTestSuite(map(test_case_class, test_case_names)) def loadFromModule(module): debug("Examining module {} for test cases".format(module.__name__), 2) test_cases = [] for item in dir(module): obj = getattr(module, item) if isinstance(obj, type) and issubclass(obj, unittest.case.TestCase): test_cases.append(loadFromTestCase(obj)) return GreenTestSuite(test_cases) def loadFromModuleFilename(filename): dotted_module, parent_dir = findDottedModuleAndParentDir(filename) # Adding the parent path of the module to the start of sys.path is # the closest we can get to an absolute import in Python that I can # find. sys.path.insert(0, parent_dir) try: __import__(dotted_module) loaded_module = sys.modules[dotted_module] debug("Imported {}".format(dotted_module), 2) except unittest.case.SkipTest as e: # TODO: #25 - Right now this mimics the behavior in unittest. Lets # refactor it and simplify it after we make sure it works.
def test_defaultArgs(self): """ Passing in default arguments causes attributes to be set. """ gts = GreenTestSuite(args=default_args) self.assertEqual(gts.allow_stdout, default_args.allow_stdout)
def test_empty(self): """ An empty suite can be instantiated. """ GreenTestSuite()
def test_noTestsFound(self): """ When we don't find any tests, we say so. """ run(GreenTestSuite(), self.stream, self.args) self.assertIn('No Tests Found', self.stream.getvalue())
def suite(): """ return our TestSuite """ suite = GreenTestSuite() suite = loadFromTestCase(TestConfig) return suite