バグをなくし開発システムの信頼性(品質)を保証するために,テストコードを書いて自動的にテストをできるようにしたい.またテストカバレッジ(テスト網羅度)を計測して,テスト漏れがないかを確認したい.まずは,カバレッジを計測するための coverage パッケージをインストールしよう.
(base) C:\Users\lecture\Documents\django\django_comment>pip list | find "coverage" ⏎
(base) C:\Users\lecture\Documents\django\django_comment>pip install coverage ⏎
Collecting coverage
Downloading coverage-5.2.1-cp37-cp37m-win_amd64.whl (208 kB)
|████████████████████████████████| 208 kB 1.1 MB/s
Installing collected packages: coverage
Successfully installed coverage-5.2.1
(base) C:\Users\lecture\Documents\django\django_comment>pip list | find "coverage" ⏎
coverage 5.2.1
(base) C:\Users\lecture\Documents\django\django_comment>
Mac でもほぼ同じ方法で coverage パッケージをインストールできる.
rinsaka@MacBookPro django_comment % pip list | grep coverage ⏎
rinsaka@MacBookPro django_comment % pip install coverage ⏎
Collecting coverage
Downloading https://files.pythonhosted.org/packages/cc/c9/f5c77b3385d2951ed6abd25f90e36eee056a5e2cd4fe7f93625c0024fcb8/coverage-5.0.4-cp37-cp37m-macosx_10_13_x86_64.whl (203kB)
|████████████████████████████████| 204kB 574kB/s
Installing collected packages: coverage
Successfully installed coverage-5.0.4
rinsaka@MacBookPro django_comment % pip list | grep coverage ⏎
coverage 5.0.4
rinsaka@MacBookPro django_comment %
テストのコードは次のような comments/test.py である.
comments/test.py
from django.test import TestCase
# Create your tests here.
このテストコードに簡単なテストを記述してみよう.まずは,トップページ (/) にアクセスして,200番(成功)のステータスコードを受け取ることができるかどうかを確認するテストを記述してみよう.
comments/test.py
from django.test import TestCase
from django.urls import reverse
# Create your tests here.
class CommentIndexTests(TestCase):
def test_comment_index(self):
"""
Comment index のテスト
"""
response = self.client.get(reverse('comments:index'))
self.assertEqual(response.status_code, 200)
テストコードの記述ができたら,テストを実行してみる.1つのテストが実行されて,成功していることがわかる.
(base) C:\Users\lecture\Documents\django\django_comment>python manage.py test comments ⏎ Creating test database for alias 'default'... System check identified no issues (0 silenced). . ---------------------------------------------------------------------- Ran 1 test in 0.027s OK Destroying test database for alias 'default'... (base) C:\Users\lecture\Documents\django\django_comment>
次に,コメントの詳細表示ページのテストコードを記述する.Laravel の自動テストと異なり,Django ではテスト実行時に別のデータベースが作成される.つまり,テストコードの中でデータを投入する必要がある.次のコードではコメントを1件追加して,その詳細ページに投稿したタイトルが表示されているかどうかをテストしている.
comments/test.py
from django.test import TestCase
from django.urls import reverse
from django.utils import timezone
from .models import Comment
# Create your tests here.
class CommentIndexTests(TestCase):
def test_comment_index(self):
"""
Comment index のテスト
"""
response = self.client.get(reverse('comments:index'))
self.assertEqual(response.status_code, 200)
def test_comment_show(self):
"""
Comment の詳細ページ
"""
comment = Comment.objects.create(
title="test title",
body="test body",
created_at=timezone.now(),
updated_at=timezone.now())
url = reverse('comments:show', args=(comment.id,))
response = self.client.get(url)
self.assertContains(response, "test title")
再度テストを実行すると2件のテストをパスしたことがわかる.
(base) C:\Users\lecture\Documents\django\django_comment>python manage.py test comments ⏎ Creating test database for alias 'default'... System check identified no issues (0 silenced). .. ---------------------------------------------------------------------- Ran 2 tests in 0.278s OK Destroying test database for alias 'default'... (base) C:\Users\lecture\Documents\django\django_comment>
このようにコードを変更するたびに自動テストを実施すれば,思わぬバグを作り込んでしまっても発見できる可能性が高くなる.しかし,ソースコードのどの部分のテストはされて,どの部分のテストができていないかを知ることも重要である.このために,テストカバレッジ(網羅度)を計測しよう.
テストカバレッジを計測するには,テストの実行コマンドにいくつかのオプションを加え,coverage run --source='.' manage.py test comments
を実行すると良い.これにより,.coverage ファイルが生成される.その後,カバレッジレポートを表示するために coverage report
コマンドを実行する.その結果,comments/views.py は52行中,20行がまだテストされておらず,カバレッジが62%であることが確認できた.
(base) C:\Users\lecture\Documents\django\django_comment>coverage run --source='.' manage.py test comments ⏎
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..
----------------------------------------------------------------------
Ran 2 tests in 0.301s
OK
Destroying test database for alias 'default'...
(base) C:\Users\lecture\Documents\django\django_comment>coverage report ⏎
Name Stmts Miss Cover
---------------------------------------------------------
comments\__init__.py 0 0 100%
comments\admin.py 1 0 100%
comments\apps.py 3 0 100%
comments\forms.py 18 9 50%
comments\migrations\0001_initial.py 5 0 100%
comments\migrations\__init__.py 0 0 100%
comments\models.py 6 0 100%
comments\tests.py 13 0 100%
comments\urls.py 4 0 100%
comments\views.py 52 20 62%
django_comment\__init__.py 0 0 100%
django_comment\asgi.py 4 4 0%
django_comment\settings.py 18 0 100%
django_comment\urls.py 2 0 100%
django_comment\wsgi.py 4 4 0%
manage.py 12 2 83%
---------------------------------------------------------
TOTAL 142 39 73%
(base) C:\Users\lecture\Documents\django\django_comment>
カバレッジの詳細を確認したい場合は,coverage html
コマンドで HTML ファイルを生成すれば良い.このコマンドによって htmlcov というフォルダが作成され,カバレッジレポートの HTML が生成される.この中の index.html をブラウザで閲覧する.
(base) C:\Users\lecture\Documents\django\django_comment>coverage html ⏎ (base) C:\Users\lecture\Documents\django\django_comment>
comments/views.py のページを開くと,テストされていないコードがハイライトされて確認できる.このページを確認しながら,すべての行がテストされるようにテストケースを追加し,カバレッジ100%を目指すと良い.