Git Product home page Git Product logo

pytest-param-scope's Introduction

pytest-param-scope

The pytest parametrize scope fixture workaround.


pytest-param-scope provides a param_scope marker to pass setup and teardown functions to a parametrized function.

There's also a param_scope fixture to allow the return value of the setup function to be passed to the test.

Installation

From PyPI:

$ pip install pytest-param-scope

Example

import pytest


def param_setup():
    print('\nparam setup')
    return 'some data from setup'


def param_teardown():
    print('\nparam teardown')


@pytest.mark.param_scope(param_setup, param_teardown)
@pytest.mark.parametrize('x', ['a', 'b', 'c'])
def test_param(x, param_scope):
    """
    mark.param_scope is used to pass
    setup and teardown functions to fixture

    param_scope fixture is necessary if you
    want to use the value from setup
    """
    assert param_scope == 'some data from setup'

Let's see it run:

(venv) $ pytest -s -v test_param_scope.py::test_param
================== test session starts ===================
collected 3 items                                        

test_param_scope.py::test_param[a] 
param setup
PASSED
test_param_scope.py::test_param[b] PASSED
test_param_scope.py::test_param[c] PASSED
param teardown

=================== 3 passed in 0.01s ====================

What are we seeing?

  1. Setup is run before the first parameter in a set.
  2. Teardown is run after the last parameter.
  3. The param_scope fixture holds the return value of the setup function.

Similarities to Fixtures

  • Teardown is not run if the setup fails.
  • Setup is run once, even though the value can be retrieved by all parametrized test cases.
  • If an exception occurs in setup, the test will report Error and not run. The teardown will also not run.
  • If an exception occurs in teardown, the LAST parametrized test case to run results in BOTH PASS and Error. This is weird, but consistent with pytest fixtures.

You can combine setup and teardown in one function

You can provide a function separated by a yield to put both setup and teardown in one function.

However, there's a trick to doing this:

  • Either, pass None as the teardown.
  • Or use with_args, as in @pytest.mark.param_scope.with_args(my_func)

Here's a combo setup/teardown function:

def setup_and_teardown():
    print('\nsetup')
    yield 42
    print('\nteardown')

Calling it with None for teardown:

import pytest

@pytest.mark.param_scope(setup_and_teardown, None)
@pytest.mark.parametrize('x', ['a', 'b', 'c'])
def test_yield(x, param_scope):
    assert param_scope == 42

Or using with_args:

@pytest.mark.param_scope.with_args(setup_and_teardown)
@pytest.mark.parametrize('x', ['a', 'b', 'c'])
def test_just_one_func(x, param_scope):
    assert param_scope == 42

Both of these examples are in examples/test_yield.py.

More examples

Please see examples directory in the repo.

Limitations

The implementation is a total hack and relies on global variables and looking up the next test to see when to run the teardown. There is undoubtedly room for improvement.

  • With pytest-xdist: I haven't come up with a failing case yet, but it seems like this will be sketchy with tests running in parallel.

  • With pytest-repeat: This actually works great with pytest-repeat, as repeat works by generating parametrized tests.

FAQ

Why not just use existing fixture scopes?

There isn't a scope that quite fits.

  • Function: runs setup before and after each parametrized test case.
  • Class: Kinda works if you put only one function in a test class.
  • Module: Too wide.
  • Session: Way too wide.

I want a setup that runs before all parametrized test cases, and clean up after the last one.

Why implement this as a plugin and not add this functionality to pytest core?

A couple reasons.

  1. I'm not sure we want this funcitonality in core pytest. Playing with it as a plugin will tell us if it's important to people.
  2. Implementing it as a plugin is faster to get it out there and usable.

Contributing

Contributions are very welcome. Tests can be run with tox.

License

Distributed under the terms of the MIT license, "pytest-param-scope" is free and open source software

Issues

If you encounter any problems, please file an issue along with a detailed description.

Changelog

See changelog.md

pytest-param-scope's People

Contributors

okken avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

pytest-param-scope's Issues

Meta-issue tracking efforts towards param scope support in pytest

pytest-param-scope emulates functionality that approximates what a fixture scope at the parametrized test level might achieve. In fact, native support for such a scope may come to pytest, and this issue tracks the related efforts. The following two issues directly track the interest for this feature:

However, implementation requires pytest's test collection node structure to understand functions at definition time, prior to parametrization. Also, pytest-dev/pytest#1552 (comment) and pytest-dev/pytest#1552 (comment) detail the implementation problem of how such a scope is not so simply defined, due to the fact that parametrize can be used on functions as well as fixtures, operating at various scopes. See further discussion in #1. And in pytest's backwards compatibility policy, it is explicitly stated that this feature effort constitutes a true breakage. We can see some of the broader upstream efforts related to the above feature requests:

Contributors are welcome to contribute here at pytest-param-scope to improve the emulation of param scope functionality until the massive overhaul in pytest properly supports the scope. I would also like to point potentially interested contributors towards helping the upstream effort for supporting param scope in pytest. However, most of the direct blockers touch a lot of the core parts of pytest, so the work is being carried out primarily by core pytest contributors. At the time of writing, then, the best way to help out pytest upstream is to follow their contribution guide, and work on issues designated as good first issues or those marked as help wanted.


Meta-meta-question: This developer-focused meta-issue has a lot of detail. Some of these details may be relevant to the user-focused readme documentation. If so, which details might be worth including there?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.