KindOfGuy
KindOfGuy

Reputation: 3211

How to debug failing tests in Django?

How do I debug my tests? For example, I POST to create an entry and expect it to validate and return a particular page. It works in the browser and in the shell, but the test is the only thing that fails (ironically!). I would like to print the response to the console or something so I could read errors or what have you. But I can only see things that I print in e.g. the view.

Not sure it's necessary, but here's the test code in question from tests.py:

    resp = self.client.post('/meal/invite/', 
        {'summary': 'Test munch', 'when': now(), 'max_diners': '1', 'description': 'Munchies'}, follow=True)
    self.assertEqual(resp.status_code, 200)
    self.assertContains(resp, 'Test munch', 1)
    self.assertContains(resp, 'You are hosting this meal', 1)

The final assertion is incorrect. If I change it to a value present in the original form page showing 'field required' errors, it passes. I just can't see what I'm missing.

I have a few other tests working, but I just don't know how to debug this.

How is it done?

Upvotes: 29

Views: 23627

Answers (7)

Constantinos Petrakis
Constantinos Petrakis

Reputation: 91

Django by default sets DEBUG to False when running tests to emulate a production environment and get better performance.

When your tests fail and you don't know why (except a nice HTTP 4xx, 5xx status code) that essentially tells you nothing you can set DEBUG to True.

To do that, run the tests with the debug-mode flag like this:

python manage.py test --debug-mode

Source: How do you set DEBUG to True when running a Django test?

Upvotes: 1

Lisa Treweek
Lisa Treweek

Reputation: 1

in pycharm you can put a test in tests.py using TestCase library then highlight that test and then rt click to get the option to runtests.tests in debug mode. Very convenient and puts making unit tests in my regular development cycle.

Upvotes: 0

Peheje
Peheje

Reputation: 14234

If you are using vscode, you can create a new configuration inside your root/vscode/launch.json file like so:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Django RUN",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/manage.py",
            "args": [
                "runserver",
                "--noreload",
                "--nothreading"
            ],
            "django": true
        },
        {
            "name": "Django TEST",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/manage.py",
            "args": [
                "test",
                "<your-app-name>",
            ],
            "django": true
        }
    ]
}

This allows you to put breakpoints in your tests and debug using vscode.

Upvotes: 15

daigorocub
daigorocub

Reputation: 806

One can use eclipse IDE with Pydev, create a Debug configuration where the Arguments are the test command. Something like:

test  users.tests.selenium_tests.UsersTestCase.test_user_creation --keepdb --settings=project.settings.test_settings

enter image description here

And then, use the Pydev debugger with breakpoints and step by step workflow, variables, expressions, etc.

The docs are here (http://www.pydev.org/manual_adv_debugger.html) but don't refer to Django.

Upvotes: 0

Brenda J. Butler
Brenda J. Butler

Reputation: 1485

To run the test under pdb:

python -m pdb manage.py test yourapp

I agree with Alasdair, the print response.content (and printing stuff in general) is a great help. The output gets mixed up with the normal test runner output, and should be removed once you find the problem and fix it, but it can help you narrow down the problem.

Also, if the code works in the browser and the shell but not the unit test, remember that the unit test makes a new (empty) database. Ensure that your setUp puts in any data that is required for your test.

(Updated the code part from Patrick's suggestion, thanks Patrick)

Upvotes: 16

dm03514
dm03514

Reputation: 55972

You can drop in a pdb and inspect everything.

If you're using nose i believe you have to run your tests with -s

 -s, --nocapture       Don't capture stdout (any stdout output will be
                        printed immediately) [NOSE_NOCAPTURE]

This is what keeps you from seeing output immediately.

Upvotes: 13

Alasdair
Alasdair

Reputation: 309099

The simplest thing to do is add print response.content before your assertion. The output can be a little overwhelming, but often its enough to let you spot the problem.

If that doesn't solve it, there are loads of features listed in the docs which can help. Add a few print statements and see what you get. Here's a few suggestions, but don't limit yourself to these, there are more tools in the docs.

https://docs.djangoproject.com/en/dev/topics/testing/

First, you need to check that the page is actually redirecting as you expect. Try using redirect_chain or assertRedirects.

I suspect that your post data is not valid for some reason. You can grab the form from the response context.

form = response.context['form']
print form.is_valid()
print form.errors

Upvotes: 7

Related Questions