Qiita Django Advent Calendar 2021 4日目は、Django 4.0のtestコマンドに追加された--shuffleオプションについて紹介します。 --shuffleオプションについての公式ドキュメントの説明は以下を参照してください。

django-admin and manage.py | Django documentation | Django

Django 4.0からは、testコマンド実行時に--shuffleオプションを付けるとテストメソッドの実行順が毎回ランダムに並べ替えられます。 これを使うことで、特定の実行順でないと成功しないテストに気づきやすくなります。

Django 4.0未満で同様のことをするには、pytestdjango-pytestpytest-randomlyを組み合わせるしかありませんでしたが、標準機能でできるようになったのは嬉しいですね。

以下のサンプルコードを用意して、実際に--shuffleオプションを使ってみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from django.test import TestCase


class Example1Test(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        print("example1")

    def test_1(self):
        print("example1-test1")

    def test_2(self):
        print("example1-test2")

    def test_3(self):
        print("example1-test3")

    def test_4(self):
        print("example1-test4")

    def test_5(self):
        print("example1-test5")


class Example2Test(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        print("example2")

    def test_1(self):
        print("example2-test1")

    def test_2(self):
        print("example2-test2")

    def test_3(self):
        print("example2-test3")

    def test_4(self):
        print("example2-test4")

    def test_5(self):
        print("example2-test5")

上記テストを--shuffleオプション付きで何度か実行すると、テストメソッドの実行順が毎回違っていることがわかります。1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
$ ./manage.py test --shuffle -v 2
Using shuffle seed: 9050151650 (generated)
(省略)
example2
test_1 (example.tests.Example2Test) ... example2-test1
ok
test_2 (example.tests.Example2Test) ... example2-test2
ok
test_3 (example.tests.Example2Test) ... example2-test3
ok
test_4 (example.tests.Example2Test) ... example2-test4
ok
test_5 (example.tests.Example2Test) ... example2-test5
ok
example1
test_3 (example.tests.Example1Test) ... example1-test3
ok
test_2 (example.tests.Example1Test) ... example1-test2
ok
test_1 (example.tests.Example1Test) ... example1-test1
ok
test_4 (example.tests.Example1Test) ... example1-test4
ok
test_5 (example.tests.Example1Test) ... example1-test5
ok

----------------------------------------------------------------------
Ran 10 tests in 0.017s

OK
Used shuffle seed: 9050151650 (generated)
Destroying test database for alias 'default' ('test_django40_example')...
$ ./manage.py test --shuffle -v 2
Using shuffle seed: 5827039468 (generated)
(省略)
example1
test_4 (example.tests.Example1Test) ... example1-test4
ok
test_5 (example.tests.Example1Test) ... example1-test5
ok
test_1 (example.tests.Example1Test) ... example1-test1
ok
test_3 (example.tests.Example1Test) ... example1-test3
ok
test_2 (example.tests.Example1Test) ... example1-test2
ok
example2
test_1 (example.tests.Example2Test) ... example2-test1
ok
test_4 (example.tests.Example2Test) ... example2-test4
ok
test_2 (example.tests.Example2Test) ... example2-test2
ok
test_5 (example.tests.Example2Test) ... example2-test5
ok
test_3 (example.tests.Example2Test) ... example2-test3
ok

----------------------------------------------------------------------
Ran 10 tests in 0.015s

OK
Used shuffle seed: 5827039468 (generated)
Destroying test database for alias 'default' ('test_django40_example')...
$ ./manage.py test --shuffle -v 2
Using shuffle seed: 927016270 (generated)
(省略)
example1
test_2 (example.tests.Example1Test) ... example1-test2
ok
test_3 (example.tests.Example1Test) ... example1-test3
ok
test_1 (example.tests.Example1Test) ... example1-test1
ok
test_4 (example.tests.Example1Test) ... example1-test4
ok
test_5 (example.tests.Example1Test) ... example1-test5
ok
example2
test_4 (example.tests.Example2Test) ... example2-test4
ok
test_5 (example.tests.Example2Test) ... example2-test5
ok
test_1 (example.tests.Example2Test) ... example2-test1
ok
test_3 (example.tests.Example2Test) ... example2-test3
ok
test_2 (example.tests.Example2Test) ... example2-test2
ok

----------------------------------------------------------------------
Ran 10 tests in 0.015s

OK
Used shuffle seed: 927016270 (generated)
Destroying test database for alias 'default' ('test_django40_example')...

  1. 出力内容を見やすくするために-v 2オプションも加えています。 ↩︎