Skip to content

Commit

Permalink
Implement support for unittest.expectedFailure
Browse files Browse the repository at this point in the history
Fixes issue nose-devs#33
  • Loading branch information
csdev committed Jan 5, 2015
1 parent e2b1749 commit a9b846a
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 1 deletion.
6 changes: 6 additions & 0 deletions functional_tests/support/expected_failure/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import unittest

class TC(unittest.TestCase):
@unittest.expectedFailure
def test(self):
assert False
6 changes: 6 additions & 0 deletions functional_tests/support/unexpected_success/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import unittest

class TC(unittest.TestCase):
@unittest.expectedFailure
def test(self):
pass
23 changes: 23 additions & 0 deletions functional_tests/test_expected_failure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import os
import unittest
from nose.plugins.plugintest import PluginTester, remove_timings

support = os.path.join(os.path.dirname(__file__), 'support')


class TestExpectedFailure(PluginTester, unittest.TestCase):
activate = '-v'
plugins = []
suitepath = os.path.join(support, 'expected_failure')

def test_expected_failure(self):
print self.output
output = remove_timings(str(self.output))
assert output == """\
test (test.TC) ... expected failure
----------------------------------------------------------------------
Ran 1 test in ...s
OK (expectedFailures=1)
"""
23 changes: 23 additions & 0 deletions functional_tests/test_unexpected_success.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import os
import unittest
from nose.plugins.plugintest import PluginTester, remove_timings

support = os.path.join(os.path.dirname(__file__), 'support')


class TestExpectedFailure(PluginTester, unittest.TestCase):
activate = '-v'
plugins = []
suitepath = os.path.join(support, 'unexpected_success')

def test_expected_failure(self):
print self.output
output = remove_timings(str(self.output))
assert output == """\
test (test.TC) ... unexpected success
----------------------------------------------------------------------
Ran 1 test in ...s
FAILED (unexpectedSuccesses=1)
"""
16 changes: 16 additions & 0 deletions nose/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,17 @@ def addSkip(self, test, reason):
plugins.addError(self.test, (SkipTest, reason, None))
self.result.addSkip(self.test, reason)

def addExpectedFailure(self, test, err):
self.assertMyTest(test)
self.result.addExpectedFailure(self.test, self._prepareErr(err))

def addUnexpectedSuccess(self, test):
self.assertMyTest(test)
self.test.passed = False
self.result.addUnexpectedSuccess(self.test)
if self.config.stopOnError:
self.shouldStop = True

def addSuccess(self, test):
self.assertMyTest(test)
self.plugins.addSuccess(self.test)
Expand All @@ -184,5 +195,10 @@ def stopTest(self, test):
"""Tests that raised an exception""")
failures = proxied_attribute('result', 'failures',
"""Tests that failed""")
expectedFailures = proxied_attribute('result', 'expectedFailures',
"""Tests that failed as expected""")
unexpectedSuccesses = proxied_attribute('result', 'unexpectedSuccesses',
"""Tests that passed
unexpectedly""")
testsRun = proxied_attribute('result', 'testsRun',
"""Number of tests run""")
6 changes: 5 additions & 1 deletion nose/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ def printSummary(self, start, stop):
summary['failures'] = len(self.failures)
if len(self.errors):
summary['errors'] = len(self.errors)
if len(self.expectedFailures):
summary['expectedFailures'] = len(self.expectedFailures)
if len(self.unexpectedSuccesses):
summary['unexpectedSuccesses'] = len(self.unexpectedSuccesses)

if not self.wasSuccessful():
write("FAILED")
Expand All @@ -155,7 +159,7 @@ def wasSuccessful(self):
lists that are marked as errors and should cause a run to
fail.
"""
if self.errors or self.failures:
if self.errors or self.failures or self.unexpectedSuccesses:
return False
for cls in self.errorClasses.keys():
storage, label, isfail = self.errorClasses[cls]
Expand Down
21 changes: 21 additions & 0 deletions unit_tests/test_result_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def test_proxy_has_basic_methods(self):
proxy = ResultProxy(res, test=None)

methods = [ 'addError', 'addFailure', 'addSuccess',
'addExpectedFailure', 'addUnexpectedSuccess',
'startTest', 'stopTest', 'stop' ]
for method in methods:
m = getattr(proxy, method)
Expand Down Expand Up @@ -51,13 +52,16 @@ def runTest(self):
proxy.addError(test, err)
proxy.addFailure(test, err)
proxy.addSuccess(test)
proxy.addExpectedFailure(test, err)
proxy.addUnexpectedSuccess(test)
proxy.startTest(test)
proxy.stopTest(test)
proxy.beforeTest(test)
proxy.afterTest(test)
proxy.stop()
proxy.shouldStop = 'yes please'
for method in ['addError', 'addFailure', 'addSuccess',
'addExpectedFailure', 'addUnexpectedSuccess',
'startTest', 'stopTest', 'beforeTest', 'afterTest',
'stop']:
assert method in res.called, "%s was not proxied"
Expand All @@ -68,6 +72,8 @@ def test_attributes_are_proxied(self):
proxy = ResultProxy(res, test=None)
proxy.errors
proxy.failures
proxy.expectedFailures
proxy.unexpectedSuccesses
proxy.shouldStop
proxy.testsRun

Expand Down Expand Up @@ -160,6 +166,21 @@ def runTest(self):
assert proxy.shouldStop
assert res.shouldStop

def test_stop_on_unexpected_success(self):
from nose.case import Test
class TC(unittest.TestCase):
@unittest.expectedFailure
def runTest(self):
pass
conf = Config(stopOnError=True)
test = TC()
case = Test(test)
res = unittest.TestResult()
proxy = ResultProxy(res, case, config=conf)
case(proxy)
assert proxy.shouldStop
assert res.shouldStop

def test_coercion_of_custom_exception(self):
from nose.case import Test

Expand Down

0 comments on commit a9b846a

Please sign in to comment.