From 08c249ee5d6f7c694d5487d6a80b0298deefe5f8 Mon Sep 17 00:00:00 2001 From: Stanislav Zubov Date: Wed, 4 Apr 2018 15:16:20 +0700 Subject: [PATCH] noseid-also-adds-failed-to-setup-test-suite-to-noseid (#33) --- CHANGELOG.md | 4 ++ README.md | 6 +- lode_runner/plugins/testid.py | 104 +++++++++++++++++++++------------- setup.py | 2 +- 4 files changed, 72 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69e3ae5..cefa40a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.5 + +- NoseId plugin also collects tests failed during setup test suite + ## 0.4.4 - Add 'lode_runner.plugins.Suppressor' plugin. Allows suppress any exceptions in tearDown-methods diff --git a/README.md b/README.md index 24af523..19b1f4b 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ lode_runner =========== -[![Build Status](https://travis-ci.org/nwlunatic/lode_runner.svg?branch=master)](https://travis-ci.org/nwlunatic/lode_runner) +[![Build Status](https://travis-ci.org/2gis/lode_runner.svg?branch=master)](https://travis-ci.org/2gis/lode_runner) -# install +# Installation ```bash -pip install -U git+https://github.com/2gis/lode_runner.git#egg=lode_runner +pip install lode_runner ``` # Running and debugging tests with PyCharm diff --git a/lode_runner/plugins/testid.py b/lode_runner/plugins/testid.py index 589a68d..9c0e475 100644 --- a/lode_runner/plugins/testid.py +++ b/lode_runner/plugins/testid.py @@ -1,14 +1,17 @@ # coding: utf-8 -import multiprocessing -import sys + import os +import sys +import multiprocessing + +from nose.suite import ContextSuite try: from cPickle import dump, load except ImportError: from pickle import dump, load -from nose.plugins.testid import TestId +from nose.plugins.testid import TestId as NoseTestId from nose.plugins import Plugin from nose.util import split_test_name @@ -23,7 +26,7 @@ LOCK = MANAGER.Lock() -class TestId(TestId): +class TestId(NoseTestId): collecting = True def configure(self, options, conf): @@ -33,9 +36,11 @@ def configure(self, options, conf): if options.failed: self.enabled = True self.loopOnFailed = True + self.idfile = os.path.expanduser(options.testIdFile) if not os.path.isabs(self.idfile): self.idfile = os.path.join(conf.workingDir, self.idfile) + self.id = 1 self.ids = IDS self.tests = TESTS @@ -50,32 +55,32 @@ def configure(self, options, conf): self.stream = sys.stderr def _load_from_file(self, names): - if not len(self.ids): + if not self.ids: + failed = [] try: - fh = open(self.idfile, 'rb') - data = load(fh) - failed = list() - if 'ids' in data: - self.ids.update(data['ids']) - failed += data['failed'] - self.source_names += data['source_names'] - else: - # old ids field - self.ids.update(data) - self.source_names += names - if len(self.ids): - self.id = len(self.ids) + 1 - self.tests.update(dict(list(zip(list(self.ids.values()), list(self.ids.keys()))))) - else: - self.id = 1 - fh.close() - - if self.loopOnFailed and len(failed): - self.collecting = False - return failed + with open(self.idfile, 'rb') as fh: + data = load(fh) + if 'ids' in data: + self.ids.update(data['ids']) + failed += data['failed'] + self.source_names += data['source_names'] + else: + # old ids field + self.ids.update(data) + self.source_names += names except IOError: pass + if self.ids: + self.id = len(self.ids) + 1 + self.tests.update(dict(list(zip(list(self.ids.values()), list(self.ids.keys()))))) + else: + self.id = 1 + + if self.loopOnFailed and failed: + self.collecting = False + return failed + return names def loadTestsFromNames(self, names, module=None): @@ -125,6 +130,29 @@ def loadTestsFromNames(self, names, module=None): return (None, translated + really_new + filtered or names) + def _handle_test(self, test): + """ + Fake start and finish test + :param test: nose.case.Test + """ + self.startTest(test) + test.passed = False + self.afterTest(test) + + def _handle_suite(self, test, err): + if isinstance(test, ContextSuite): + for single_test in test._tests: + if isinstance(single_test, ContextSuite): + self._handle_suite(single_test, err) + else: + self._handle_test(single_test) + + def handleError(self, test, err): + self._handle_suite(test, err) + + def handleFailure(self, test, err): + self._handle_suite(test, err) + def startTest(self, test): """Maybe output an id # before the test name. @@ -142,32 +170,27 @@ def startTest(self, test): self.write('#%s ' % self.tests[adr]) self._seen[adr] = 1 return + with LOCK: - self.tests[adr] = len(self.tests)+1 - self.id = len(self.tests)+1 - # self.write(str(dict(self.tests))) + self.id = len(self.tests) + 1 + self.tests[adr] = self.id self.write('#%s ' % self.id) - # self.id += 1 def finalize(self, result): """Save new ids file, if needed. """ ids = dict(self.ids) source_names = list(self.source_names) - failed = list(self.failed) + failed = [] if result.wasSuccessful() else list(self.failed) tests = dict(self.tests) - if result.wasSuccessful(): - failed = [] if self.collecting: ids = dict(list(zip(list(tests.values()), list(tests.keys())))) - else: - pass - fh = open(self.idfile, 'wb') - dump({'ids': ids, - 'failed': failed, - 'source_names': source_names}, fh) - fh.close() + + with open(self.idfile, 'wb') as fh: + dump({'ids': ids, + 'failed': failed, + 'source_names': source_names}, fh) def parse_test_name(test): @@ -180,5 +203,6 @@ def parse_test_name(test): test_class, test_name = class_and_name, None return test_file, test_class, test_name + # do not collect parse_test_name.__test__ = False diff --git a/setup.py b/setup.py index 9a3bf8c..ed1704c 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ setup( name='lode_runner', url='https://github.com/2gis/lode_runner', - version='0.4.4', + version='0.4.5', description='Nosetests runner plugins package', long_description='', author='Igor Pavlov',