Run unittest in a python module in PyCharm/IntelliJ IDEA12? - python

In testsuite/__init__.py, I write this:
import unittest
def suite():
from my_module.testsuite import (
shell_command,
shell_command_on_jinja,
workflow
)
suite = unittest.TestSuite()
suite.addTest(shell_command.suite())
suite.addTest(shell_command_on_jinja.suite())
suite.addTest(workflow.suite())
return suite
In terminal, I can execute the test suite like this:
python3 -m unittest testsuite.suite
However, I don't know how to config the test for Pycharm/InteliJ. I add a configuration under Python's test and set Test to Function, Script to my_module/testsuite/__init__.py, and Function to suiteand then run it. But it doesn't work. Does anyone have ideas about this? Thanks!

It seems that PyCharm doesn't support this now. Please check the following thread.
http://forum.jetbrains.com/thread/PyCharm-1116

Related

Is it possible to use parameterize imports with pytest?

I am using pytest to test a project I am working on. I have a project structure like
|my_project
||__init__.py
||my_code.py
||test.py
and test.py looks like
# contents of test.py
import .my_code
def test_function():
...
...
To run the tests, I can just run python -m pytest from this directory. So far so good.
But for the code to run remotely, I have to use Pants to build a virtual environment so that the import statement will actually look like:
import long.path.to.my_project.my_code as my_code
I want to make sure that the code still works in this virtual environment as well, so right now I have a different file called test_venv.py with identical tests, where the only difference is the import.
# contents of test_venv.py
import long.path.to.my_project.my_code as my_code
def test_function():
...
...
This does work, but it's very annoying to have two almost identical test files. Is there a way to make the import statement parameterized, so that I can tell pytest where I want to import from when I run the test?
You can combine imports. Do one way, catch exception, do the other way.
try:
import .my_code
except ImportError:
import long.path.to.my_project.my_code as my_code
def test_function():
...
...
I'm not sure, may be it's should be
try:
import long.path.to.my_project.my_code as my_code
except ImportError:
import .my_code
After playing around with #morhc's suggestion to use this, I figured out a way. It involves using parameterized fixtures and importlib. I set up the fixture as follows.
#pytest.fixture(scope='module', params=['local', 'installed'])
def my_code_module(request):
if request.param == 'local':
return importlib.import_module("my_code")
if request.param == 'installed':
return importlib.import_module("long.path.to.my_project.my_code")
Then write the tests to request the fixture as follows.
def test_code(my_code_module):
assert my_code_module.whatever() == ...

Can I call "python -m unittest test_code" by "runpy.run_module"?

I am learning unittest of python.
I learned that I can run a test, test_code, by
python -m unittest test_code
from command line.
Now I would like to run unittest in python script.
I learned "runpy.run_module()" corresponds with "python -m".
However I could not understand how to give arguments to unittest
in the way of "runpy.run_module()".
That is,
runpy.run_module(unittest) # where should I put 'test_code'?
Can I run unittest with test_code with runpy.run_module() in the python script?
Thank you very much.
Here are some ways to do it:
import unittest
import tests # where my unit tests are at
import tests_copy # where my unit tests are at
# make a collection of TestCases
suit = unittest.TestSuite()
# add all testcases in tests module
suit.addTest(unittest.defaultTestLoader.loadTestsFromName('tests'))
# add testcase tester1 from module tests_copy
suit.addTest(unittest.defaultTestLoader.loadTestsFromName('tests_copy.tester1'))
# add all testcases in tests module
suit.addTest(unittest.defaultTestLoader.loadTestsFromModule(tests))
# add testcase tester1 from module tests_copy
suit.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(tests.tester1))
# run the tests
runner = unittest.TextTestRunner()
runner.run(suit)
Read the docs

How can I integrate doctests with unittest's test discovery?

I wrote a python script to do all my tests automatically for me, and generate a HTML report. I discovered discover for unittests the other day which lets me run all the unittests in a given directory without explicitly naming them, and I'd really like to be able to do my doctests the same way, rather than having to import each module explicitly.
I found some info on how to do this at https://docs.python.org/2/library/doctest.html but didn't really get it. Could you please help me with using discover with my doctests?
Python test discovery with doctests, coverage and parallelism is related, but still doesn't answer my question.
coverage_module
import coverage
import doctest
import unittest
import os
# import test_module
import my_module
cov = coverage.Coverage()
cov.start()
# running doctest by explicity naming the module
doctest.testmod(my_module)
# running unittests by just specifying the folder to look into
testLoad = unittest.TestLoader()
testSuite = testLoad.discover(start_dir=os.getcwd())
runner = unittest.TextTestRunner()
runner.run(testSuite)
cov.stop()
cov.save()
cov.html_report()
print "tests completed"
test_module
import unittest
import doctest
from my_module import My_Class
class My_Class_Tests(unittest.TestCase):
def setUp(self):
# setup variables
def test_1(self):
# test code
# The bit that should load up the doctests? What's loader, tests, and ignore though?
# Is this in the right place?
def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocTestSuite(module_with_doctests))
return tests
if __name__ == '__main__':
unittest.main()
Lets figure out what's happening there
1) unittest.discovery
It has no clue of doctests as doctests is a different framework.
So unittest isn't supposed to discover doctests out of the box.
That means you'll need to glue them together by hand
2) doctest
It's essentially a separate framework although it has some glueing classes to convert doctests into unittest-like TestCases.
https://docs.python.org/2.7/library/doctest.html#doctest.DocTestSuite
3) discover
Didn't get what discover you mean, I suppose it's
python -m unittest discover
If not and you're talking about https://pypi.python.org/pypi/discover then just forget about it - it's a backport for earlier versions of python
4) what to do
either scatter a lot of load_tests hooks across your code as described here https://docs.python.org/2.7/library/doctest.html#unittest-api or code a method to collect all the modules your have in one place and convert them into a DocTestSuite[s] https://docs.python.org/2.7/library/doctest.html#doctest.DocTestSuite
But honestly neither approach makes any sense nowadays as it boils down to:
$ py.test --doctest-modules
or
$ nosetests --with-doctest
Of course coverage and lots of bells & whistles are also supplied by these frameworks and you may keep sticking to unittest.TestCase, and you won't even need to create a coverage_module so I would dig into one of them rather then trying to come up with your own solution

Test if code is executed from within a py.test session

I'd like to connect to a different database if my code is running under py.test. Is there a function to call or an environment variable that I can test that will tell me if I'm running under a py.test session? What's the best way to handle this?
A simpler solution I came to:
import sys
if "pytest" in sys.modules:
...
Pytest runner will always load the pytest module, making it available in sys.modules.
Of course, this solution only works if the code you're trying to test does not use pytest itself.
There's also another way documented in the manual:
https://docs.pytest.org/en/latest/example/simple.html#pytest-current-test-environment-variable
Pytest will set the following environment variable PYTEST_CURRENT_TEST.
Checking the existence of said variable should reliably allow one to detect if code is being executed from within the umbrella of pytest.
import os
if "PYTEST_CURRENT_TEST" in os.environ:
# We are running under pytest, act accordingly...
Note
This method works only when an actual test is being run.
This detection will not work when modules are imported during pytest collection.
A solution came from RTFM, although not in an obvious place. The manual also had an error in code, corrected below.
Detect if running from within a pytest run
Usually it is a bad idea to make application code behave differently
if called from a test. But if you absolutely must find out if your
application code is running from a test you can do something like
this:
# content of conftest.py
def pytest_configure(config):
import sys
sys._called_from_test = True
def pytest_unconfigure(config):
import sys # This was missing from the manual
del sys._called_from_test
and then check for the sys._called_from_test flag:
if hasattr(sys, '_called_from_test'):
# called from within a test run
else:
# called "normally"
accordingly in your application. It’s also a good idea to use your own
application module rather than sys for handling flag.
Working with pytest==4.3.1 the methods above failed, so I just went old school and checked with:
script_name = os.path.basename(sys.argv[0])
if script_name in ['pytest', 'py.test']:
print('Running with pytest!')
While the hack explained in the other answer (http://pytest.org/latest/example/simple.html#detect-if-running-from-within-a-pytest-run) does indeed work, you could probably design the code in such a way you would not need to do this.
If you design the code to take the database to connect to as an argument somehow, via a connection or something else, then you can simply inject a different argument when you're running the tests then when the application drives this. Your code will end up with less global state and more modulare and reusable. So to me it sounds like an example where testing drives you to design the code better.
This could be done by setting an environment variable inside the testing code. For example, given a project
conftest.py
mypkg/
__init__.py
app.py
tests/
test_app.py
In test_app.py you can add
import os
os.environ['PYTEST_RUNNING'] = 'true'
And then you can check inside app.py:
import os
if os.environ.get('PYTEST_RUNNING', '') == 'true':
print('pytest is running')

Unit-testing extensions for an 'external' program with pyunit

I'm struggling to know where to start with unittest, having read the dive-into-python tutorial and looked at http://pyunit.sourceforge.net/.
I've got a piece of analysis software (call it 'prog.exe') which uses python for its input decks. I've started writing a python module which I'm going to import from that input deck to provide some useful functionality. So, running one of these analyses will go like this:
prog.exe inputdeck.py
where inputdeck.py contains:
from mymodule import mystuff
So how do I set up and run tests on mymodule? Should the above be in a system call in a setUp method of the test, or what?
Ok - solution:
Don't use unittest.main() as that's the command line tool. Instead call the appropriate unittest methods directly as follows:
From the command line run:
prog.exe mytests.py
where mytests.py contains:
import unittest
# ... code to run the analysis which we'll use for the tests ...
# ... test definitions ...
suite = unittest.TestLoader().loadTestsFromTestCase(test_cases)
unittest.TextTestRunner().run(suite)
See example at http://docs.python.org/release/2.6.7/library/unittest.html#unittest.TextTestRunner
Pyunit is a little bit outdated (2001), it is now completely included in python core distribution (http://docs.python.org/library/unittest.html). You should start read this documentation, especially the basic example part.
To test your module you'll have to create a file, let's call it mymodule_test.py and put in it something like this :
import unittest
from mymodule import mystuff
class MyTestCase(unittest.TestCase):
def test_01a(self):
""" test mystuff"""
self.failUnless(mystuff.do_the_right_stuff())
if __name__ == '__main__':
unittest.main()
and run it with python mymodule_test.py

Categories

Resources