daino3
daino3

Reputation: 4566

Python test fixture to run a single test?

I'm looking for something like ruby rspec's focus metadata or elixir's mix tags to run a single python test.

Ruby RSpec Example:

# $ rspec spec
it 'runs a single test', :focus do 
  expect(2).to eq(2)
end

Elixir ExUnit & Mix Example:

# $ mix test --only focus
@tag :focus
test "only run this test" do
  assert true
end

Is this possible / available with any python test runner and fixture combo? Running single tests by specifying nested module.class.test_name via command line args can become very verbose in larger projects.

So Something like:

Desired Python Code:

# $ nosetests --only focus

from tests.fixtures import focus

class TestSomething(unittest.TestCase):
    @focus
    def test_all_the_things(self):
        self.assertEqual(1, 1)

Upvotes: 14

Views: 5203

Answers (2)

sjaq
sjaq

Reputation: 105

Had a similar problem and wanted to imitate the same behaviour that rspec provides for ruby, where the entire test suite is ran when there are no focused tests, but when there are it only runs the focused tests.

The setup is fairly similar to what Piotr suggested, but adds one extra step to filter out the selected tests.

  1. Configure the marker as suggested by Piotr in your pytest.ini or pyproject.toml:

    [pytest]
    markers = 
        focus: what is being developed right now
    
  2. Add the following code to your root conftest.py

    def pytest_collection_modifyitems(session: pytest.Session, config: Any, items: list[pytest.Item]):
        focused = [i for i in items if i.get_closest_marker("focus")]
    
        if focused:
            items[:] = focused
    

This will filter the collected tests when there are one or more tests that have a focus marker. Combining this with pytest-testmon gives you the same behaviour as guard provides when coming from a ruby background.

Upvotes: 2

Piotr Dawidiuk
Piotr Dawidiuk

Reputation: 3092

Say hello to pytest mark. You can create a focus tag, assign to any test case or method and then run tests with pytest -v -m focus command. For example:

import unittest
import pytest

class TestOne(unittest.TestCase):
    def test_method1(self):
        # I won't be executed with focus mark
        self.assertEqual(1, 1)

    @pytest.mark.focus
    def test_method2(self):  
        # I will be executed with focus mark          
        self.assertEqual(1, 1)

will run test_method2. To run all methods within some TestCase, you simply mark a class:

import unittest
import pytest

@pytest.mark.focus
class TestOne(unittest.TestCase):
    ...

You will need to register your custom marks in pytest.ini like

[pytest]
markers =
    focus: what is being developed right now

To see the available marks, run pytest --markers.

Upvotes: 13

Related Questions