I cannot find a situation when pass does not follow immediately follow the module definition for the #scenario decorator.
#For example:
#scenario('myFileName.feature', 'my scenario title')
def my_scenario_module1():
pass
#given(blah blah)
blah blah actual code
...blah blah other decorators (ie: #when #then)
I understand that the scenario is tested in the #given, #when and #then. But what is the point of the pass after the #scenario?
Is there a purpose to the module for #scenario other than just writing pass every time?
I was wondering at some stage too. Here is the answer I got from pytest-bdd dev team:
https://github.com/pytest-dev/pytest-bdd/issues/279
pytest tests discovery
test_ prefixed test functions or methods outside of class
scenario decorator
Function decorated with scenario decorator behaves like a normal test function, which will be executed after all scenario steps. You can consider it as a normal pytest test function, e.g. order fixtures there, call other functions and make assertions
Some more details (scenarios shortcut)
...with the manual approach you get all the power to be able to additionally parametrize the test, give the test function a nice name, document it, etc...
Related
From the official documentation, in the example about parametrizing fixtures:
Parametrizing fixtures
Extending the previous example, we can flag the fixture to create two smtp_connection fixture instances which will cause all tests using the fixture to run twice.
#pytest.fixture(scope="module", params=["smtp.gmail.com", "mail.python.org"])
def smtp_connection(request):
I wrote a parametrized fixture like the above example, but now my problem is I want to use the fixture in a different test function that should only execute once for one of the parameters...Like so:
def my_test_function(smtp_connection)
# I want this function to execute only once for the first or the second parameter...
So my question is: Can a test function use the fixture and be executed only for some parameters using pytest API? Or is this use case already a mistake and should both the fixture or the test functions be implemented differently in such case? If so, what would conceptually be the correct design alternative?
I am looking for a programmatic solution that doesn't require using command-line flags when I run pytest.
You could use indirect fixture parametrization - in this case you would define the parameters you want to use in the test instead of the fixture:
#pytest.fixture(scope="module")
def smtp_connection(request):
url = request.param
...
pytest.mark.parametrize("smtp_connection", ["smtp.gmail.com", "mail.python.org"], indirect=True)
def def my_test_function(smtp_connection):
...
pytest.mark.parametrize("smtp_connection", ["smtp.gmail.com"], indirect=True)
def def my_other_test_function(smtp_connection):
...
This will parametrize the fixture with each of the parameters you provide in the list for a specific test. You can read the parameter from request.param as shown above.
Of course, if you have many tests that use the same parameters you are probably better off using specific fixtures instead.
I want to have a specific setup/tear down fixture for one of the test modules. Obviously, I want it to run the setup code once before all the tests in the module, and once after all tests are done.
So, I've came up with this:
import pytest
#pytest.fixture(scope="module")
def setup_and_teardown():
print("Start")
yield
print("End")
def test_checking():
print("Checking")
assert True
This does not work that way. It will only work if I provide setup_and_teardown as an argument to the first test in the module.
Is this the way it's supposed to work? Isn't it supposed to be run automatically if I mark it as a module level fixture?
Module-scoped fixtures behave the same as fixtures of any other scope - they are only used if they are explicitely passed in a test, marked using #pytest.mark.usefixtures, or have autouse=True set:
#pytest.fixture(scope="module", autouse=True)
def setup_and_teardown():
print("setup")
yield
print("teardown")
For module- and session-scoped fixtures that do the setup/teardown as in your example, this is the most commonly used option.
For fixtures that yield an object (for example an expansive resource that shall only be allocated once) that is accessed in the test, this does not make sense, because the fixture has to be passed to the test to be accessible. Also, it may not be needed in all tests.
I'm a beginner programmer, I've been stuck for the past week trying to write unit tests. I read through the unit test docs and watched two long tutorials on implementing unit testing with Mock. The docs refer to mocking classes extensively, but for functions, I'm not sure if I should be using #patch/with patch, patch.dict{}, side_effect, or some other option to mock a function, specifically the argument to a function.
mymodule.py
def regex():
'''Runs a regex, creates a dict 'data' and then calls scraper(data)'''
def scraper(data):
'''scrapes a website and then calls a function which submits data to a db'''
I would like to create a test that passes in test data to the function scraper . Thank you in advance.
Yes, you can also do unit test using mock for non-object_oriented code.
See example below:
from unittest.mock import MagicMock
def a():
return 10
def b():
print(a())
b()
a = MagicMock(return_value=3)
b()
And the output is:
10
3
In the previous example mock is used to fake/mock the function a(), so you can test function b() in isolation, b() is your SUT, without calling a() real implementation. This can be useful for more complex code, specially when function a() relies on data that might not be available in the unit test level.
You haven't given enough examples to really help, but a couple of observations:
Generally, it's better to structure your code to avoid the need for mocking in tests; to the extent possible, each function should be a self-contained piece of code, which can be called separately.
There's no need to mock arguments; simply pass the test value in.
I'm not sure what's intended with this code:
bar = {'key': 'value'}
def foo(bar):
pass
The bar defined at the outer level is a completely separate variable to the bar used as an argument in the function definition. It is confusing to give them the same name...
A function can be mocked using patch or patch.object with the return_value=... option; often, though, it suggests that the code needs to be refactored to reduce the dependency between the two functions.
Sorry for this question. It may be repetetive but did not find enough on google related to this. I know fixtures are having 4 scopes (function, module, class, session). Just want to know whether these scopes are valid only if I use autouse true?. For autouse=False, can i use any fixture having any scope in a test function
Like I am having a conftest.py file which is having fixture as
#pytest.fixture(scope="module")
def test_fixture():
DO something
print "Module level fixture am called"
test.py file is having below data
class ABC:
def test(test_fixture):
print "Doing something"
def test_2(test_fixture):
print "Executing second test"
Now If I change scope of fixture to session, it will still run and produce the same result.
Does that mean scoping only valid if autouse=True?
First of all, I needed to rename your class to TestABC, so that pytest can find it.
Secondly, I will assume that you are using Python 2, but remember that it will no longer be supported in pytest 5.0.
And what I think is your main issue: since your are using a class to group your tests, the first argument to your methods is always the instance itself (aka self) even if you give it another name.
That's why pytest is not really detecting that you want to pass the fixture and it never does it.
So try something like this:
class TestABC:
def test(self, test_fixture):
print "Doing something"
def test_2(self, test_fixture):
print "Executing second test"
Also note that you don't need to use classes to group your tests, you could use regular functions. So removing the class should also solve your problem:
def test(test_fixture):
print "Doing something"
def test_2(test_fixture):
print "Executing second test"
Also, in your case module and session will produce a similar effect, since you only have one module (at least in your example).
But you can easily compare with the default scope: if you remove the scope argument completely, the fixture will be called once before each test that requires it.
#pytest.fixture
def test_fixture():
# DO something
print "Default test level fixture"
Using module will call it once for the whole module. And session would call it once for all the modules.
To answer your original question: no, scopes also apply when autouse=False.
I'm writing test system using py.test, and looking for a way to make particular tests execution depending on some other test run results.
For example, we have standard test class:
import pytest
class Test_Smoke:
def test_A(self):
pass
def test_B(self):
pass
def test_C(self):
pass
test_C() should be executed if test_A() and test_B() were passed, else - skipped.
I need a way to do something like this on test or test class level (e.g. Test_Perfo executes, if all of Test_Smoke passed), and I'm unable to find a solution using standard methods (like #pytest.mark.skipif).
Is it possible at all with pytest?
You might want to have a look at pytest-dependency. It is a plugin that allows you to skip some tests if some other test had failed.
Consider also pytest-depends:
def test_build_exists():
assert os.path.exists(BUILD_PATH)
#pytest.mark.depends(on=['test_build_exists'])
def test_build_version():
# this will skip if `test_build_exists` fails...