py.test : do something just after a test - python-3.x

For my tests, I build temporary files that I would like to remove whatever the result of the test is (failure or test passed).
Is there a way to "tell" to py.test to do something just after it finishes to test my Python file ?

Here is a canvas found in the official documentation.
from pytest import fixture
#fixture(scope="module")
def or_datas(request):
# Something done before a test.
def fin():
# Here, just do something after the test.
...
request.addfinalizer(fin)
# How to use it ?
def test_something(or_datas):
# Note the argument corresponding the function decorated
# by fixture.
...

Related

pytest - run tests with customized markers

I used customized pytest markers like below,
#pytest.mark.test_id("AB-1234")
def test_test1():
pass
#pytest.mark.test_id("AB-1234")
def test_test2():
pass
#pytest.mark.test_id("AB-5678")
def test_test3():
pass
Here test_id is the marker name and "AB-1234" is the value.
From command line how to run all the tests with marker test_id==AB-1234? I tried different variations with -m option but couldn't find a solution.
EDIT: I tried pytest -m "AB-1234" but it runs all the tests.

PytestUnknownMarkWarning: Unknown pytest.mark.xxx - is this a typo?

I have a file called test.py with the following code:
import pytest
#pytest.mark.webtest
def test_http_request():
pass
class TestClass:
def test_method(self):
pass
pytest -s test.py passed but gave the following warnings:
pytest -s test.py
=============================== test session starts ============================
platform linux -- Python 3.7.3, pytest-5.2.4, py-1.8.0, pluggy-0.13.1
rootdir: /home/user
collected 2 items
test.py ..
=============================== warnings summary ===============================
anaconda3/lib/python3.7/site-packages/_pytest/mark/structures.py:325
~/anaconda3/lib/python3.7/site-packages/_pytest/mark/structures.py:325:
PytestUnknownMarkWarning: Unknown pytest.mark.webtest - is this a typo? You can register
custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
PytestUnknownMarkWarning,
-- Docs: https://docs.pytest.org/en/latest/warnings.html
=============================== 2 passed, 1 warnings in 0.03s ===================
Environment: Python 3.7.3, pytest 5.2.4, anaconda3
What is the best way to get rid of the warning message?
To properly handle this you need to register the custom marker. Create a pytest.ini file and place the following inside of it.
[pytest]
markers =
webtest: mark a test as a webtest.
Next time you run the tests, the warning about the unregistered marker will not be there.
without updating pytest.ini, we can ignore warning using --disable-warnings
We can also use --disable-pytest-warnings
Example using your case:
pytest -s test.py -m webtest --disable-warnings
#gold_cy's answer works. If you have too many custom markers need to register in pytest.ini, an alternative way is to use the following configuration in pytest.ini:
[pytest]
filterwarnings =
ignore::UserWarning
or in general, use the following:
[pytest]
filterwarnings =
error
ignore::UserWarning
the configuration above will ignore all user warnings, but will transform all other warnings into errors. See more at Warnings Capture
test.py (updated with two custom markers)
import pytest
#pytest.mark.webtest
def test_http_request():
print("webtest::test_http_request() called")
class TestClass:
#pytest.mark.test1
def test_method(self):
print("test1::test_method() called")
Use the following commands to run desired tests:
pytest -s test.py -m webtest
pytest -s test.py -m test1
The best way to get rid of the message is to register the custom marker as per #gold_cy's answer.
However if you just wish to suppress the warning as per Jonathon's answer, rather than ignoring UserWarning (which will suppress all instances of the warning regardless of their source) you can specify the particular warning you want to suppress like so (in pytest.ini):
ignore::_pytest.warning_types.PytestUnknownMarkWarning
Note: For third party libraries/modules the full path to the warning is required to avoid an _OptionError exception
If you don't have pytest.ini and don't wanna create one just for this then you can also register it programmatically in conftest.py as described here:
def pytest_configure(config):
# register an additional marker
config.addinivalue_line(
"markers", "env(name): mark test to run only on named environment"
)
To add to the existing answers - custom markers can also be registered in pyproject.toml:
# pyproject.toml
[tool.pytest.ini_options]
markers = [
"webtest: mark a test as a webtest.",
]
Related docs.

Python 3.7 Unit Tests

So I tried many things (from SO and more) getting my tests running but nothing worked this is my current code:
test.py which I call to run the tests: python3 ./src/preprocess/python/test.py
import unittest
if __name__ == '__main__':
testsuite = unittest.TestLoader().discover('.')
unittest.TextTestRunner(verbosity=2).run(testsuite)
the test file looks like this:
import unittest
from scrapes.pdf import full_path_to_destination_txt_file
print(full_path_to_destination_txt_file)
class PreprocessingTest(unittest.TestCase):
def path_txt_appending(self):
self.assertEqual(full_path_to_destination_txt_file(
"test", "/usr/test"), "/usr/test/test.txt")
if __name__ == '__main__':
unittest.main(verbosity=2)
But the output is always like this:
python3 ./src/preprocess/python/test.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Additional Information:
As you can see I call this not from my root directory. The test folder is in ./src/preprocess/python/test/ and has a __init__.pyfile included (there is also a init file on the level of test.py)
it would be okay for me if I have to code down all the calls for all the tests I just want to finish this
automatic search with -t does not work either so I thought the more robust method here with test.py would work...
using this framework is a requirement I have to follow
test_preprocessing.py is in the test folder and from scrapes.pdf import full_path_to_destination_txt_filescrapes is a module folder on the same level as test
When I call the single unit test directly in the command line it fails because of the relative import. But using the test.py (obviously) finds the modules.
What is wrong?
By default, unittest will only execute methods whose name starts with test:
testMethodPrefix
String giving the prefix of method names which will be interpreted as test methods. The default value is 'test'.
This affects getTestCaseNames() and all the loadTestsFrom*() methods.
from the docs.
Either change that attribute or (preferably) prefix your method name with test_.

Set testing options while django doctesting

Following these posts, I have managed to run my doctest within django with:
# myapp/tests.py
import doctest
def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocTestSuite())
return tests
Then running:
python manage.py tests
However, since I am used to test my (non-django) scripts with the simple command:
py.test --doctest-modules -x
I am now quite confused about:
testing procedure not stopping after first failure (my good'ol -x) (so I get flooded with results and I need to scroll back all the way up to the first problem each time)
option # doctest: +ELLIPSIS not being set by default.
How do I set this kind of options from this django load_tests() hook?
Okay, I've got it. Options flags like ELLIPSIS or FAIL_FAST can be
provided as an optionflags argument to DocTestSuite.
The right way to combine them, as reported here, is to bitwise OR them :)
So the following does work:
# myapp/tests.py
import doctest
def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocTestSuite(
optionflags=doctest.ELLIPSIS | doctest.FAIL_FAST))
return tests

How to get debug output for Jupyter Notebook ContentManager code

I'm writing a ContentsManager for Jupyter-Notebook to store data on a local OpenStack SwiftStore. I'm taking S3Contents as my starting point.
I have a basic framework that will connect & create a container if it doesn't exist.... however before I go any further, I need to start creating unit tests.
My question is how do I see the DEBUG output?
If I have a method that starts:
def get(self, path, content=True, type=None, format=None):
"""Retrieve an object from the store, named in 'path'
"""
self.log.debug("SwiftContents[swiftmanager]: get '%s', path)
.... how do I see the output SwiftContents[swiftmanager]: get '\foo\bar'?
Also, what's the testing framework used by notebooks?
class SwiftContentsManager(ContentsManager):
# Initialise the instance
def __init__(self, *args, **kwargs):
super(SwiftContentsManager, self).__init__(*args, **kwargs)
self.swiftfs = SwiftFS(log=self.log)
It looks a bit like unittest, except it has setUp rather than startUp
To run tests: nosetests path/to/tests/test_foo.py
To run tests, and see what it's actually doing: nosetests -v path/to/tests/test_foo.py
To run tests, see what it's actually doing, and see the debug output: nosetests -v --debug path/to/tests/test_foo.py
For more information, see http://pythontesting.net/framework/nose/nose-introduction/

Resources