django testrunner not running my tests - python

I've got the following tests.py file:
from django.test import TestCase
from lxml import etree
import tempfile
import utils
class CreateSurveyFromCsvTextTests(TestCase):
def parsesSurveyPassedInAsCsvAndReturnsXmlRepresentation(self):
text = """"survey",,,,,
,"name","type","label","hint","required"
,"gps","geopoint","Record your current location",,"false"
,"start","start",,,
,"end","end",,,
"settings",
,"form_title"
,"New survey" """
xml = create_survey_from_csv_text(text)
lxml.fromstring(xml)
when I run my module with python manage.py test, the output is
Ran 0 tests in 0.000s
I know the runner is picking up the file because if I make an invalid import it throws an error.
Why is the test not being called?

The name of the test methods need to start with test_. This allows the class to have both test methods and helper methods that you may write as well.
Hence you should rename your method to test_parsesSurveyPassedInAsCsvAndReturnsXmlRepresentation (and perhaps shorten the name too).

Related

Django tests manage.py

To run my Django's tests, I was using the manage.py file.
But I decided to create my own file runtests.py.
As specified in the Django's doc, the manage.py file will execute all methods whose name is starting like "test" and whose class inherits TestCase !
My aim is to use this searching method to display all possible tests (not running them).
So do you know where I could get this "searching method" ?
Thank you !
What you're looking for is called "test discovery", and you don't need to do it manually.
If you want to write a standalone script that runs your tests, you can simply invoke Django's test runner manually from Python code after configuring. The process for this is:
# First you need settings.
# You can do this by setting DJANGO_SETTINGS_MODULE:
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'path.to.your.settings')
# Or you can do it manually:
SETTINGS_DICT = {
# Put all the settings you'll need in here...
}
from django.conf import settings
settings.configure(**SETTINGS_DICT)
import django
django.setup()
import sys
# Now you can run tests:
from django.test.utils import get_runner
TestRunner = get_runner(settings)
test_runner = TestRunner(verbosity=2, interactive=True)
failures = test_runner.run_tests(
['test_module_to_look_in']
)
sys.exit(bool(failures))

Import classes from child directory python

I've been trying to import some python classes which are defined in a child directory. The directory structure is as follows:
workspace/
__init__.py
main.py
checker/
__init__.py
baseChecker.py
gChecker.py
The baseChecker.py looks similar to:
import urllib
class BaseChecker(object):
# SOME METHODS HERE
The gChecker.py file:
import baseChecker # should import baseChecker.py
class GChecker(BaseChecker): # gives a TypeError: Error when calling the metaclass bases
# SOME METHODS WHICH USE URLLIB
And finally the main.py file:
import ?????
gChecker = GChecker()
gChecker.someStuff() # which uses urllib
My intention is to be able to run main.py file and call instantiate the classes under the checker/ directory. But I would like to avoid importing urllib from each file (if it is possible).
Note that both the __init__.py are empty files.
I have already tried calling from checker.gChecker import GChecker in main.py but a ImportError: No module named checker.gChecker shows.
In the posted code, in gChecker.py, you need to do
from baseChecker import BaseChecker
instead of import baseChecker
Otherwise you get
NameError: name 'BaseChecker' is not defined
Also with the mentioned folders structure you don't need checker module to be in the PYTHONPATH in order to be visible by main.py
Then in main.y you can do:
from checker import gChecker.GChecker

Make a python py.test unit test run independantly of the location where py.test in executed?

Lets say my code looks like this
import pytest
import json
#pytest.fixture
def test_item():
test_item = json.load(open('./directory/sample_item_for_test.json','rb'))
return test_item
def test_fun(test_document):
assert type(test_item.description[0]) == unicode
And I would like to run this test via Py.Test
If I run Py.test from the directory that it is in, it is fine. BUT if I run it from an above directory, it fails due to not being able to find 'sample_item_for_test.json'. Is there a way to make this test run correctly no matter where I execute Py.test?
The magic attribute __file__ is the path to the python file on the filesystem. So, you can use that with some magic from os to get the current directory...
import pytest
import json
import os
_HERE = os.path.dirname(__file__)
_TEST_JSON_FILENAME = os.path.join(_HERE, 'directory', 'sample_item_for_test.json')
#pytest.fixture
def test_item():
with open(_TEST_JSON_FILENAME, 'rb') as file_input:
return json.load(file_input)
When I migrated to py.test, I had a large set of legacy tests that were accustomed to being executed in the directory where the test file lives. Instead of tracking down every test failure, I added a pytest hook to my conftest.py to chdir to the test directory before each test starts:
import os
import functools
def pytest_runtest_setup(item):
"""
Execute each test in the directory where the test file lives.
"""
starting_directory = os.getcwd()
test_directory = os.path.dirname(str(item.fspath))
os.chdir(test_directory)
teardown = functools.partial(os.chdir, starting_directory)
# There's probably a cleaner way than accessing a private member.
item.session._setupstate.addfinalizer(teardown, item)

Testing Django Commands with Mock

I have a command that I would like to test. It hits external services and I would like to mock out the function calls that hit these external services, only check that they were called with the proper arguments. The code looks like this:
import mock
from django.core.management import call_command
from myapp.models import User
class TestCommands(TestCase):
def test_mytest(self):
import package
users = User.objects.filter(can_user_service=True)
with mock.patch.object(package, 'module'):
call_command('djangocommand', my_option=True)
package.module.assert_called_once_with(users)
When I run it however I keep getting AssertionError: Expected to be called once. Called 0 times. I assume this is because I am not actually calling the module within the context, I am calling it in call_command('djangocommand', my_option=True), but shouldn't all calls to this module be mocked out while the context is active? If not, does anyone have suggestions for how such a test could be conducted?
The reference you need to patch is the 'module' attribute reference in django.core.management. Attempting to mock the package reference in the test file doesn't change the reference in django.core.management.
You'll need to do something like
import mock
from django.core.management import call_command
import django.core.management
from myapp.models import User
class TestCommands(TestCase):
def test_mytest(self):
users = User.objects.filter(can_user_service=True)
with mock.patch.object(django.core.management, 'module'):
call_command('djangocommand', my_option=True)
django.core.management.module.assert_called_once_with(users)

Running Tests From a Module

I am attempting to run some unit tests in python from what I believe is a module. I have a directory structure like
TestSuite.py
UnitTests
|__init__.py
|TestConvertStringToNumber.py
In testsuite.py I have
import unittest
import UnitTests
class TestSuite:
def __init__(self):
pass
print "Starting testting"
suite = unittest.TestLoader().loadTestsFromModule(UnitTests)
unittest.TextTestRunner(verbosity=1).run(suite)
Which looks to kick off the testing okay but it doesn't pick up any of the test in TestConvertNumberToString.py. In that class I have a set of functions which start with 'test'.
What should I be doing such that running python TestSuite.py actually kicks off all of my tests in UnitTests?
Here is some code which will run all the unit tests in a directory:
#!/usr/bin/env python
import unittest
import sys
import os
unit_dir = sys.argv[1] if len(sys.argv) > 1 else '.'
os.chdir(unit_dir)
suite = unittest.TestSuite()
for filename in os.listdir('.'):
if filename.endswith('.py') and filename.startswith('test_'):
modname = filename[:-2]
module = __import__(modname)
suite.addTest(unittest.TestLoader().loadTestsFromModule(module))
unittest.TextTestRunner(verbosity=2).run(suite)
If you call it testsuite.py, then you would run it like this:
testsuite.py UnitTests
Using Twisted's "trial" test runner, you can get rid of TestSuite.py, and just do:
$ trial UnitTests.TestConvertStringToNumber
on the command line; or, better yet, just
$ trial UnitTests
to discover and run all tests in the package.

Categories

Resources