Tests in 1.6

63 views
Skip to first unread message

Larry Martell

unread,
Jul 10, 2014, 3:35:12 PM7/10/14
to django...@googlegroups.com
I am trying to upgrade a site to 1.6. I read the change notes about
the tests now having to start with test.

My project's structure is this:

myproj/app/appname/tests

and in that dir was a file called EventLog.py, and in that file a
function called EventLogTest

My __init__ had:

from myproj.app.appname.tests.EventLog import EventLogTest

I would run the test with:

manage.py test appname.EventLogTest

I reanmed EventLog.py to testEventLog.py, and I also changed it in the
__init__ file to:

from myproj.app.appname.tests.testEventLog import EventLogTest

Then I tried:

manage.py test appname.EventLogTest

ImportError: No module named appname

manage.py test app.appname.EventLogTest

ImportError: No module named app

manage.py test myproj.app.appname.EventLogTest

AttributeError: 'module' object has no attribute 'EventLogTest'

manage.py test myproj.app.appname.tests.EventLogTest

AttributeError: 'module' object has no attribute 'tests'


What simple, stupid thing I am doing wrong here? What do I have to do
to run my tests in 1.6?


Thanks!
-larry

Russell Keith-Magee

unread,
Jul 10, 2014, 8:40:41 PM7/10/14
to Django Users
It depends where you're coming from, and how long you need your project to last.

If you've got a working Django 1.5 project, and you just need to get it into 1.6 as fast as possible, then just add

TEST_RUNNER = 'django.test.simple.DjangoTestSuiteRunner'

to your settings file, and you're done. Your 1.6 test suite will run exactly the same as it does in 1.5, and there won't be any change to the way your test suite runs - no changes to the way the tests are found, and no change to the way you execute them. That means:

 * If you've got a tests *package*, you'll have to put a bunch of imports in the tests/__init__.py module so that all the test classes are sitting in the appname.tests namespace

 * When you run a test, you run one of:
   - manage.py test appname
   - manage.py test appname.TestClassName
   - manage.py test appname.TestClassName.test_this_feature

However, if you want to upgrade to the "new" behaviour in 1.6, you need to make other changes. 

The "new" test runner doesn't require the imports in tests/__init__.py. It does automated discovery of file in those submodules named test*.py. If your tests aren't in files with "discoverable" names, you'll need to either rename the files (and directories), or manually point manage.py test at the right filenames.

If you've got a newly-structured test suite, then invoking tests is slightly different, too:
   - manage.py test appname
   - manage.py test appname.tests.test_submodule.TestClassName
   - manage.py test appname.tests.test_submodule.TestClassName.test_this_feature

That is, you give the fully qualified Python module name of a test class, not just the 'app name.classname' simplification.

See https://docs.djangoproject.com/en/dev/topics/testing/overview/#running-tests for more details, including details of how to include files other than test_*.

As an aside - if you want your project to be long lived, you'll *eventually* need to make these naming changes to your test suite. It's just a question of whether you need to do it *right now*. The old approach will still work in 1.6; it will also work in 1.7, but will be more noisy. In 1.8, the DjangoTestSuiteRunner will be removed completely. So, if you want your project test suite to last until Django 1.8 and beyond, you'll ultimately need to make these changes.

I hope that helps.

Yours,
Russ Magee %-)

Larry Martell

unread,
Jul 11, 2014, 9:38:17 AM7/11/14
to django...@googlegroups.com
I appreciate the detailed reply, and I think I understand all this,
but I still cannot get my tests to run. Let's look at one test.

My tests are in this dir: /usr/local/motor/motor/app/cdsem/tests
A file with a test is called: testEventLog.py
In that file is a class EventLogTest

I am running manage.py from /usr/local/motor

How would I run that test?

I have tried:

manage.py test app.cdsem.tests.testEventLog
manage.py test app.cdsem.tests.testEventLog.EventLogTest
manage.py test cdsem.tests.testEventLog
manage.py test cdsem.tests.testEventLog.EventLogTest
manage.py test motor.app.cdsem.tests.testEventLog
manage.py test motor.app.cdsem.tests.testEventLog.EventLogTest
manage.py test tests.testEventLog.EventLogTest

And none of them find the test. What am I doing wrong?

Thanks!

Russell Keith-Magee

unread,
Jul 11, 2014, 10:44:58 AM7/11/14
to Django Users
Hi Larry

On Fri, Jul 11, 2014 at 9:37 PM, Larry Martell <larry....@gmail.com> wrote:
On Thu, Jul 10, 2014 at 8:35 PM, Russell Keith-Magee
<rus...@keith-magee.com> wrote:

I appreciate the detailed reply, and I think I understand all this,
but I still cannot get my tests to run. Let's look at one test.

My tests are in this dir: /usr/local/motor/motor/app/cdsem/tests

Ok - 

 * Do you have an __init__.py in the cdsem/tests directory? 

 * Which directory is manage.py in? 

 * What's your PYTHONPATH?

I have a suspicion that the problem might be caused by your directory structure. There's a few more directories there than I would expect to see, which suggests to me that there might be problem with the interaction of PYTHONPATH with manage.py.

One way that might help diagnose the problem: 

./manage.py test -v 2

This turns up the verbosity on the full test suite, and will tell you the test paths that are being executed. When it runs, you'll see lines like:

test_other_size (lillee.tests.WidgetTestCase) ... ok
test_resize (lillee.tests.WidgetTestCase) ... ok

That tells you the path that is being discovered, which you can put back into ./manage.py to run the test.

./manage.py test lillee.tests.WidgetTestCase.test_resize

Yours,
Russ Magee %-)

Larry Martell

unread,
Jul 11, 2014, 11:16:46 AM7/11/14
to django...@googlegroups.com
On Fri, Jul 11, 2014 at 10:44 AM, Russell Keith-Magee
<rus...@keith-magee.com> wrote:
> Hi Larry
>
> On Fri, Jul 11, 2014 at 9:37 PM, Larry Martell <larry....@gmail.com>
> wrote:
>>
>> On Thu, Jul 10, 2014 at 8:35 PM, Russell Keith-Magee
>> <rus...@keith-magee.com> wrote:
>>
>> I appreciate the detailed reply, and I think I understand all this,
>> but I still cannot get my tests to run. Let's look at one test.
>>
>> My tests are in this dir: /usr/local/motor/motor/app/cdsem/tests
>
>
> Ok -
>
> * Do you have an __init__.py in the cdsem/tests directory?

Yes. I changed it from this:

from motor.app.cdsem.tests.EventLog import EventLogTest

to this:

from motor.app.cdsem.tests.testEventLog import EventLogTest

> * Which directory is manage.py in?

/usr/local/motor

> * What's your PYTHONPATH?

That is not set.

> I have a suspicion that the problem might be caused by your directory
> structure. There's a few more directories there than I would expect to see,
> which suggests to me that there might be problem with the interaction of
> PYTHONPATH with manage.py.

This all works with 1.5.

> One way that might help diagnose the problem:
>
> ./manage.py test -v 2

With no args I see:

motor.app.cdsem.tests.testEventLog
(unittest.loader.ModuleImportFailure) ... ERROR

When I run:

./manage.py test -v 2 motor.app.cdsem.tests.testEventLog

I get:

AttributeError: 'module' object has no attribute 'tests'


This is the full traceback:

File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/Library/Python/2.7/site-packages/django/core/management/__init__.py",
line 399, in execute_from_command_line
utility.execute()
File "/Library/Python/2.7/site-packages/django/core/management/__init__.py",
line 392, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Library/Python/2.7/site-packages/django/core/management/commands/test.py",
line 50, in run_from_argv
super(Command, self).run_from_argv(argv)
File "/Library/Python/2.7/site-packages/django/core/management/base.py",
line 242, in run_from_argv
self.execute(*args, **options.__dict__)
File "/Library/Python/2.7/site-packages/django/core/management/commands/test.py",
line 71, in execute
super(Command, self).execute(*args, **options)
File "/Library/Python/2.7/site-packages/django/core/management/base.py",
line 285, in execute
output = self.handle(*args, **options)
File "/Library/Python/2.7/site-packages/django/core/management/commands/test.py",
line 88, in handle
failures = test_runner.run_tests(test_labels)
File "/Library/Python/2.7/site-packages/django/test/runner.py", line
144, in run_tests
suite = self.build_suite(test_labels, extra_tests)
File "/Library/Python/2.7/site-packages/django/test/runner.py", line
63, in build_suite
tests = self.test_loader.loadTestsFromName(label)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/loader.py",
line 100, in loadTestsFromName
parent, obj = obj, getattr(obj, part)

Larry Martell

unread,
Jul 11, 2014, 2:10:01 PM7/11/14
to django...@googlegroups.com
I figured this out - I was just trying to get this one test going
initially. But I have 16 tests in my __init__ file and it didn't like
something about those. I commented out all but the one I am working on
and it worked. I'll add them back one at a time as I convert them for
1.6. Thanks for the help Russ.
Reply all
Reply to author
Forward
0 new messages