172

I'm trying to get started with unit testing in Python and I was wondering if someone could explain the advantages and disadvantages of doctest and unittest.

What conditions would you use each for?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Sean
  • 5,244
  • 6
  • 28
  • 27

11 Answers11

194

Both are valuable. I use both doctest and nose taking the place of unittest. I use doctest for cases where the test is giving an example of usage that is actually useful as documentation. Generally I don't make these tests comprehensive, aiming solely for informative. I'm effectively using doctest in reverse: not to test my code is correct based on my doctest, but to check that my documentation is correct based on the code.

The reason is that I find comprehensive doctests will clutter your documentation far too much, so you will either end up with either unusable docstrings, or incomplete testing.

For actually testing the code, the goal is to thoroughly test every case, rather than illustrate what is does by example, which is a different goal which I think is better met by other frameworks.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Brian
  • 116,865
  • 28
  • 107
  • 112
  • 30
    There's a lot less boilerplate, and I find tests much simpler to write (and read). The low startup cost to write tests (ie just write a "test_foo()" function and go) also helps fight off the temptation to do the interesting code bits before nailing down your tests. – Brian Dec 12 '08 at 16:56
  • What other testing frameworks do you use? Or is it exclusively nose? – Joe Apr 05 '11 at 17:54
  • 7
    Given the age of this answer it's probably worth mentioning that much of the "boilerplate" of older versions of unittest are largely gone. I still like Nose better as well, but it's pretty much a toss-up. – Adam Parkin Jun 01 '12 at 20:55
  • I find that [pytest](http://pytest.org) is often under-represented so I think I'll chime in here... I'm partial to pytest and doctest together. Using doctest as Brian describes above: to inform and to make the documentation testable. Unit tests (etc.) written using pytest. pytest as the test-runner, because [it can run doctests too](http://pytest.org/latest/doctest.html). – floer32 Jul 09 '13 at 18:37
  • I know that this post is a little old, but here are my two cents: I have been using nose for a while now as well, and would definitely reccomend it over unittest. As mentioned, unittest still has the boilerplate code to identify where the tests are. With nose, I just point it to the directory containing code, and if there is a file starting with "Test" it assumes it is a test. In fact, I just have a simple batch file to run that runs "nosetests --with-coverage --cover-html --cover-html-dir=Tests\html --cover-erase --cover-package ", and that does the coverage as well – Sbspider Jun 20 '14 at 02:29
  • 2
    FYI nose has been in "maintenance mode" for the past several years and will likely cease all development (absent 3rd-party intervention). It's maintainers recommend new projects use an alternative. – Six Mar 09 '16 at 11:38
50

I use unittest almost exclusively.

Once in a while, I'll put some stuff in a docstring that's usable by doctest.

95% of the test cases are unittest.

Why? I like keeping docstrings somewhat shorter and more to the point. Sometimes test cases help clarify a docstring. Most of the time, the application's test cases are too long for a docstring.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • Would be cool to see an example, what you think is suitable for `docstring` and what not. I actually like docstring in term's that it's explicitly showing how to use an interface, but using it both for that and unit testing might not fit well. – user1767754 Jul 10 '18 at 01:34
38

Another advantage of doctesting is that you get to make sure your code does what your documentation says it does. After a while, software changes can make your documentation and code do different things. :-)

Jason Baker
  • 192,085
  • 135
  • 376
  • 510
33

I work as a bioinformatician, and most of the code I write is "one time, one task" scripts, code that will be run only once or twice and that execute a single specific task.

In this situation, writing big unittests may be overkill, and doctests are an useful compromise. They are quicker to write, and since they are usually incorporated in the code, they allow to always keep an eye on how the code should behave, without having to have another file open. That's useful when writing small script.

Also, doctests are useful when you have to pass your script to a researcher that is not expert in programming. Some people find it very difficult to understand how unittests are structured; on the other hand, doctests are simple examples of usage, so people can just copy and paste them to see how to use them.

So, to resume my answer: doctests are useful when you have to write small scripts, and when you have to pass them or show them to researchers that are not computer scientists.

dalloliogm
  • 8,718
  • 6
  • 45
  • 55
  • 6
    "doctests are useful when you have to write small scripts, and when you have to pass them or show them to researchers that are not computer scientists." Excellent point. I do the same thing and the non-python programmers are always amazed that the documentation can be executed. – Daniel Canas Jul 14 '12 at 23:40
14

If you're just getting started with the idea of unit testing, I would start with doctest because it is so simple to use. It also naturally provides some level of documentation. And for more comprehensive testing with doctest, you can place tests in an external file so it doesn't clutter up your documentation.

I would suggest unittest if you're coming from a background of having used JUnit or something similar, where you want to be able to write unit tests in generally the same way as you have been elsewhere.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 4
    I was encouraged in this direction (`doctest` to begin with) , but eventually regretted it. For non-trivial test-cases, I lost the syntax highlighting and auto-completion of my editor. When the tests were in a separate file, I could no longer run it straight from the editor - I would have to change context back to the corresponding source file every time. – Oddthinking Nov 02 '10 at 08:06
8

I don't use doctest as a replacement for unittest. Although they overlap a bit, the two modules don't have the same function:

  • I use unittest as a unit testing framework, meaning it helps me determine quickly the impact of any modification on the rest of the code.

  • I use doctest as a guarantee that comments (namely docstrings) are still relevant to current version of the code.

The widely documented benefits of test driven development I get from unittest. doctest solves the far more subtle danger of having outdated comments misleading the maintenance of the code.

rahmu
  • 5,708
  • 9
  • 39
  • 57
7

I use unittest exclusively; I think doctest clutters up the main module too much. This probably has to do with writing thorough tests.

Tony Arkles
  • 1,946
  • 13
  • 14
7

Using both is a valid and rather simple option. The doctest module provides the DoctTestSuite and DocFileSuite methods which create a unittest-compatible testsuite from a module or file, respectively.

So I use both and typically use doctest for simple tests with functions that require little or no setup (simple types for arguments). I actually think a few doctest tests help document the function, rather than detract from it.

But for more complicated cases, and for a more comprehensive set of test cases, I use unittest which provides more control and flexibility.

davidavr
  • 14,143
  • 4
  • 27
  • 31
4

Doctest can some times lead to wrong result. Especially when output contains escape sequences. For example

def convert():
    """
    >>> convert()
    '\xe0\xa4\x95'
    """
    a = '\xe0\xa4\x95'
    return a
import doctest
doctest.testmod()

gives

**********************************************************************
File "hindi.py", line 3, in __main__.convert
Failed example:
    convert()
Expected:
    'क'
Got:
    '\xe0\xa4\x95'
**********************************************************************
1 items had failures:
   1 of   1 in __main__.convert
***Test Failed*** 1 failures. 

Also doesn't check the type of the output. It just compares the output strings. For example it have made some type rational which prints just like integer if it is a whole number. Then suppose you have function which return rational. So, a doctest won't differentiate if the output is rational whole number or a integer number.

Mangu Singh Rajpurohit
  • 10,806
  • 4
  • 68
  • 97
Harsh
  • 198
  • 1
  • 2
  • 12
  • 6
    You can use raw docstrings (`r""" ... """`) to fix the first problem. – icktoofay Jun 09 '13 at 03:32
  • Works fine in Python 3.4. To make it work in Python 2.7 as well, use `'\\xe0\\xa4\\x95'` in your docstring. – Cees Timmerman Jun 04 '15 at 12:56
  • I've also found that unicode literals also don't work with doctests (even with the right 'coding utf-8' comment line at top of file. Generally doctests aren't as well supported as unittest tests, so there are some bugs that don't get fixed. – RichVel Apr 10 '16 at 14:06
4

I almost never use doctests. I want my code to be self documenting, and the docstrings provide the documentation to the user. IMO adding hundreds of lines of tests to a module makes the docstrings far less readable. I also find unit tests easier to modify when needed.

JimB
  • 104,193
  • 13
  • 262
  • 255
3

I prefer the discovery based systems ("nose" and "py.test", using the former currently).

doctest is nice when the test is also good as a documentation, otherwise they tend to clutter the code too much.

Miki Tebeka
  • 13,428
  • 4
  • 37
  • 49
  • nose is pretty much the easiest test framework to use, IMO. It makes writing and running test cases pretty much effortless. – Kamil Kisiel Dec 12 '08 at 17:38