CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-nose2

A testing framework that extends unittest with plugins and enhanced discovery capabilities

Pending
Overview
Eval results
Files

test-tools.mddocs/

Test Tools and Decorators

Utilities for writing parameterized tests, BDD-style specifications, and enhanced test setup/teardown functionality. These tools extend unittest capabilities with modern testing patterns.

Capabilities

Parameterized Testing

Decorators for creating parameterized tests that run with multiple input values.

def params(*paramList):
    """
    Make a test function or method parameterized by parameters.
    
    Parameters may be defined as simple values or tuples. To pass a tuple
    as a simple value, wrap it in another tuple.
    
    Parameters:
    - paramList: Variable arguments, each becomes a test parameter set
    
    Returns:
    Decorator function that adds paramList attribute to test function
    
    Example:
    @params(1, 2, 3)
    def test_nums(num):
        assert num < 4
    
    @params((1, 2), (2, 3), (4, 5))  
    def test_less_than(a, b):
        assert a < b
    """

def cartesian_params(*paramList):
    """
    Make a test function or method parameterized by cartesian product of parameters.
    
    Parameters in the list must be defined as iterable objects (tuple or list).
    
    Parameters:
    - paramList: Variable arguments of iterables for cartesian product
    
    Returns:
    Decorator function that adds paramList attribute to test function
    
    Example:
    @cartesian_params((1, 2, 3), ('a', 'b'))
    def test_nums(num, char):
        assert num < ord(char)
    """

Test Setup and Teardown Decorators

Decorators for adding setup and teardown methods to function-based tests.

def with_setup(setup):
    """
    Decorator that sets the setup method to be executed before the test.
    
    Currently works only for function test cases.
    
    Parameters:
    - setup: The method to be executed before the test
    
    Returns:
    Decorator function that adds setup attribute to test function
    
    Example:
    def my_setup():
        # setup code
        pass
    
    @with_setup(my_setup)
    def test_something():
        # test code
        pass
    """

def with_teardown(teardown):
    """
    Decorator that sets the teardown method to be executed after the test.
    
    Currently works only for function test cases.
    
    Parameters:  
    - teardown: The method to be executed after the test
    
    Returns:
    Decorator function that adds tearDownFunc attribute to test function
    
    Example:
    def my_teardown():
        # teardown code
        pass
    
    @with_teardown(my_teardown)
    def test_something():
        # test code
        pass
    """

BDD-Style Testing (such)

Domain-specific language for writing behavior-driven tests with hierarchical organization and fixtures.

def A(description):
    """
    Test scenario context manager.
    
    Returns a Scenario instance, conventionally bound to 'it'.
    
    Parameters:
    - description: Description of the test scenario
    
    Returns:
    Context manager yielding Scenario instance
    
    Example:
    with such.A('calculator functionality') as it:
        # tests and fixtures
        pass
    """

class Scenario:
    """
    A test scenario that defines a set of fixtures and tests.
    """
    
    def having(self, description):
        """
        Define a new group under the current group.
        
        Context manager for creating nested test groups. Fixtures and tests
        defined within the block belong to the new group.
        
        Parameters:
        - description: Description of the test group
        
        Returns:
        Context manager yielding self
        
        Example:
        with it.having('valid input data'):
            # nested tests and fixtures
            pass
        """
    
    def uses(self, layer):
        """
        Add a layer as mixin to this group.
        
        Parameters:
        - layer: Layer class to add as mixin
        """
    
    def has_setup(self, func):
        """
        Add a setup method to this group.
        
        The setup method runs once before any tests in the containing group.
        A group may define multiple setup functions - they execute in order.
        
        Parameters:
        - func: Setup function to add
        
        Returns:
        The original function (decorator pattern)
        
        Example:
        @it.has_setup
        def setup():
            it.data = load_test_data()
        """
    
    def has_teardown(self, func):
        """
        Add a teardown method to this group.
        
        The teardown method runs once after all tests in the containing group.
        A group may define multiple teardown functions - they execute in order.
        
        Parameters:
        - func: Teardown function to add
        
        Returns:
        The original function (decorator pattern)
        
        Example:
        @it.has_teardown
        def teardown():
            cleanup_test_data()
        """
    
    def has_test_setup(self, func):
        """
        Add a test case setup method to this group.
        
        The setup method runs before each test in the containing group.
        Functions may optionally take one argument (the TestCase instance).
        
        Parameters:
        - func: Test setup function to add
        
        Example:
        @it.has_test_setup
        def setup(case):
            case.client = TestClient()
        """
    
    def has_test_teardown(self, func):
        """
        Add a test case teardown method to this group.
        
        The teardown method runs after each test in the containing group.  
        Functions may optionally take one argument (the TestCase instance).
        
        Parameters:
        - func: Test teardown function to add
        
        Example:
        @it.has_test_teardown
        def teardown(case):
            case.client.close()
        """
    
    def should(self, desc):
        """
        Define a test case.
        
        Each function marked with this decorator becomes a test case in the
        current group. Test functions may optionally take one argument
        (the TestCase instance) for executing assert methods.
        
        Parameters:
        - desc: Description of what the test should do, or the test function
                if used without arguments
        
        Returns:
        Decorator function or Case instance if desc is a function
        
        Example:
        @it.should('calculate sum correctly')
        def test_sum(case):
            result = calculator.add(2, 3)
            case.assertEqual(result, 5)
        
        @it.should
        def test_subtraction():
            \"\"\"subtract numbers correctly\"\"\"
            assert calculator.subtract(5, 3) == 2
        """
    
    def createTests(self, mod):
        """
        Generate test cases for this scenario.
        
        You must call this with globals() to generate tests from the scenario.
        If you don't call this, no tests will be created.
        
        Parameters:
        - mod: Module globals dictionary (usually globals())
        
        Example:
        it.createTests(globals())
        """

class Group:
    """A group of tests with common fixtures and description."""
    
    def __init__(self, description, indent=0, parent=None, base_layer=None):
        """
        Initialize test group.
        
        Parameters:
        - description: Group description
        - indent: Indentation level
        - parent: Parent group
        - base_layer: Base layer class
        """
    
    def addCase(self, case):
        """Add a test case to this group."""
    
    def addSetup(self, func):
        """Add a setup function to this group."""
    
    def addTeardown(self, func):
        """Add a teardown function to this group."""
    
    def child(self, description, base_layer=None):
        """Create a child group."""

class Case:
    """Information about a test case."""
    
    def __init__(self, group, func, description):
        """
        Initialize test case.
        
        Parameters:
        - group: Parent group
        - func: Test function
        - description: Test description
        """
    
    def __call__(self, testcase, *args):
        """Execute the test case with given TestCase instance."""

Usage Examples

Parameterized Tests

from nose2.tools import params, cartesian_params

# Simple parameter list
@params(1, 2, 3, 4, 5)
def test_positive_numbers(num):
    assert num > 0

# Tuple parameters
@params((1, 2, 3), (4, 5, 9), (6, 7, 13))
def test_sum(a, b, expected):
    assert a + b == expected

# Cartesian product parameters
@cartesian_params([1, 2], ['a', 'b'], [True, False])
def test_combinations(num, char, flag):
    # Test runs with all combinations: 8 total tests
    assert isinstance(num, int)
    assert isinstance(char, str)
    assert isinstance(flag, bool)

# Class method parameterization
class TestMath(unittest.TestCase):
    
    @params(0, 1, 5, 10)
    def test_square_root(self, num):
        result = math.sqrt(num * num)
        self.assertEqual(result, num)

Setup and Teardown Decorators

from nose2.tools.decorators import with_setup, with_teardown

# Global test data
test_data = {}

def setup_data():
    test_data['value'] = 42
    test_data['list'] = [1, 2, 3]

def cleanup_data():
    test_data.clear()

@with_setup(setup_data)
@with_teardown(cleanup_data)
def test_data_access():
    assert test_data['value'] == 42
    assert len(test_data['list']) == 3

BDD-Style Testing

from nose2.tools import such

with such.A('web application') as it:
    
    @it.has_setup
    def setup():
        it.app = create_test_app()
        it.client = it.app.test_client()
    
    @it.has_teardown 
    def teardown():
        it.app.cleanup()
    
    with it.having('user authentication'):
        
        @it.has_test_setup
        def setup_auth(case):
            case.user = create_test_user()
        
        @it.should('allow login with valid credentials')
        def test_valid_login(case):
            response = it.client.post('/login', data={
                'username': case.user.username,
                'password': 'password'
            })
            case.assertEqual(response.status_code, 200)
        
        @it.should('reject invalid credentials')
        def test_invalid_login(case):
            response = it.client.post('/login', data={
                'username': 'wrong',
                'password': 'wrong'
            })
            case.assertEqual(response.status_code, 401)
    
    with it.having('API endpoints'):
        
        @it.should('return JSON responses')
        def test_json_response(case):
            response = it.client.get('/api/status')
            case.assertEqual(response.content_type, 'application/json')
    
    # Generate test cases - this is required!
    it.createTests(globals())

Mixed Testing Styles

import unittest
from nose2.tools import params, such
from nose2.tools.decorators import with_setup

# Traditional unittest class
class TestBasicMath(unittest.TestCase):
    
    @params(1, 2, 3, 5, 8)
    def test_fibonacci_numbers(self, num):
        self.assertIn(num, [1, 1, 2, 3, 5, 8, 13, 21])

# Function-based tests with setup
def setup_calculator():
    global calc
    calc = Calculator()

@with_setup(setup_calculator)
@params((2, 3, 5), (10, 5, 15), (0, 100, 100))
def test_addition(a, b, expected):
    result = calc.add(a, b)
    assert result == expected

# BDD-style specification
with such.A('calculator application') as it:
    
    @it.has_setup
    def setup():
        it.calc = Calculator()
    
    with it.having('basic arithmetic operations'):
        
        @it.should('add positive numbers')
        def test_positive_addition(case):
            result = it.calc.add(2, 3)
            case.assertEqual(result, 5)
        
        @it.should('handle zero values')
        def test_zero_addition(case):
            case.assertEqual(it.calc.add(0, 5), 5)
            case.assertEqual(it.calc.add(5, 0), 5)
    
    it.createTests(globals())

Install with Tessl CLI

npx tessl i tessl/pypi-nose2

docs

configuration.md

index.md

plugin-development.md

test-discovery.md

test-tools.md

tile.json