472,984 Members | 1,927 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,984 software developers and data experts.

unittest.py patch: add skipped test functionality

Ok, here we go.

I added the possibility for tests using the unittest.py framework
to be skipped. Basically, I added two methods to TestCase:

TestCase.skip(msg): skips unconditionally
TestCase.skipIf(expr, msg): skips if expr is true

These can be called either in setUp() or in the test methods. I also
added reporting of skipped tests to TestResult, _TextTestResult and
TextTestRunner. If no tests are skipped, everything should be the
same as before.

I am using Python 2.3.3, so the changes are against the file in that
version. I attached the patch against the original
(unittest_skip.patch), a complete test suite for the new functionality
(testSkippedTest.py) and a usage example (SkippedTestDemo.py).

I would welcome any feedback about the idea, the implementation,
suggestions for improvements, fixes, etc.

I would also like to know if this would be a candidate for inclusion
into the unittest.py provided with Python. I suppose I should
contact Steve Purcell directly for that.

-- Remy

Quick usage example:

class ReadShadowTest(unittest.TestCase):
"""Read access to /etc/shadow"""
def testReadingAsRoot(self):
"""Reading /etc/shadow as root"""
self.skipIf(os.geteuid() != 0, "Must be root")
open("/etc/shadow").close()
The attached example (SkippedTestDemo.py) produces the following output:

$ ./SkippedTestDemo.py -v
Access to autoexec.bat ... SKIPPED (Only available on Windows)
Access to config.sys ... SKIPPED (Only available on Windows)
Reading /etc/shadow as root ... SKIPPED (Must be root)
Reading /etc/shadow as non-root ... ok

----------------------------------------------------------------------
Ran 4 tests in 0.004s

OK (skipped=3)

--- unittest.py.orig 2004-09-24 10:33:21.933370804 +0200
+++ unittest.py 2004-09-24 02:21:25.000000000 +0200
@@ -75,6 +75,8 @@
def _strclass(cls):
return "%s.%s" % (cls.__module__, cls.__name__)

+class SkipException(Exception): pass
+
class TestResult:
"""Holder for test result information.

@@ -89,6 +91,7 @@
def __init__(self):
self.failures = []
self.errors = []
+ self.skipped = []
self.testsRun = 0
self.shouldStop = 0

@@ -111,6 +114,11 @@
returned by sys.exc_info()."""
self.failures.append((test, self._exc_info_to_string(err)))

+ def addSkipped(self, test, err):
+ """Called when a test is skipped. 'err' is a tuble of values as
+ returned by sys.exc_info()."""
+ self.skipped.append((test, str(err[1])))
+
def addSuccess(self, test):
"Called when a test has completed successfully"
pass
@@ -128,9 +136,9 @@
return string.join(traceback.format_exception(*err), '')

def __repr__(self):
- return "<%s run=%i errors=%i failures=%i>" % \
+ return "<%s run=%i errors=%i failures=%i skipped=%i>" % \
(_strclass(self.__class__), self.testsRun, len(self.errors),
- len(self.failures))
+ len(self.failures), len(self.skipped))
class TestCase:
@@ -218,6 +226,9 @@
try:
try:
self.setUp()
+ except SkipException:
+ result.addSkipped(self, self.__exc_info())
+ return
except KeyboardInterrupt:
raise
except:
@@ -230,6 +241,8 @@
ok = 1
except self.failureException:
result.addFailure(self, self.__exc_info())
+ except SkipException:
+ result.addSkipped(self, self.__exc_info())
except KeyboardInterrupt:
raise
except:
@@ -346,6 +359,13 @@

assert_ = failUnless

+ def skip(self, msg=None):
+ """Skip the test, with the given message."""
+ raise SkipException, msg
+
+ def skipIf(self, expr, msg=None):
+ """Skip the test if the expression is true."""
+ if expr: raise SkipException, msg
class TestSuite:
@@ -623,6 +643,16 @@
elif self.dots:
self.stream.write('F')

+ def addSkipped(self, test, err):
+ TestResult.addSkipped(self, test, err)
+ if self.showAll:
+ msg = str(err[1])
+ if msg:
+ msg = " (" + msg + ")"
+ self.stream.writeln("SKIPPED" + msg)
+ elif self.dots:
+ self.stream.write('S')
+
def printErrors(self):
if self.dots or self.showAll:
self.stream.writeln()
@@ -666,15 +696,20 @@
self.stream.writeln()
if not result.wasSuccessful():
self.stream.write("FAILED (")
- failed, errored = map(len, (result.failures, result.errors))
+ failed, errored, skipped = map(len, (result.failures, result.errors, result.skipped))
if failed:
self.stream.write("failures=%d" % failed)
if errored:
if failed: self.stream.write(", ")
self.stream.write("errors=%d" % errored)
+ if skipped:
+ self.stream.write(", skipped=%d" % skipped)
self.stream.writeln(")")
else:
- self.stream.writeln("OK")
+ if result.skipped:
+ self.stream.writeln("OK (skipped=%d)" % len(result.skipped))
+ else:
+ self.stream.writeln("OK")
return result

#!/usr/bin/env python
"""\
testSkippedTest.py Test cases for adding skipped tests to unittest.py
Copyright (C) 2004 Remy Blank
"""

import unittest
import sys
from cStringIO import StringIO

# Dummy test cases
class SkipInTest(unittest.TestCase):
"""Tests skip in test methods"""
def testDoesntSkip(self):
"""Doesn't skip"""
self.assert_(True)

def testFails(self):
"""Fails"""
self.fail()

def testSkips(self):
"""Test skips"""
self.skip()

def testSkipsMessage(self):
"""Test skips with a message"""
self.skip("A message")
class SkipInSetUp(unittest.TestCase):
"""Tests skip in setUp()"""
def setUp(self):
super(SkipInSetUp, self).setUp()
self.skip()

def testDummy(self):
"""Never executed"""
# Test cases
class TestResultTest(unittest.TestCase):
"""Tests relating to TestResult"""
def testSkippedAttribute(self):
"""List of skipped tests"""
result = unittest.TestResult()
self.assertEqual([], result.skipped)
self.assertEqual("<unittest.TestResult run=0 errors=0 failures=0 skipped=0>", repr(result))

def testAddSkipped(self):
"""TestResult.addSkipped()"""
result = unittest.TestResult()
test = SkipInTest("testDoesntSkip")
try:
raise unittest.SkipException, "Skipped"
except:
result.addSkipped(test, sys.exc_info())

self.assert_(test is result.skipped[0][0])
self.assertEqual("Skipped", result.skipped[0][1])
self.assertEqual("<unittest.TestResult run=0 errors=0 failures=0 skipped=1>", repr(result))
class TestCaseTest(unittest.TestCase):
"""Tests relating to TestCase"""
def setUp(self):
super(TestCaseTest, self).setUp()
self.result = unittest.TestResult()

def testNoSkip(self):
"""Test case that doesn't skip"""
test = SkipInTest("testDoesntSkip")
test(self.result)

self.assertEqual(1, self.result.testsRun)
self.assertEqual([], self.result.skipped)

def testSkipInTest(self):
"""Test case that skips in test method"""
test = SkipInTest("testSkips")
test(self.result)

self.assertEqual(1, self.result.testsRun)
self.assertEqual([], self.result.failures)
self.assertEqual([], self.result.errors)
self.assert_(test is self.result.skipped[0][0])

def testSkipInSetUp(self):
"""Test case that skips in setUp()"""
test = SkipInSetUp("testDummy")
test(self.result)

self.assertEqual(1, self.result.testsRun)
self.assertEqual([], self.result.failures)
self.assertEqual([], self.result.errors)
self.assert_(test is self.result.skipped[0][0])
class SkipMethodsTest(unittest.TestCase):
"""Tests for skip() methods"""
def setUp(self):
super(SkipMethodsTest, self).setUp()
self.test = SkipInTest("testDoesntSkip")

def catchSkipException(self, callable, *args, **kwargs):
try:
callable(*args, **kwargs)
except unittest.SkipException, e:
return e
return None

def testSkip(self):
"""skip()"""
e = self.catchSkipException(self.test.skip)
self.assertNotEqual(None, e)

def testSkipMessage(self):
"""skip(message)"""
e = self.catchSkipException(self.test.skip, "A message")
self.assertNotEqual(None, e)
self.assertEqual("A message", str(e))

def testSkipIfFalse(self):
"""skipIf(False)"""
e = self.catchSkipException(self.test.skipIf, False)
self.assertEqual(None, e)

def testSkipIfTrue(self):
"""skipIf(True)"""
e = self.catchSkipException(self.test.skipIf, True)
self.assertNotEqual(None, e)

def testSkipIfTrueMessage(self):
"""skipIf(True, message)"""
e = self.catchSkipException(self.test.skipIf, True, "Another message")
self.assertNotEqual(None, e)
self.assertEqual("Another message", str(e))
class TextTestResultTest(unittest.TestCase):
"""Tests for _TextTestResult"""
def setUp(self):
super(TextTestResultTest, self).setUp()
self.out = unittest._WritelnDecorator(StringIO())

def testNoSkippingQuiet(self):
"""No skipping, verbosity=1"""
result = unittest._TextTestResult(self.out, True, 1)
test = SkipInTest("testDoesntSkip")
test(result)

self.assertEqual(".", self.out.getvalue())

def testNoSkippingVerbose(self):
"""No skipping, verbosity=2"""
result = unittest._TextTestResult(self.out, True, 2)
test = SkipInTest("testDoesntSkip")
test(result)

self.assertEqual("Doesn't skip ... ok\n", self.out.getvalue())

def testSkippingQuiet(self):
"""Skipping, verbosity=1"""
result = unittest._TextTestResult(self.out, True, 1)
test = SkipInTest("testSkips")
test(result)

self.assertEqual("S", self.out.getvalue())

def testSkippingVerbose(self):
"""Skipping, verbosity=2"""
result = unittest._TextTestResult(self.out, True, 2)
test = SkipInTest("testSkips")
test(result)

self.assertEqual("Test skips ... SKIPPED\n", self.out.getvalue())

def testSkippingMessageVerbose(self):
"""Skipping with a message, verbosity=2"""
result = unittest._TextTestResult(self.out, True, 2)
test = SkipInTest("testSkipsMessage")
test(result)

self.assertEqual("Test skips with a message ... SKIPPED (A message)\n", self.out.getvalue())
class TextTestRunnerTest(unittest.TestCase):
"""Tests for TextTestRunner"""
def setUp(self):
super(TextTestRunnerTest, self).setUp()
self.out = unittest._WritelnDecorator(StringIO())

def testOkNoSkips(self):
"""All tests OK, no skips"""
runner = unittest.TextTestRunner(self.out, True)
test = SkipInTest("testDoesntSkip")
runner.run(test)

self.assert_(self.out.getvalue().endswith("OK\n"))

def testOkSkip(self):
"""All tests OK, one skip"""
runner = unittest.TextTestRunner(self.out, True)
test = SkipInTest("testSkips")
runner.run(test)

self.assert_(self.out.getvalue().endswith("OK (skipped=1)\n"))

def testFailedNoSkip(self):
"""Failed test, no skips"""
runner = unittest.TextTestRunner(self.out, True)
test = SkipInTest("testFails")
runner.run(test)

self.assert_(self.out.getvalue().endswith("FAILED (failures=1)\n"))

def testFailedSkip(self):
"""Failed test, one skip"""
runner = unittest.TextTestRunner(self.out, True)
test = unittest.TestSuite((SkipInTest("testFails"), SkipInTest("testSkips")))
runner.run(test)

self.assert_(self.out.getvalue().endswith("FAILED (failures=1, skipped=1)\n"))
if __name__ == "__main__":
unittest.TestProgram(argv=sys.argv + ["TestResultTest", "TestCaseTest",
"SkipMethodsTest", "TextTestResultTest", "TextTestRunnerTest"])

#!/usr/bin/env python
"""\
SkippedTestDemo.py Demo usage for skipped tests in unittest.py
Copyright (C) 2004 Remy Blank
"""

import unittest
import os
class ReadShadowTest(unittest.TestCase):
"""Read access to /etc/shadow"""
def testReadingAsRoot(self):
"""Reading /etc/shadow as root"""
self.skipIf(os.geteuid() != 0, "Must be root")
open("/etc/shadow").close()

def testReadingAsUser(self):
"""Reading /etc/shadow as non-root"""
isRoot = os.geteuid() == 0
if isRoot: # Can run this test even as root
os.seteuid(500)
self.assertRaises(IOError, open, "/etc/shadow")
if isRoot:
os.seteuid(0)
class BootFileTest(unittest.TestCase):
"""Boot file access"""
def setUp(self):
super(BootFileTest, self).setUp()
self.skipIf(os.name != "nt", "Only available on Windows")

def testConfigSys(self):
"""Access to config.sys"""
open("c:\\config.sys").close()

def testAutoexecBat(self):
"""Access to autoexec.bat"""
open("c:\\autoexec.bat").close()
if __name__ == "__main__":
unittest.main()

Jul 18 '05 #1
0 1976

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Will Stuyvesant | last post by:
I have a unittest testfile like this: ----------------------- test_mod.py --------------------- import sys sys.path.append('..') import unittest import mod class...
12
by: Paul Moore | last post by:
One of the things I really dislike about Unittest (compared, say, to a number of adhoc testing tricks I've used in the past, and to Perl's "standard" testing framework) is that the...
31
by: Antoon Pardon | last post by:
I have been working with unittests lately and found that the self.failUnlessAlmostEqual, isn't as usefull as it could be. My main problem is, that it is only usefull with objects that can be...
8
by: Remy Blank | last post by:
Hello unittest users, In a project I am working on, I have a series of tests that have to be run as root, and others as a normal user. One solution is to separate the tests into two different...
41
by: Roy Smith | last post by:
I've used the standard unittest (pyunit) module on a few projects in the past and have always thought it basicly worked fine but was just a little too complicated for what it did. I'm starting a...
7
by: Jorgen Grahn | last post by:
I have a set of tests in different modules: test_foo.py, test_bar.py and so on. All of these use the simplest possible internal layout: a number of classes containing test*() methods, and the good...
2
by: Oleg Paraschenko | last post by:
Hello, I decided to re-use functionality of "unittest" module for my purposes. More precisely, I have a list of folders. For each folder, code should enter to the folder, execute a command and...
0
by: Chris Fonnesbeck | last post by:
I have built the following unit test, observing the examples laid out in the python docs: class testMCMC(unittest.TestCase): def setUp(self): # Create an instance of the sampler...
0
by: Kurt B. Kaiser | last post by:
Patch / Bug Summary ___________________ Patches : 434 open ( +3) / 3430 closed ( +5) / 3864 total ( +8) Bugs : 929 open (+13) / 6285 closed (+12) / 7214 total (+25) RFE : 245 open...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
4
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.