Differences: nose2 vs nose vs unittest2

nose2 is not nose

What’s Different

Python Versions

nose supports Python 2.4 and above, but nose2 only supports Python versions currently supported by the Python team.

Test Discovery and Loading

nose loads test modules lazily: tests in the first-loaded module are executed before the second module is imported. nose2 loads all tests first, then begins test execution. This has some important implications.

First, it means that nose2 does not need a custom importer. nose2 imports test modules with __import__().

Second, it means that nose2 does not support all of the test project layouts that nose does. Specifically, projects that look like this will fail to load tests correctly with nose2:

.
`-- tests
    |-- more_tests
    |   `-- test.py
    `-- test.py

To nose’s loader, those two test modules look like different modules. But to nose2’s loader, they look the same, and will not load correctly.

Test Fixtures

nose2 supports only the same levels of fixtures as unittest2. This means class level fixtures and module level fixtures are supported, but package-level fixtures are not. In addition, unlike nose, nose2 does not attempt to order tests named on the command-line to group those with the same fixtures together.

Parameterized and Generator Tests

nose2 supports more kinds of parameterized and generator tests than nose, and supports all test generators in test functions, test classes, and in unittest TestCase subclasses. nose supports them only in test functions and test classes that do not subclass unittest.TestCase. See: Loader: Test Generators and Loader: Parameterized Tests for more.

Configuration

nose expects plugins to make all of their configuration parameters available as command-line options. nose2 expects almost all configuration to be done via configuration files. Plugins should generally have only one command-line option: the option to activate the plugin. Other configuration parameters should be loaded from config files. This allows more repeatable test runs and keeps the set of command-line options small enough for humans to read. See: Configuring nose2 for more.

Plugin Loading

nose uses setuptools entry points to find and load plugins. nose2 does not. Instead, nose2 requires that all plugins be listed in config files. This ensures that no plugin is loaded into a test system just by virtue of being installed somewhere, and makes it easier to include plugins that are part of the project under test. See: Configuring nose2 for more.

Limited support for python setup.py test

nose2 supports setuptools’ python setup.py test command, but via very different means than nose. To avoid the internal complexity forced on nose by the fact that the setuptools test command can’t be configured with a custom test runner, when run this way, nose2 essentially hijacks the test running process. The “test suite” that nose2.collector.collector() returns actually is a test runner, cloaked inside of a test case. It loads and runs tests as normal, setting up its own test runner and test result, and calls sys.exit() itself – completely bypassing the test runner and test result that setuptools/unittest create. This may be incompatible with some projects.

Plugin API

nose2 implements a new plugin API based on the work done by Michael Foord in unittest2’s plugins branch. This API is greatly superior to the one in nose, especially in how it allows plugins to interact with each other. But it is different enough from the API in nose that supporting nose plugins in nose2 is not practical: plugins must be rewritten to work with nose2. See: Writing Plugins for more.

Missing Plugins

nose2 does not include some of the more commonly-used plugins in nose. Some of nose’s builtin plugins could not be ported to nose2 due to differences in internals. See: Plugins for nose2 for information on the plugins built in to nose2.

Internals

nose wraps or replaces everything in unittest. nose2 does a bit less: it does not wrap TestCases, and does not wrap the test result class with a result proxy. nose2 does subclass TestProgram, and install its own loader, runner, and result classes. It does this unconditionally, rather than allowing arguments to TestProgram.__init__() to specify the test loader and runner. See Internals for more information.

License

While nose was LGPL, nose2 is BSD licensed. This change was made at the request of the majority of nose contributors.

What’s the Same

Philosophy

nose2 has the same goals as nose: to extend unittest to make testing nicer and easier to understand. It aims to give developers flexibility, power and transparency, so that common test scenarios require no extra work, and uncommon test scenarios can be supported with minimal fuss and magic.

nose2 is not (exactly) unittest2/plugins

nose2 is based on the unittest2 plugins branch, but differs from it in several substantial ways. The event api not exactly the same because nose2 can’t replace unittest.TestCase, and does not configure the test run or plugin set globally. nose2 also has a wholly different reporting API from unittest2’s plugins, to better support some common cases (like adding extra information to error output). nose2 also defers more work to plugins than unittest2: the test loader, runner and result are just plugin callers, and all of the logic of test discovery, running and reporting is implemented in plugins. This means that unlike unittest2, nose2 includes a substantial set of plugins that are active by default.