Created
September 23, 2013 22:59
-
-
Save mattvonrocketstein/6678175 to your computer and use it in GitHub Desktop.
partition tests by type, retrieve misc. test metadata
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import os, sys | |
| import inspect | |
| import unittest, unittest2 | |
| from django import test as dtest | |
| import nose | |
| def _suite2list(s): | |
| return [x for x in _suite2iter(s)] | |
| def _suite2iter(s): | |
| """ suites contain tests but also *are* tests | |
| so unpacking them takes some effort. | |
| """ | |
| for test in s: | |
| if unittest.suite._isnotsuite(test): | |
| yield test | |
| else: | |
| for t in _suite2iter(test): | |
| yield t | |
| class2dotpath = lambda x: "{0}.{1}".format(x.__module__, x.__name__) | |
| class PartionTestsByType(nose.core.TestProgram): | |
| _suite2list = staticmethod(_suite2list) | |
| def _dammit_nose_you_took_my_io(self): | |
| """ NB: without this prints and embedded | |
| shells will not be possible """ | |
| sys.stdout = sys.__stdout__ | |
| sys.stdin = sys.__stdin__ | |
| def consider_test(self, test): | |
| ## handed some kind of nose wrapper at first, unpack it | |
| unwrapped_test = test.test | |
| ## almost got something useful.. unpack more metadata | |
| test_class = unwrapped_test.__class__ | |
| test_method_name = unwrapped_test._testMethodName | |
| bound_test_method = getattr(unwrapped_test, test_method_name) | |
| test_method_source = inspect.getsource(bound_test_method) | |
| setUp_method_source = inspect.getsource(test_class.setUp) | |
| ## things we know for sure | |
| test_class_bases = test_class.__bases__ | |
| test_class_base_names = [ class2dotpath(x) for x in test_class_bases] | |
| is_unittest2 = unittest2.TestCase in test_class_bases | |
| is_unittest1 = unittest.TestCase in test_class_bases | |
| is_django_testcase = any([ | |
| # FIXME: there's a bug here since this should be truly recursive | |
| issubclass(x, dtest.TransactionTestCase ) \ | |
| for x in test_class_bases]) | |
| is_using_django_fixtures = is_django_testcase and \ | |
| bool(getattr(test_class, 'fixtures', [])) | |
| # | |
| # TODO: | |
| # is_solr_integration_test = ... | |
| # | |
| # this can't work with issubclass() because for instance when | |
| # partitioning tests in some random component, we wont be able | |
| # to import medley.abc.testing.HaystackTestCase. will have to | |
| # use kls.__name__ (and dont forget to recurse up thru parent | |
| # classes properly.) | |
| # | |
| # heuristics (but pretty strong ones, imho) | |
| using_django_test_client = 'self.client.' in test_method_source | |
| method_needs_refactor = len(test_method_source.split('\n')) > 8 | |
| class_needs_refactor = any([ | |
| # setup method too long? | |
| len(setUp_method_source.split('\n')) > 10, | |
| # too many methods? | |
| len([x for x in dir(test_class) if x.startswith('test_')])]) | |
| result = locals() | |
| result.pop('self') | |
| return result | |
| def runTests(self): | |
| """ we don't really want to run tests; | |
| we want to inspect them. this is a nice | |
| place to hook in though because we know | |
| the suite is fully collected and prepared | |
| """ | |
| self._dammit_nose_you_took_my_io() | |
| every_test = _suite2list(self.test) # [ nose.case.Test, .. ] | |
| for test in every_test: | |
| print 'considering: ', test | |
| partition = self.consider_test(test) | |
| # | |
| # do something with partition data here | |
| # | |
| # | |
| # do any aggregating necessary for reporting here. | |
| # for now we just drop to a shell here, so the user can | |
| # inspect the last test we considered. | |
| # | |
| # (..try typing "print partition" from the terminal) | |
| # | |
| from IPython import Shell; Shell.IPShellEmbed(argv=['-noconfirm_exit'])() | |
| #return True # just to be safe. probably used for the sys.exit() status. | |
| if __name__ == '__main__': | |
| PartionTestsByType(argv=['-w', '.', '--collect'],) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment