Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can tests with pytest fixtures be run interactively?

Tags:

python

pytest

I have some tests written using pytest and fixtures, e.g.:

class TestThing:
    @pytest.fixture()
    def temp_dir(self, request):
        my_temp_dir = tempfile.mkdtemp()
        def fin():
            shutil.rmtree(my_temp_dir)
        request.addfinalizer(fin)
        return my_temp_dir
    def test_something(self, temp_dir)
        with open(os.path.join(temp_dir, 'test.txt'), 'w') as f:
            f.write('test')

This works fine when the tests are invoked from the shell, e.g.

 $ py.test

but I don't know how to run them from within a python/ipython session; trying e.g.

tt = TestThing()
tt.test_something(tt.temp_dir())

fails because temp_dir requires a request object to be passed on. So, how does one invoke a fixture with a request object injected?

like image 712
keflavich Avatar asked Nov 10 '14 09:11

keflavich


People also ask

Can a pytest fixture be a test?

Those are the things that need to test a certain action. In pytest the fixtures are functions that we define to serve these purpose, we can pass these fixtures to our test functions (test cases) so that they can run and set up the desired state for you to perform the test.

Can pytest fixtures use other fixtures?

A fixture can use multiple other fixtures. Just like a test method can take multiple fixtures as arguments, a fixture can take multiple other fixtures as arguments and use them to create the fixture value that it returns.

What is the point of a pytest fixture?

Pytest fixtures are functions that can be used to manage our apps states and dependencies. Most importantly, they can provide data for testing and a wide range of value types when explicitly called by our testing software. You can use the mock data that fixtures create across multiple tests.

Can pytest fixtures have arguments?

You can pass arguments to fixtures with the params keyword argument in the fixture decorator, and you can also pass arguments to tests with the @pytest. mark.


2 Answers

Yes. You don't have to manually assemble any test fixtures or anything like that. Everything runs just like calling pytest in the project directory.

Method1:

This is the best method because it gives you access to the debugger if your test fails

In ipython shell use:

**ipython**> run -m pytest prj/

This will run all your tests in the prj/tests directory.

This will give you access to the debugger, or allow you to set breakpoints if you have a import ipdb; ipdb.set_trace() in your program (https://docs.pytest.org/en/latest/usage.html#setting-breakpoints).

Method2:

Use !pytest while in the test directory. This wont give you access to the debugger. However, if you use

**ipython**> !pytest --pdb

If you have a test failure, it will drop you into the debugger (subshell), so you can run your post-mortem analysis (https://docs.pytest.org/en/latest/usage.html#dropping-to-pdb-python-debugger-on-failures)


Using these methods you can even run individual modules/test_fuctions/TestClasses in ipython using (https://docs.pytest.org/en/latest/usage.html#specifying-tests-selecting-tests)

**ipython**> run -m pytest prj/tests/test_module1.py::TestClass1::test_function1

like image 67
alpha_989 Avatar answered Oct 02 '22 12:10

alpha_989


You can bypass the pytest.fixture decorator and directly call the wrapped test function.

tmp = tt.temp_dir.__pytest_wrapped__.obj(request=...)

Accessing internals, it's bad, but when you need it...

like image 23
Sebastien Lelong Avatar answered Oct 02 '22 12:10

Sebastien Lelong