【Django入門】自動化されたtestを使ってみよう

こんにちは。ryoです。

今回は、Djangoで作ったWebアプリケーションをテストする方法について解説したいと思います。

この記事では、

  • Webアプリケーションのテストとは
  • Pythonに付属しているunittestの使い方

について解説します。さらに、

  • Seleniumを使ったブラウザ操作の自動化

についての解説を通して、今のテストの流行りであるSeleniumについても知っておきましょう。

目次

Webアプリケーションのテストとは

これから学習するWebアプリケーションのテストとは、一体どのようなものなのでしょうか。普段使っているGoogleやYahoo、AmazonなどのWebアプリケーションは、とても多くの機能を持っています。それらの機能がしっかりと期待する動作をしてくれるかどうかを調べるのがテストです。

それ以外にも

  • 性能テスト(ページが表示されるまでに時間が掛かり過ぎていないか。)
  • 負荷テスト(アクセスが見込めるサイトでどの程度の負荷まで耐えることが出来るのか。)
  • UI・UXテスト(ユーザーインターフェイス・ユーザーエクスペリエンスがサイトの方針に合っているか。)
  • セキュリティテスト(悪質な攻撃に備えて脆弱性を修正。)

など、様々なテスト項目があります。これらの項目についてそれぞれ手動でテストをしていく方法もあります。しかし大規模なサイトではそれぞれのテストに対する項目が多すぎて、時間も労力も途方が無いものになってしまいます。

そこでテストを自動化するツールも出てきました。Pythonにはunittestというテスト自動化ツールが付属しています。今回はunittestを使って、DjangoのWebアプリケーションのテストを行っていきましょう。

unittestを使ったテストの実行

ここからは実際にWebアプリケーションのテストを行っていきます。ここから動作させるコードやコマンドはすべてMacで実行したものになります。WindowsやLinuxで動かす場合は、コマンドを置き換えて見てください。

また、この記事で使ったPythonの環境は、

  • Python 3.6.0
  • Django 1.11.2

となっています。新しいバージョンでも動作するはずですが、もしも上手く行かなかったら、バージョンを合わせて試してみてください!

Djangoの下準備

まずはDjangoの環境を整えましょう。Djangoはプロジェクトを作成して、その中にWebアプリケーションを作成するのが基本の流れになっています。まずは、プロジェクトを作りたいディレクトリに移動して、このコマンドを実行しましょう。

django-admin startproject mySite

これでmySiteというディレクトリが出来上がります。次にmySiteディレクトリに移動して、このコマンドを実行しましょう。

python manage.py startapp myapp

これでmySiteプロジェクトの中に、myappというWebアプリケーションが出来上がりました。現在のディレクトリ構成はこのようになっています。

mySite
├── manage.py
├── mySite
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   └── settings.cpython-36.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── myapp
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

4 directories, 14 files

次に、mySite/settings.pyのINSTALLED_APPSを編集していきます。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
]

INSTALLED_APPSに、myappを追加しました。これでDjangoの下準備は出来ました。

次にmyapp/models.pyを編集していきます。

from django.db import models

class Person(models.Model):
    pass

modelsにPersonクラスを追加しました。次にこのコマンドを実行してマイグレーションファイルを作成します。

python manage.py makemigrations myapp

続いてマイグレートを実行します。

python manage.py migrate

マイグレーションファイルなど、modelsについての解説はこちらの記事をご覧ください。

unittestを作る

DjangoのユニットテストではPython付属のunittestを拡張したDjango独自のTestCaseクラスを使います。基本的な流れとしてはdjango.testをimportしてTestCaseを継承してテストケースを作っていきます。

myapp/tests.pyを編集して保存することで、ユニットテストとして実行することが出来ます。今回は先程作ったPersonのmodelsに登録されているレコードの数をユニットテストします。

from django.test import TestCase
from myapp.models import Person

class PersonModelTests(TestCase):
    def test_is_empty(self):
        saved_persons = Person.objects.all()
        self.assertEqual(saved_persons.count(), 0)

次にこのコマンドを実行しましょう。

python manage.py test

結果を見てみましょう。実行結果

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

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

これでユニットテストが実行できました。ここまでのことを振り返ってみましょう。myapp/tests.pyに書いたself.assertEqual関数の第二引数に指定した数と、レコードの数を確認してみてください。まだレコードには何も追加されていません。

そして第二引数とレコードに追加された数が同じなので、ユニットテストの結果に「OK」返ってきたことが分かるかと思います。このようにmyapp/tests.pyにテストケースを追加していくことで、それぞれのmodelsに対してユニットテストをしていくことが出来ます。

それぞれのテストケース(クラス)はいくつ追加しても構いませんが、TestCaseクラスを継承しましょう。また、テストケースの数が多くなってくる場合はmyapp/testsというディレクトリを作ってテストケースを分けて書くことで管理がしやすくなります。

一歩進んだテストの方法

Webアプリケーションのテストはunittestを使った方法だけではありません。テスト自動化の代表的なツールとしてSeleniumがあります。Seleniumは自動でブラウザを操作するためのツールです。

今回はSeleniumがどのようなものなのかを簡単に紹介します。

Seleniumのインストール

SeleniumはPythonのパッケージマネージャであるpipでインストールすることが出来ます。

pip install selenium

また、各ブラウザ向けに配布しているドライバを使う必要があります。今回はChromeを想定して解説します。ドライバはこちらからダウンロード、インストールしましょう。

Seleniumでテストを自動化

ここからは実際にSeleniumを使って、ブラウザを直接操作せずに www.sejuku.net にアクセスして見ようと思います。pythonを実行するディレクトリにchromedriverを置いておきましょう。

ターミナルを開いてPythonのコンソールを開きましょう。下のコマンドを1行づつ実行してみると、PythonでChromeが操作出来ることが分かるかと思います。

from selenium import webdriver

browser = webdriver.Chrome(executable_path='./chromedriver')
#Chromeが開く

browser.get('http://www.google.co.jp')
#Googleにアクセス

t=browser.find_element_by_id('lst-ib')
t.send_keys(u'www.sejuku.netn')
#検索ウィンドウに「www.sejuku.net」を入力

b=browser.find_element_by_xpath('//*[@id="rso"]/div/div/div[1]/div/div/h3/a')
b.click()
#検索順番の1番上のリンクをクリック

無事に www.sejuku.net にアクセス出来たでしょうか。SeleniumではDOM(Document Object Model)と呼ばれるページの構造についてを知る必要があります。

DOMとはHTMLなどの文書のためのインターフェイスのことです。上のサンプルコードにある「t=browser.find_element_by_id(‘lst-ib’)」では、IDでlst-ibというエレメント(要素)を探しています。

今回はPythonのコンソールを使って一つ一つ確認しました。しかしこれらのファイルを.pyファイルにまとめることによって、しっかりと自動化することが出来ます。「テストを自動化する」という意味がよくわからなかった方も、Seleniumを使った方法でなんとなくは理解していただけましたか?

まとめ

Djangoで作ったWebアプリケーションのテスト方法について解説しました。unittestはPythonに標準で付属しているので内部的な機能に特化しています。また多くの言語から使えるSeleniumはブラウザから動きを見ることが出来ます。

ちょっとした挙動のテストから実際のユーザーが実行すると思われる挙動まで、幅広くカバーできます。いまいちイメージがつかめない方はSeleniumを使ってみて、視覚的にテストについて実感していくと良いと思います。

この記事を書いた人

侍エンジニア塾は「人生を変えるプログラミング学習」をコンセンプトに、過去多くのフリーランスエンジニアを輩出したプログラミングスクールです。侍テック編集部では技術系コンテンツを中心に有用な情報を発信していきます。

目次