# for loop in django unittest

**URL:** <https://forum.djangoproject.com/t/for-loop-in-django-unittest/10062>\
**Category:** Using Django\
**Created:** [October 11, 2021, 5:23am UTC](https://forum.djangoproject.com/t/for-loop-in-django-unittest/10062 "2021-10-11T05:23:21Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yang](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/yang/32/5977_2.png) [@Yang](https://forum.djangoproject.com/u/Yang)\
**Post date:** [October 11, 2021, 5:23am UTC](https://forum.djangoproject.com/t/for-loop-in-django-unittest/10062/1 "2021-10-11T05:23:21Z")

</div>

I want to test register view in django project,

so I build some fake test cases(`self.correct_samples`)

after register successfully, it should redirect to home page which means the status code should be 302.

```python
from django.test import TestCase
from django.urls.base import reverse

class RegisterTests(TestCase):

    def setUp(self):
        url = reverse('account:register')
        self.response = self.client.get(url)

        self.correct_samples = (
            ('testuser1@email.com', 'testuser', 'test112233', 'test112233'),
            ('fakeuser@email.com', 'fake123', 'fakeuser111', 'fakeuser111'),
            ('correct@email.com', 'Jack', 'myfavorite', 'myfavorite'),

            ('failemail', 'Jack', 'myfavorite', 'myfavorite'), # fail for purpose
        )

    def test_register_form(self):

        for test_case in self.correct_samples:

            email, username, password1, password2 = test_case
            self.response = self.client.post(reverse('account:register'), data={
                'email': email,
                'username': username,
                'password1': password1,
                'password2': password2,
            })

            self.assertEqual(self.response.status_code, 302)
            self.assertRedirects(
                self.response, expected_url='/', status_code=302, target_status_code=200)

```

The fourth data in `self.correct_samples` which is `('failemail', 'Jack', 'myfavorite', 'myfavorite')` should be a fail case.

but after `python manage.py test`. It passed.

```auto
(env) C:\Users\User\myblog>python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
C:\Users\User\myblog\env\lib\site-packages\whitenoise\base.py:115: UserWarning: No directory at: C:\Users\User\myblog\staticfiles\
  warnings.warn(u"No directory at: {}".format(root))
.
----------------------------------------------------------------------
Ran 1 test in 0.195s

OK
Destroying test database for alias 'default'...

```

* * *

Here comes the tricky thing,

it failed after switching order from fourth to first.

```python
from django.test import TestCase
from django.urls.base import reverse

class RegisterTests(TestCase):

    def setUp(self):
        ...

        self.correct_samples = (
            ('failemail', 'Jack', 'myfavorite', 'myfavorite'), # fail for purpose

            ('testuser1@email.com', 'testuser', 'test112233', 'test112233'),
            ('fakeuser@email.com', 'fake123', 'fakeuser111', 'fakeuser111'),
            ('correct@email.com', 'Jack', 'myfavorite', 'myfavorite'),
        )

    def test_register_form(self):
        ...

```

result:

```auto
(env) C:\Users\User\myblog>python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
C:\Users\User\myblog\env\lib\site-packages\whitenoise\base.py:115: UserWarning: No directory at: C:\Users\User\myblog\staticfiles\
  warnings.warn(u"No directory at: {}".format(root))
F
======================================================================
FAIL: test_register_form (account.tests.RegisterTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\User\myblog\account\tests.py", line 34, in test_register_form
    self.assertEqual(self.response.status_code, 302)
AssertionError: 200 != 302

----------------------------------------------------------------------
Ran 1 test in 0.026s

FAILED (failures=1)
Destroying test database for alias 'default'...

```

# **Why this happened?**

I have searched for related keywords like `unittest in forloop`, `multiple testcases in forloop`.

but it seems no answers for it, or maybe search through other keywords?

or something I missed or misunderstood?

thanks for helping.

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [October 11, 2021, 11:10am UTC](https://forum.djangoproject.com/t/for-loop-in-django-unittest/10062/2 "2021-10-11T11:10:12Z")

</div>

Hi Yang

The problem you’re seeing is almost certainly a lack of isolation between your tests.  
I can’t quite work it out without doing debugging with your actual view code.  
But I can help you improve your tests.

Running several tests in one function is not a good idea, because they cannot run and fail independently.  
If the a test fails, we get no information about the later tests, since they don’t run.  
Plus it increases the chance that something will “leak” between the tests, causing the kind of bug you’re seeing.

unittest does provide the `subTest()` helper, but I prefer to write independent tests, or use [parameterized](https://pypi.org/project/parameterized/).  
Independent tests are great since we can name them to provide some information on what we’re looking for.  
So to do that with your tests:

```python
from django.test import TestCase
from django.urls.base import reverse

class RegisterTests(TestCase):
        
    def check_register(self, email, username, password1, password2):
        response = self.client.post(reverse('account:register'), data={
            'email': email,
            'username': username,
            'password1': password1,
            'password2': password2,
        })

        self.assertEqual(response.status_code, 302)
        self.assertRedirects(
            response, expected_url='/', status_code=302, target_status_code=200)

    def test_register_long_password(self):
        self.check_register('testuser1@example.com', 'testuser', 'test112233', 'test112233')
    
    def test_register_numerical_username(self):
        self.check_register('fakeuser@example.com', 'fake123', 'fakeuser111', 'fakeuser111')
    
    def test_register_capitalized_username(self):
        self.check_register('correct@example.com', 'Jack', 'myfavorite', 'myfavorite')
    
    def test_register_fail_bad_email(self):
        self.check_register('failemail', 'Jack', 'myfavorite', 'myfavorite')

```

Note also:

- You had what seems to be an unnecessary `self.client.get(url)` in the `setUp()`, which I’ve removed.  
If this _is_ necessary because it sets a cookie or session data, then it should be added to `check_register()`.  
Before this was only done for the first test, which may have been the cause of your failure.

- Use [example.com](https://example.com/) for test data, as it’s the domain explicitly registered for examples.  
[email.com](http://email.com) might be a real email provider, so if your tests accidentally sent emails, you’d sent potentially sensitive information to random accounts!

Hope this helps,

Adam

---

<div class="post-metadata">

**Author:** ![Yang](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/yang/32/5977_2.png) [@Yang](https://forum.djangoproject.com/u/Yang)\
**Post date:** [October 12, 2021, 7:30am UTC](https://forum.djangoproject.com/t/for-loop-in-django-unittest/10062/3 "2021-10-12T07:30:56Z")

</div>

Hi Adam

Problem has been solved through [parameterized](https://pypi.org/project/parameterized/), this package seems pretty much for my original intention. `subtest()` doesn’t work, still need to separate each test case for one test function.

Thanks for your informative advice, especially the concept about naming test function for different scenario and [example.com](https://example.com/) information. Really appreciate. 😀
