Add a pytest option that doesn't have dashes? - python

I have a lot of tests that take a long time to run. Luckily, the time these tests take is evenly distributed among tests for several subsystems of my project.
I'm using IPython's pytest magic commands. I'd like to be able to just say things like
pytest potato_peeler --donttesti18n --runstresstests
or
pytest garlic_squeezer --donttestsmell --logperfdata
but I can't add the garlic_squeezer and potato_peeler options the same way I do logperfdata et al because parser.addoption gets upset if the option name doesn't start with a --.
I know this seems like a tiny inconvenience, but I have a ton of people running these tests several times a day and I'd like the way they're invoked to make as much sense as possible, by emulating how you issue commands on a command line (command, thing you want to run the command on, then --flags.)
Is there a way have non-dashed options? (that doesn't involve writing a full-blown pytest plugin that overrides the option parsing?)
I was hoping to use the pytest_commandline_parse hook but you can't use that hook in a conftest.py, you have to write a full-blown plugin.

You can mark your tests and run only those with some mark.
For example:
import pytest
#pytest.mark.runstresstests
def test_stress_something():
pass
#pytest.mark.logperfdata
def test_something_quick():
pass
...
If you only want to run stress tests: pytest -m runstresstests
Full documentation at https://docs.pytest.org/en/latest/example/markers.html

Related

Better python unittest integration?

I'm using GNU Emacs 24.5.1 to work on Python code. I often want to run just a single unit test. I can do this, for example, by running:
test=spi.test_views.IndexViewTest.generate_select2_data_with_embedded_spaces make test
with M-X compile. My life would be simpler if I could give some command like "Run the test where point is", and have emacs figure out the full name of the test for me. Is possible?
Update: with the folowing buffer, I'd like some command which runs M-X compile with:
test=spi.test_views.IndexViewTest.test_unknown_button make test
where spi is the name of the directory test_views.py is in. Well, technically, I need to construct the python path to my test function, but in practice, it'll be <directory.file.class.function>.
This seems like the kind of thing somebody would have already invented, but I don't see anything in the python mode docs.
I believe you use the "default" python mode, while the so-called elpy mode (that I strongly recommend giving a try when doing Python developments within Emacs) seems to provide what you are looking for:
C-c C-t (elpy-test)
Start a test run. This uses the currently configured test runner to discover
and run tests. If point is inside a test case, the test runner will run exactly
that test case. Otherwise, or if a prefix argument is given, it will run all tests.
Extra details
The elpy-test function internally relies on the function (elpy-test-at-point), which appears to be very close to the feature you mentioned in the question.
See e.g. the code/help excerpt in the following screenshot:

pytest run new tests (nearly) first

I am using pytest. I like the way I call pytest (re-try the failed tests first, verbose, grab and show serial output, stop at first failure):
pytest --failed-first -v -s -x
However there is one more thing I want:
I want pytest to run the new tests (ie tests never tested before) immediately after the --failed-first ones. This way, when working with tests that are long to perform, I would get most relevant information as soon as possible.
Any way to do that?
This may not be directly what you are asking about, but, my understanding is that the test execution order is important for you when you create new tests during development.
Since you are already working with these "new" tests, the pytest-ordering plugin might be a good option to consider. It allows you to influence the execution order by decorating your tests with #pytest.mark.first, #pytest.mark.second etc decorators.
pytest-ordering is able to change the execution order by using a pytest_collection_modifyitems hook. There is also pytest-random-order plugin which also uses the same hook to control/change the order.
You can also have your own hook defined and adjusted to your specific needs. For example, here another hook is used to shuffle the tests:
Dynamically control order of tests with pytest
For anyone coming to this now, pytest added a --new-first option to run new tests before all other tests. It can be combined with --failed-first to run new and failed tests. For test-driven development, I've found it helpful to use these options with pytest-watch, which I described in my blog.

Setting up environment for testing in Python

I'm writing integration tests using plain unittest in Python (import unittest) and are creating stubs for some external services. Now I want to run the same tests with a real implementation; but also keep the stubs. That way I can run the tests with and without the stubs and compare behaviour.
I'm running my tests both from SetupTools and through PyCharm. Is there some generic way for me to set/inject/bootstrap a parameter which tells my code wether to use the stub or the real implementation? Command line preferrable. Any pointers appreciated. :)
It sounds like you are looking for a mocking framework. Mocking frameworks allow you to create a 'stub' for the method from within your test. This is good because you don't want to be inserting any test specific code into your actual code.
One of the more popular mocking frameworks for python 2.* is python-mock (in fact it comes with python 3) So you can write the code as:
from mock import MagicMock
test_foo_mocked():
bar = MagicMock()
bar.return_value = 'fake_val'
assertEqual(bar(), 'fake_val')
test_foo_real():
assertEqual(bar(), 'real_val')
Side Note:
I would really recommend that you think of these as completely unrelated tests. There are many benefits to keeping your integration tests separate from your unit tests. Thinking of them as two different ways of running the 'same test' may encourage you to write bad tests. Unit tests should be able to test things that would be difficult or impossible to test through integration tests and vice versa.

how to omit imports using .coveragerc in coverage.py?

I am using nosetests --with-coverage to test and see code coverage of my unit tests. The class that I test has many external dependencies and I mock all of them in my unit test.
When I run nosetests --with-coverage, it shows a really long list of all the imports (including something I don't even know where it is being used).
I learned that I can use .coveragerc for configuration purposes but it seems like I cannot find a helpful instruction on the web.
My questions are..
1) In which directory do I need to add .coveragerc? How do I specify the directories in .coveragerc? My tests are in a folder called "tests"..
/project_folder
/project_folder/tests
2)It is going to be a pretty long list if I were to add each in omit= ...
What is the best way to only show the class that I am testing with the unittest in the coverage report?
It would be nice if I could get some beginner level code examples for .coveragerc. Thanks.
The simplest way to direct coverage.py's focus is to use the source option, usually source=. to indicate that you only want to measure code in the current working tree.
You can also use the --cover-package=PACKAGE option. For example:
nosetests --with-coverage --cover-package=module_you_are_testing
See http://nose.readthedocs.org/en/latest/plugins/cover.html for details.

Are there any python libraries to help test external python scripts

I'd like to test some python scripts.
Are there any python libraries to help test external system behaviors(running scripts, testing the contents of external files, managing input/output files, and similar actions).
Also I tried making the scripts more api like to allow imports rather then calling it directly for more unit test like tests. Changes include making scripts easier to run interactively(factor lots of stuff into functions/module values and make it less procedural, add parameter to silence stdout, passing optional args to main) also serializing results in addition to the usual output formats(even though the functions to generate the output files have a medium amount of logic in them)).
Is this a good strategy or is it better to attempt to test scripts by running them blackbox style and examining output.
Test library
I'll go ahead and suggest unittest (even though it's the top Google hit for "python unit testing" and you probably already know of it). It's a very nice, easy to use, feature-ful library for unit testing.
Test strategy
Writing testable code is hard. Testing things like side-effects, environments, and file output can take the unit right out of unit test.
What I typically try to do is structure the code so that as little of it as possible does I/O or other nasty things. Then all of that code can usually be straightforwardly unit-tested.
For the parts that are hard to break into units, such as the command-line interface, I test for file output etc.
Conclusion
use unit tests as much as possible
otherwise, use black-box tests
constantly refactor code to make writing unit tests easier & more effective

Categories