[TIP] fixture ordering and dynamically adding fixtures to Testcases
arun kali raja
arunsep886 at gmail.com
Tue Jan 16 08:40:40 PST 2018
Thanks a lot for the insight.
i was trying out few things and found these..
1. Ordering fixtures:
Suppose the user wants to impose the ordering of fixtures in a certain
way then he can do it via the *pytest_generate_tests(metafunc)* hook:
the *metafunc* object has a member variable *fixturenames*.. that is
the list of fixtures that are gona be executed for this test.
the user can reorder it as he wishes.
In my case i have some autoUse fixtures, but they have some dependency
fixtures which are not autoUse.. so fixtureA(autoUse) is dependent on
fixtureB( not autoUse). So only if fixtureB is available i want to include
fixtureA otherwise i dont want to use fixtureA at all.. i Can achieve this
by checking contents of the list and making appropriate decisions to remove
invalid fixtures too..
Now say i want to call all my session fixtures , then module, then class
and then function fixtures, how do i know which is what? bcoz the
*fixturenames* variable is just a list of fixture names(strings)..
the solution is to check the fixture information from the
*dictionary. the dictionary has fixture name as key and a tuple as a value.
the tuple has a object FixtureDef which scope related information.
Is this a right way to do? or just a hacky way to make things work?
why is the values in the *_arg2fixturedefs* a tuple?? can a fixture have
more than one definitions??
2. Adding fixtures dynamically at run time.
I am trying to create a library of fixtures which will provide a
standard set of functionalities.. the user has to add those in his testcase
and then parameterise them according to his usecase.
Instead of the selecting the fixtures i want to give flexibility to
specify the usecase in a marker with some parameters and then the
dynamically add the fixtures.
I think here too *pytest_generate_tests* is the right place to do such
I was able to read the markers using *metafunc.function* member
variable and then add fixtures to the *metafunc.fixturenames* member
And the fixture got called at the time of execution too..
Suppose i want to create a fixture chain according to my use case i
can do it by inserting them one after the other in the *fixturenames. *But
suppose i want to access value returned by fixtureA in fixtureB i am not
sure how to do it.. Becase in that case i have to add fixtureA as a
dependency to fixtureB. I havent figured out that yet..
The *metafunc._arg2fixturedefs *variable i have mentioned above
seems to be populated at the *pytest_generate_tests *phase itself.. I am
not sure how appending the fixture name at *pytest_generate_tests *even
works.. i tried putting a breakpoint at *pytests_itemcollected() *hook..
but even there it seems that the *_arg2fixturedefs *doesnt seem to have
the entry for the newly added fixture.. So i am not sure yet how it works..
On 16 January 2018 at 02:47, Floris Bruynooghe <flub at devork.be> wrote:
> It seems Bruno's reply got lost somewhere...
> On Sat 13 Jan 2018 at 22:38 +0530, arun kali raja wrote:
> > 1. I have a .py file where i have defined two Autouse fixtures..
> > fixtureMod_1 is module scoped and fixtureFunc_1 is function scoped.. Now
> > conftest.py i have imported these two fixtures.. in my test_x.py i have a
> > another module scoped fixture say fixtureMod_2..The order of execution of
> > fixture seems to be fixtureMod_1,fixtureFunc_1 and then fixtureMod_2..
> > module level fixtures supposed to be executed before function level
> > fixtures?? isnt that how scopes are ordered.. i am able to solve the
> > by giving fixtureMod_2 as a dependency to fixtureFunc_1.. but still i am
> > trying to understand why pytest respects the scope ordering in this
> > does the order of sourcing the fixture override the scope based
> If I understand this correct then you have something like this:
> def fixtureMod_1():
> def fixtureFunc_1():
> from foo import fixtureMod_1
> from foo import fixtureFun_1
> def fixtureMod_2():
> def test_foo(fixtureMod_1, fixtureFunc_1, fixtureMod_2):
> From pytest's point of view you have not specified any ordering here.
> The scopes are used to know when the setup and teardown of each fixture
> needs to run, e.g. with a function-scope the fixture will be created for
> just before a single test which needs it and destroyed right after this
> test has run.
> For a module scope the fixture gets only created once for
> all tests in a module. So if multiple tests in test_x require either
> fixtureMod_1 or fixtureMod_2 their setup and teardown will only be
> executed once.
> So scopes have nothing to do with ordering.
> As you discovered if you declare dependencies on fixtures then the
> ordering will start to be defined:
> def fixtureFunc_1(fixtureMod_2):
> This will ensure that fixtureMod_2 is created first. It's good that
> this dependency needs to be explicit in your code. However be careful
> in general to not over-use dependencies like this, e.g. if the only
> reason you declare fixtureMod_2 is to use as a dependency in
> fixtureFunc_1 then maybe fixtureMod_2 shouldn't be a fixture at all.
> As another aside btw, I always *strongy* advice against ever importing
> fixtures. The semantics of it are very confusing (this was probably a
> design mistake) so instead always move the fixture to the right
> location, i.e. your conftest.py file.
> > 2. I have one usecase where i want to dynamically create a fixture
> > say i mark by testcase with useCaseA and that translates to an ordering
> > fixture.. can i add a fixture to a testcase at run time.. at
> > pytest_generate_test phase or pytest_configure phase?? i found a method
> > called add_marker to add a marker at runt time.. since fixtures can also
> > added via markers i was trying to explore if can use that method but it
> > doesnt accept any parameters.. any way i can achieve this??
> Here I'm somewhat lost with your example, I think you have this:
> def test_foo():
> But I'm afraid you'll have to give me more info on how tha translates to
> fixtures in your implementation.
> With respect to dynamically requested fixtures, this is usually done
> using request.getfixturevalue() . However, and this is where
> personal opinions differ, my advice is to avoid this if you possibly
> can. And my opinion is also that this is always possible, e.g. a
> fixture can return instances of two different classes depending on the
> dynamic "thing".
> Hope this helps,
>  https://docs.pytest.org/en/latest/builtin.html?highlight=
பா. அருண் காளி ராசா
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the testing-in-python