Use `__name__ == "__main__":` within a class that implements `unittest.TestCase` - python

I have a unittest.TestCase with a very heavy setup class
I would like to run it using a mock if the code is launched as main, and run the full data check if it runs trough an import as following:
import unittest
from utilities import create_full_data,create_mock_data
if __name__ == "__main__":
print(' I want to run this block if code starts from here')
data_to_check=create_mock_data()
else:
print(' I want to run this block if imported')
data_to_check = create_full_data()
class Test_payer_seg(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.data_to_test = data_to_check
def test_data_qaulity(self):
self.assertTrue(1==1)
The problem seems to occur since under the hood nosetests detects is as python tests and runs it as an internal process, hence __name__ can't possibly become 'main'.
How can I create a flow that runs it as mock if it is launched a main?
Note that this issue may happen since I'm running it using pycharm

pycharm recognize it as unit test and automatically runs it using the installed unit test package.
You can create a new Python configuration with the script full path and working directory. This will run your main section without using the unit tests package.

Related

Why doesn't the test work without if __name__ == '__main__'?

I can't figure out why without the line if __name__ == '__main__': before unittest.main() the test does not find?
I am using the latest version of PyCharm. I know that in order for the test to work in PyCharm, you can not add these lines at all, but I want to deal with the logic itself: why without the line if __name__ == '__main__': the result is as in the screenshot, but if you add it, then everything works?
Code:
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""Tests for 'name_function.py'."""
def test_first_last_name(self):
"""Are names like 'Janis Joplin' working correctly?"""
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')
unittest.main()
There is only one function in the name_function module:
def get_formatted_name(first, last):
"""Builds a formatted full name."""
full_name = f"{first} {last}"
return full_name.title()
Result:
No tests were found
/Users/xxx/Documents/PycharmProjects/Book/venv/bin/python
"/Applications/PyCharm
CE.app/Contents/plugins/python-ce/helpers/pycharm/_jb_unittest_runner.py"
--path /Users/xxx/Documents/PycharmProjects/Book/testing.py
Testing started at 00:22 ...
-------------------------------------------------------------------> Ran 0 tests in 0.000s
OK
Launching unittests with arguments python -m unittest
/Users/xxx/Documents/PycharmProjects/Book/testing.py in
/Users/xxx/Documents/PycharmProjects/Book
Process finished with exit code 0
Empty suite
Empty suite
I am running the testing.py module as the main program, but judging by the answer line PyCharm is running the test via python -m unittest testing.NamesTestCase
I additionally checked the value of the global variable __name__ and indeed it has the value testing, as if testing was imported. Although I launch it initially.
Please explain why in this case the startup script differs from the standard one and when testing.py starts it runs it through unittest? I really want to finally understand this issue. Also don't understand why, in this case, if it initially runs through unittest, unittest.main() doesn't run normally without additional checking if __name__ == '__main__':?

PyCharm doesn't appear to run all unit tests

I have a problem running unittests in pycharm. The first class 'KnownValues' runs but the other class doesn't get checked at all.
import roman
import unittest
class KnownValues(unittest.TestCase):
def test_too_large(self):
'''to_roman should fail with large input'''
self.assertRaises(roman.OutOfRangeError, roman.to_roman, 4000)
def test_too_small(self):
ls = [0,-1,-25,-60]
for x in ls:
self.assertRaises(roman.OutOfRangeError, roman.to_roman, x)
def test_non_int(self):
ls = [1.5, -6.5, 6.8,12.9, "hello wold", "nigga123"]
for x in ls:
self.assertRaises(roman.TypeError, roman.to_roman, x)
class Test2(unittest.TestCase):
def test1(self):
assert 1 == 1
if __name__ == '__main__':
unittest.main()
Start all of your test functions with test. Many people use underscores to separate words, so a lot of people end up with tests starting with test_, but test is all that is required.
When having trouble in the GUI, you can check how your tests are running from the command line.
python test.py
or
python -m test
One problem that you might run into is that you have defined your tests within classes, and when running them through the GUI, the GUI has automatically discovered them for you. Be sure to include the lines at the end of your test file directing the interpreter to use the main function built into unittest.
if __name__ == '__main__':
unittest.main()
Keep in mind, you can optionally run the tests in only one of your classes at a time:
python tests.py KnownValues
python tests.py Test2
In PyCharm, it should automatically discover all the test classes. You still have the option of running only one class at a time. Choose Run->Edit Configurations to see the options that you are currently running under. Using command line parameters you can control running fewer or more tests.
As you can see, you can choose to run a script, a class, or a method. Be sure to set the name of your run configuration such that it reflects the scope of what you are running.

Python script runs perfect in PyCharm but in terminal don't

I really don't understand... If you need screenshots of some settings please tell me because I really don't know why it works in PyCharm but not outside Pycharm...
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import unittest
from datetime import datetime
class MYMaster(unittest.TestCase):
def Test_login(self):
<<<<< MY CODE >>>>>
if __name__ == '__main__':
unittest.main()
If I right click in PyCharm on line class MYMaster(unittest.TestCase): and select option Run 'Unittest in MYMaster' it will send this code
C:\Users\MyNameIs\AppData\Local\Programs\Python\Python35-32\python.exe"C:\Program Files (x86)\JetBrains\PyCharm 4.5.4\helpers\pycharm\utrunner.py" C:\Users\MyNameIs\PycharmProjects\untitled\MyProject\MyMain.py::MYMaster true
Testing started at 15:42 ...
Process finished with exit code 0
Empty test suite.
If I right click on def Test_login(self):and select option Run 'Unittest TestLogin' it will send this code (But it runs entire code and give results).
C:\Users\MyNameIs\AppData\Local\Programs\Python\Python35-32\python.exe "C:\Program Files (x86)\JetBrains\PyCharm 4.5.4\helpers\pycharm\utrunner.py" C:\Users\MyNameIs\PycharmProjects\untitled\MyProject\MyMain.py::MYMaster::Test_login true
Testing started at 15:50 ...
Process finished with exit code 0
Now I decided to open the MyMain.py in Python IDLE where I clicked Run module and this are the results:
= RESTART: C:\Users\MyNameIs\PycharmProjects\untitled\MyProject\MyMain.py =
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
In Pycharm under Tool>Python Integrated Tools Default test runner =
Unittests Docstring format = reStructuredText Checked checkbox Analyze
Python code in docstrings
When you run unittests in Pycharm, Pycharm provides a wrapper that executes other code before your code.
To execute unittests from the terminal, you should use this command, provided that you have python set in your PATH:
python -m unittest /path/to/script_with_tests.py
You should also make sure that your functions' names start with test, ie test_login.
From unittest documentation:
A testcase is created by subclassing unittest.TestCase. The three individual tests are defined with methods whose names start with the letters test. This naming convention informs the test runner about which methods represent tests.

PyCharm + cProfile + py.test --> pstat snapshot view + call graph are empty

In PyCharm, I set up py.test as the default test runner.
I have a simple test case:
import unittest
import time
def my_function():
time.sleep(0.42)
class MyTestCase(unittest.TestCase):
def test_something(self):
my_function()
Now I run the test by right-clicking the file and choosing Profile 'py.test in test_profile.py'.
I see the test running successfully in the console (it says collected 1 items). However, the Statistics/Call Graph view showing the generated pstat file is empty and says Nothing to show.
I would expect to see profiling information for the test_something and my_function. What am I doing wrong?
Edit 1:
If I change the name of the file to something which does not start with test_, remove the unittest.TestCase and insert a __main__ method calling my_function, I can finally run cProfile without py.test and I see results.
However, I am working on a large project with tons of tests. I would like to directly profile these tests instead of writing extra profiling scripts. Is there a way to call the py.test test-discovery module so I can retrieve all tests of the project recursively? (the unittest discovery will not suffice since we yield a lot of parametrized tests in generator functions which are not recognized by unittest). This way I could at least solve the problem with only 1 additional script.
Here is a work-around. Create an additional python script with the following contents (adapt the path to the tests-root accordingly):
import os
import pytest
if __name__ == '__main__':
source_dir = os.path.dirname(os.path.abspath(__file__))
test_dir = os.path.abspath(os.path.join(source_dir, "../"))
pytest.main(test_dir, "setup.cfg")
The script filename must not start with test_, else pycharm will force you to run it with py.test. Then right-click the file and run it with Profile.
This also comes in handy for running it with Coverage.

Is it possible to run all unit test?

I have two module with two different classes and their corresponding test classes.
foo.py
------
class foo(object):
def fooMethod(self):
// smthg
bar.py
------
class bar(object):
def barMethod(self):
// smthg
fooTest.py
------
class fooTest(unittest.TestCase):
def fooMethodTest(self):
// smthg
barTest.py
------
class barTest(unittest.TestCase):
def barMethodTest(self):
// smthg
In any, test and source module, file, I erased the if __name__ == "__main__": because of increasing coherency and obeying object-oriented ideology.
Like in Java unit test, I'm looking for creating a module to run all unittest. For example,
runAllTest.py
-------------
class runAllTest(unittest.TestCase):
?????
if __name__ == "__main__":
?????
I looked for search engine but didn't find any tutorial or example. Is it possible to do so? Why? or How?
Note: I'm using eclipse and pydev distribution on windows machine.
When running unit tests based on the built-in python unittest module, at the root level of your project run
python -m unittest discover <module_name>
For the specific example above, it suffices to run
python -m unittest discover .
https://docs.python.org/2/library/unittest.html
You could create a TestSuite and run all your tests in it's if __name__ == '__main__' block:
import unittest
def create_suite():
test_suite = unittest.TestSuite()
test_suite.addTest(fooTest())
test_suite.addTest(barTest())
return test_suite
if __name__ == '__main__':
suite = create_suite()
runner=unittest.TextTestRunner()
runner.run(suite)
If you do not want to create the test cases manually look at this quesiton/answer, which basically creates the test cases dynamically, or use some of the features of the unittest module like test discovery feature and command line options ..
I think what you are looking for is the TestLoader. With this you can load specific tests or modules or load everything under a given directory. Also, this post has some useful examples using a TestSuite instance.
EDIT: The code I usually have in my test.py:
if not popts.tests:
suite = unittest.TestLoader().discover(os.path.dirname(__file__)+'/tests')
#print(suite._tests)
# Print outline
lg.info(' * Going for Interactive net tests = '+str(not tvars.NOINTERACTIVE))
# Run
unittest.TextTestRunner(verbosity=popts.verbosity).run(suite)
else:
lg.info(' * Running specific tests')
suite = unittest.TestSuite()
# Load standard tests
for t in popts.tests:
test = unittest.TestLoader().loadTestsFromName("tests."+t)
suite.addTest(test)
# Run
unittest.TextTestRunner(verbosity=popts.verbosity).run(suite)
Does two things:
If -t flag (tests) is not present, find and load all tests in directory
Else, load the requested tests one-by-one
I think you could just run the following command under the folder where your tests files are located:
python -m unittest
as mentioned here in the doc that "when executed without arguments Test Discovery is started"
With PyDev right click on a folder in Eclipse and choose "Run as-> Python unit-test". This will run all tests in that folder (the names of the test files and methods have to start with "test_".)
You are looking for nosetests.
You might need to rename your files; I'm not sure about the pattern nose uses to find the test files but, personally, I use *_test.py. It is possible to specify a custom pattern which your project uses for test filenames but I remember being unable to make it work so I ended up renaming my tests instead.
You also need to follow PEP 328 conventions to work with nose. I don't use IDEs with Python but your IDE may already follow it---just read the PEP and check.
With a PEP 328 directory/package structure, you can run individual tests as
nosetests path.to.class_test
Note that instead of the usual directory separators (/ or \), I used dots.
To run all tests, simply invoke nosetests at the root of your project.

Categories