Latest update Android YouTube

NOSE | Testing in Python

Python Testing with nose: The Complete Guide

Mastering test discovery, execution, and extensibility with nose

1. Test Discovery

Basic Discovery Rules

nose automatically discovers tests following these conventions:

Pattern Description
test_*.py Files starting with "test_"
*_test.py Files ending with "_test"
Test* classes Classes starting with "Test"
test_* functions Functions starting with "test"
project/
├── tests/
│ ├── test_math.py
│ ├── string_utils_test.py
│ └── integration/
│ └── test_api.py

Advanced Discovery

# Customize discovery with nose.cfg
[nosetests]
match=^(check|validate)_
exclude=^skip_
where=tests/integration
exclude-dir=legacy_tests
nosetests --match="^integration_" Run tests matching pattern
nosetests --exclude="^slow_" Exclude matching tests
nosetests --where=tests/unit Search specific directory

Performance Optimization

# Run tests in parallel (4 processes)
nosetests --processes=4

# Cache discovered tests between runs
nosetests --with-cache

# Limit discovery depth
nosetests --no-recursive

2. Plugins System

Built-in Plugins

Plugin Command Purpose
xunit --with-xunit JUnit XML output
cover --with-coverage Code coverage reporting
prof --with-profile Performance profiling
doctests --with-doctest Run doctests

Custom Plugin Development

import nose.plugins.Plugin

class TimingPlugin(nose.plugins.Plugin):
    name = 'timing'
    
    def options(self, parser, env):
        super().options(parser, env)
        parser.add_option('--min-time', type=float, default=1.0)
        
    def configure(self, options, conf):
        self.min_time = options.min_time
        
    def beforeTest(self, test):
        self._start = time.time()
        
    def afterTest(self, test):
        duration = time.time() - self._start
        if duration > self.min_time:
            print(f"Slow test: {test.id()} ({duration:.2f}s)")

Popular Third-party Plugins

  • nose-parameterized: Data-driven testing with decorators
  • nose-progressive: Cleaner output with progress bars
  • nose-timer: Measure test execution time
  • nose-exclude: Exclude specific tests from runs

3. Execution Control

Test Selection

# Run specific test module
nosetests tests/test_math.py

# Run tests matching pattern
nosetests -m "test_addition"

# Run tests with custom attribute
nosetests -a '!slow'

Execution Options

--stop Stop after first failure
--failed Run only previously failed tests
--randomize Run tests in random order
--process-timeout=300 Set timeout for parallel tests

4. Advanced Features

Fixtures

def setup_module():
    """Module-level setup"""
    print("Setting up module")

def teardown_module():
    """Module-level teardown"""
    print("Tearing down module")

class TestExample:
    @classmethod
    def setup_class(cls):
        """Class-level setup"""
        cls.shared = Resource()
    
    def setup(self):
        """Test-level setup"""
        self.value = 42
        
    def test_example(self):
        assert self.value == 42
        
    def teardown(self):
        """Test-level teardown"""
        del self.value

Test Generators

def test_multiple_cases():
    """Generator creates multiple test cases"""
    for input, expected in [
        (1+1, 2),
        (2*3, 6),
        (9-5, 4)
    ]:
        yield check_result, input, expected

def check_result(input, expected):
    assert input == expected

Multi-process Testing

# Run tests in parallel (4 processes)
nosetests --processes=4 --process-timeout=60

# With coverage (requires special handling)
nosetests --processes=4 --with-coverage --cover-process-start

Warning: Parallel testing requires tests to be properly isolated. Avoid shared state between tests when using --processes.

5. Integration & Extensibility

CI/CD Integration

# .travis.yml example for nose
language: python
python:
  - "3.8"
  - "3.9"
install:
  - pip install nose coverage
script:
  - nosetests --with-xunit --with-coverage --cover-package=myapp

Debugging Support

# Run with PDB on failure
nosetests --pdb

# Post-mortem debugging
nosetests --pdb-failures

# Drop to debugger on specific test
from nose.tools import set_trace
def test_debugging():
    set_trace()  # Execution pauses here
    assert 1 + 1 == 2

6. Migration & Alternatives

Transitioning to nose2/pytest

Feature nose pytest
Test discovery test_*.py test_*.py + more
Fixtures setup/teardown Flexible fixture system
Plugins Rich ecosystem Larger ecosystem

When to Choose nose

  • Maintaining legacy test suites
  • Dependency on specific nose plugins
  • Team familiarity with nose idioms

7. Complete Example

# test_math_operations.py
from nose.tools import assert_equal, assert_raises

def test_addition():
    """Test basic addition"""
    assert_equal(1 + 1, 2)

def test_division():
    """Test division with exception"""
    with assert_raises(ZeroDivisionError):
        1 / 0

class TestMathOperations:
    """Group of math operation tests"""
    
    @classmethod
    def setup_class(cls):
        cls.precision = 2
    
    def test_multiplication(self):
        assert_equal(2 * 3, 6)
    
    def test_floating_point(self):
        result = 0.1 + 0.2
        assert abs(result - 0.3) < 10**-self.precision

def test_generator():
    """Data-driven test using generator"""
    test_data = [
        (2, 2, 4),
        (3, 3, 9),
        (4, 4, 16)
    ]
    for a, b, expected in test_data:
        yield check_multiplication, a, b, expected

def check_multiplication(a, b, expected):
    assert_equal(a * b, expected)

Pro Tip: Use nosetests --with-doctest to combine nose tests with doctests in the same codebase for comprehensive testing.

Post a Comment

Feel free to ask your query...
Cookie Consent
We serve cookies on this site to analyze traffic, remember your preferences, and optimize your experience.
Oops!
It seems there is something wrong with your internet connection. Please connect to the internet and start browsing again.
AdBlock Detected!
We have detected that you are using adblocking plugin in your browser.
The revenue we earn by the advertisements is used to manage this website, we request you to whitelist our website in your adblocking plugin.
Site is Blocked
Sorry! This site is not available in your country.