[Patches] [ python-Patches-1034053 ] unittest.py patch: add skipped test functionality

SourceForge.net noreply at sourceforge.net
Thu Sep 30 16:20:30 CEST 2004


Patches item #1034053, was opened at 2004-09-24 16:08
Message generated for change (Comment added) made by purcell
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1034053&group_id=5470

Category: Library (Lib)
Group: Python 2.4
Status: Open
Resolution: None
Priority: 5
Submitted By: Remy Blank (remyblank)
Assigned to: Steve Purcell (purcell)
Summary: unittest.py patch: add skipped test functionality

Initial Comment:
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 test unconditionally
  TestCase.skipIf(expr, msg): skips test 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 can generate a patch for a more 
recent version if desired. I attached the patch against 
the original (unittest_skip.patch). I can provide a 
complete test suite for the new functionality and a usage 
example program.


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 example program 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)

----------------------------------------------------------------------

>Comment By: Steve Purcell (purcell)
Date: 2004-09-30 16:20

Message:
Logged In: YES 
user_id=21477

Yes, that's right, and I would consider providing a number of such 
decorators at a later date. I've just spent a little time chatting to my 
colleage Joe Walnes (of nMock fame) about all this; he's more of an 
nUnit authority than I am. 
 
Categories are particularly interesting. In theory, it would be possible 
to get the same effect using TestSuites, but in practice tool support 
(including unittest.main()) discourages the use of TestSuites in favour 
of magic discovery of test cases; categories would be a better way of 
allowing tools to dynamically construct suites. @ignore could be 
considered equivalent to @category("ignored") in a certain sense. 
 
Skipping is not quite the same as ignoring, since it's determined at 
run-time, and so I think it is appropriate to add methods to explicitly 
support it. 
 
Interesting times indeed. 

----------------------------------------------------------------------

Comment By: Remy Blank (remyblank)
Date: 2004-09-30 15:46

Message:
Logged In: YES 
user_id=568100

Speaking of decorators, the NUnit example is quite
instructive, re. their use of attributes to mark classes as
test cases, methods as test methods, grouping tests by
category, and for that matter ignoring tests temporarily. I
expect all of this can be done with decorators: @testMethod
to mark individual tests, @category("LongRunning"), @ignore,
@explicit, ...

And if I'm not mistaken all of this can be added without
breaking backward compatibility.

Interesting times lay ahead!

----------------------------------------------------------------------

Comment By: Steve Purcell (purcell)
Date: 2004-09-30 13:31

Message:
Logged In: YES 
user_id=21477

I've been really tied up; sorry for the delayed response, but I've been 
reading all the comments on this patch. 
 
Overall, I'm leaning in favour of accepting this patch, probably with 
some minor changes to the way skipped tests are reported. 
 
The concept of skipping is one that has been kept out of JUnit, but is 
found in NUnit and is well regarded there. In my XP coaching work 
ThoughtWorks I see an obscenely large number of JUnit tests, and a 
common mistake is to comment out test method bodies, leading to 
"false passes". Explicit support for skipping in unittest would mitigate 
this. 
 
I agree with Remy that the decorator example, though ingenious, has 
the wrong result; skipped tests will be reported as successes. In order 
for a test method to decide if it should be skipped, it will often need 
information from 'self' that was gathered during setUp() -- this makes 
decorators cumbersome for this. Also, a decorator solution would not 
allow test methods to skip if the setUp() method itself decides to skip(). 
 
Please give me a few more days on this, and I'll work on integrating 
and tweaking the patch. 

----------------------------------------------------------------------

Comment By: Remy Blank (remyblank)
Date: 2004-09-30 11:37

Message:
Logged In: YES 
user_id=568100

I strongly disagree. Skipped tests should not just be
transformed into passed tests, but must be recorded as
skipped and reported to the user. Knowing that a test
skipped is important information.

The Python regression tests (although I'm not familiar with
them) provide the same "skip" functionality, and I don't
think people would be happy to replace it with just "pass".

The decorator approach is an interesting idea, though, and
could be combined with skipIf() so as to provide the other
advantages you mention, namely single definition and
appearance prior to definition. Something along the following:

def rootOnly(f):
        """Decorator to skip tests that require root access"""
        def wrapper(self):
                self.skipIf(os.getuid() != 0, "Must be root")
                self.f()
        wrapper.__doc__ = f.__doc__
        return wrapper


class ReadShadowTest(unittest.TestCase):
        """Read access to /etc/shadow"""
        @rootOnly
        def testReadingAsRoot(self):
                """Reading /etc/shadow as root"""
                open("/etc/shadow").close()

Note that I'm not yet familiar with decorators, so the
wrapper() function might not be the correct way to do this.

----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2004-09-30 10:04

Message:
Logged In: YES 
user_id=80475

After more thought, I think decorators offer a cleaner, more
complete solution without further complicating the unittest
module.

def rootonly(f):
    "Decorator to skip tests that require root access"
    if os.geteuid() == 0:
        return f
    return lambda self: 0


@rootonly
def testReadingAsRoot(self):
   . . .


Note the rootonly() decorator need only be defined once
instead of writing a full self.skipIf(condition) inside
every test.  Also, it appears prior to the definition rather
than inside.  The approach is more flexible than the
original proposal though it does lack a reporting mechanism.

----------------------------------------------------------------------

Comment By: Nick Coghlan (ncoghlan)
Date: 2004-09-29 08:36

Message:
Logged In: YES 
user_id=1038590

I'd certainly find such a feature handy - when testing
different variations of an embedded firmware image, it would
make it much easier to enable/disable different tests based
on the capabilities of the firmware.

Ditto for the original example of cross-platform testing.

----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2004-09-26 12:13

Message:
Logged In: YES 
user_id=80475

The skipIf() method is sufficient.  From there, it is
trivial to roll your own resource check.

----------------------------------------------------------------------

Comment By: Wummel (calvin)
Date: 2004-09-26 11:10

Message:
Logged In: YES 
user_id=9205

This is a nice patch. I am wondering if it can be extended
to support the resource idea used in the python regression
tests. That is the user has a --resource option to give a
list of available resources and a test only runs if its
requested resources are available. Otherwise it will be skipped.
Example:
TestDemo.py --resource=network --resource=audio
... would supply the network and audio resource.
Or does it make more sense to put this in a separate patch?

----------------------------------------------------------------------

Comment By: Remy Blank (remyblank)
Date: 2004-09-25 12:54

Message:
Logged In: YES 
user_id=568100

Added sample code.

----------------------------------------------------------------------

Comment By: Remy Blank (remyblank)
Date: 2004-09-25 12:53

Message:
Logged In: YES 
user_id=568100

The test suite for the added functionality.

----------------------------------------------------------------------

Comment By: Remy Blank (remyblank)
Date: 2004-09-25 12:51

Message:
Logged In: YES 
user_id=568100

I don't think so. Basically, the patch changes the following:
 - Adds a class SkippedException to the unittest module
 - Adds a skipped attribute to TestResult, containing the list of skipped 
tests, and an addSkipped() method to add to the list.
 - Catches the SkippedException in TestCase.__call__()
 - Adds skip() and skipIf() to TestCase
 - Modifies _TextTestResult and TextTestRunner to report skipped tests 
*only if there are any*

I see two potential problems:
 - Test runners based on (or using the output of) TextTestRunner. I've 
taken care that the output is unchanged if there are no skipped tests.
 - Code that uses repr() of a TestResult, as I extended it to always report 
skipped tests. I think this would be bad practice anyway.

However, to use the test-skipping functionality, custom test runners will 
obviously need to be extended to report skipped tests.

OTOH, I don't have a big test codebase to check. I read that e.g. Zope is 
using unittest. Maybe I can try to run their test suite with the patched 
unittest.py. I'll check.

----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2004-09-25 10:18

Message:
Logged In: YES 
user_id=80475

Will this muck up some the existing test runners that people
have written?

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1034053&group_id=5470


More information about the Patches mailing list