「すべてのDjango開発者の生活の中で、機能テストを欠いて、彼が過去を決定的に破る瞬間があります!
これについてお話します。
この記事は、小さなプロジェクトの完成したページをテストするための最適なツールを見つけた結果です。 ツールの最適性を評価するための基準として、従来、アプリケーションのセットごとに同等の条件を求めながら、最小限のテスト実行時間を取りました。
この記事では、Selenium WebDriverを使用したDjango 1.7のPython 3.4でのDjangoアプリケーションの機能テストの3つのオプションについて説明します(Seleniumの機能の詳細な説明が記載されたHabréに関する記事があります )。 また、Selenium WebDriver APIの完全な情報を以下に示します。 ロシア語の より多くのドキュメント と使用例 。
テストでは、テクノロジーとアプリケーションを使用しました:VirtualBox 4.3.6、Debian 7.7、Virtualenv 12.0.7、Python 3.4、Django 1.7、Selenium Webdriver 2.47.3、Iceweasel、Xvfb、PyVirtualDisplay 0.1.5、PhantomJS 1.9.8、Nginx 1.2.1 、uWSGI。
Debian 7.7 + Virtualenv 12.0.7 + Django 1.7 +の次のバンドルを検討してください。
- 1つのオプション。 X.org + Selenium WebDriver + Firefox (Debian用Iceweacel )-グラフィカルシェル
- 2オプション。 ターミナル + Selenium WebDriver + Xvfb 、 PyVirtualDisplay-ターミナルから起動
- 3オプション。 ターミナル + Selenium + PhantomJS- ターミナルから起動
機能テストツールを使用すると、最終的なサイトの健全性とブラウザー内のページの動作を評価できます。また、動的にロードされたデータをテストするとき(JavaScript、Ajaxを使用するとき)、基本テストクライアントDjangoが便利でない場合にも役立ちます。 さまざまなテクノロジーが単一の製品に組み込まれ、論理的な疑問が生じた場合、特定のケースでそれらがどのように一緒に動作するか。
これらのツールを使用して、実際のユーザーの行動をシミュレートできます。
さあ始めましょう!
仮想環境では、Seleniumを配置します。
pip install selenium
今回の場合、ユーザー認証プロセスをテストするため、認証アプリケーション(ポイントB)にtests.pyファイルを作成します。
オプション1.ユーザーの行動の視覚シミュレーション
A.ここではX.orgのグラフィカルインターフェイスがインストールされていると想定しています。
Debian Iceweasel(以前のDebian Firefox-Debian GNU / LinuxのMozilla Firefoxブラウザの修正)を配置しました:
sudo apt-get install iceweasel
! 注:
グラフィカル環境を起動せずにターミナルからテストを実行しようとすると、例外が発生します:raise WebDriverException( "ブラウザは終了しているように見えます„ selenium.common.exceptions.WebDriverException:メッセージ:ブラウザは終了したように見えます。 FirefoxBinaryコンストラクターでlog_fileを指定しました。詳細を確認してください。
B. tests.pyファイルを作成します。
オプション1
# Django Selenium from django.test import LiveServerTestCase # ( FireFox) from selenium import webdriver import time class SeleniumTests(LiveServerTestCase): def test_auth(self): # webdriver Firefox br = webdriver.Firefox() # , 'localhost:8081' URL br.get('%s%s' % (self.live_server_url, '/')) # br.find_element_by_xpath('//a[@href="/register/"]').click() # 3 time.sleep(3) # # username 'new' br.find_element_by_id('username').send_keys('new') # email 'new@new.ru' br.find_element_by_id('email').send_keys('new@new.ru') # 2- br.find_element_by_id('password1').send_keys('12345678') br.find_element_by_id('password2').send_keys('12345678') # br.find_element_by_id('btn_register').click() # pis = Myuser.objects.get(username='new') # - pis.is_active = True # pis.save() # br.find_element_by_xpath('//a[@href="/"]').click() # 3 time.sleep(3) # br.find_element_by_id('username').send_keys('new') br.find_element_by_id('password').send_keys('12345678') br.find_element_by_name('').click() # assert br.find_element_by_xpath('//a[@data-content=" "]').text == 'new' # , br.quit()
! 注:
エラーを回避するためにプログラムテキストでtime.sleep(3)を一時停止します。「selenium.common.exceptions.NoSuchElementException:Message:Unable to find element:{"method": "id"、 "selector": "username"}」 、「アイテムが見つかりません」、ページコンテキスト全体が読み込まれなかったことが原因です。 エラーが発生した場合、待機時間を増やすことができます。
C.認証/ tests.pyからテストを実行します。
python manage.py test authentication/
その他の起動オプション。
すべてのプロジェクトテスト:
python manage.py test
tests.pyの特定のSeleniumTestsクラス:
python manage.py test authentication.tests.SeleniumTests
SeleniumTestsクラスのtest_authメソッド:
python manage.py test authentication.tests.SeleniumTests.test_auth
テスト時間(Debian 7.7、VirtualBox、12 Mb VideoRAM、512 Mb RAM、1コア):(29.89 + 25.65 + 26.73)/ 3 = 27.42秒
オプション2. xvfb + pyvirtualdisplayでグラフィカルシェルを起動せずにターミナルでテストを実行
A.コンソールから起動するには、Xサーバー:Xvfbおよび仮想ディスプレイ:Virtualenvの仮想環境にPyvirtualdisplayをインストールする必要があります。
sudo apt-get install xvfb pip install pyvirtualdisplay
! 注:
ローカルユーザーの代わりにPyVirtualDisplayを配置します。そうしないと、インポート行でユーザーの下からテストする場合:pyvirtualdisplay import Displayから、エラーが発生します。
PyVirtualDisplay 0.1.5は公式にPythonバージョンをサポートしています:2.6、2.7、3.2、3.3、3.4でテスト-動作
B. tests.pyファイルを作成します。 前述のオプション1に、仮想ディスプレイで動作する行を追加します。
オプション2
# from pyvirtualdisplay import Display # Django Selenium from django.test import LiveServerTestCase # ( FireFox) from selenium import webdriver import time class SeleniumTests(LiveServerTestCase): def test_auth(self): # display = Display(visible=0, size=(800, 600)) display.start() # webdriver Firefox br = webdriver.Firefox() # , 'localhost:8081' URL br.get('%s%s' % (self.live_server_url, '/')) # br.find_element_by_xpath('//a[@href="/register/"]').click() # 3 time.sleep(3) # # username 'new' br.find_element_by_id('username').send_keys('new') # email 'new@new.ru' br.find_element_by_id('email').send_keys('new@new.ru') # 2- br.find_element_by_id('password1').send_keys('12345678') br.find_element_by_id('password2').send_keys('12345678') # br.find_element_by_id('btn_register').click() # pis = Myuser.objects.get(username='new') # - pis.is_active = True # pis.save() # br.find_element_by_xpath('//a[@href="/"]').click() # 3 time.sleep(3) # br.find_element_by_id('username').send_keys('new') br.find_element_by_id('password').send_keys('12345678') br.find_element_by_name('').click() # assert br.find_element_by_xpath('//a[@data-content=" "]').text == 'new' # display.stop() # , br.quit()
テスト時間(Putty SSH、Screen、Virtualenv、Debian 7.7、VirtualBox、12 Mb VideoRAM、512 Mb RAM、1コア):(28.5 + 25.82 + 24.98)/ 3 = 26.43秒
オプション3. PhantomJSでグラフィカルシェルを起動せずにターミナルでテストを実行する
A.コンソールから起動するには、PhantomJSをインストールする必要があります。
cd /usr/local/share sudo wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.8-linux-x86_64.tar.bz2 sudo tar xjf phantomjs-1.9.8-linux-x86_64.tar.bz2 sudo ln -s /usr/local/share/phantomjs-1.9.8-linux-x86_64/bin/phantomjs /usr/local/share/phantomjs sudo ln -s /usr/local/share/phantomjs-1.9.8-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs sudo ln -s /usr/local/share/phantomjs-1.9.8-linux-x86_64/bin/phantomjs /usr/bin/phantomjs
そして実行:
phantomjs -v
! 注:
受信したパッケージがこのシステムに適していない場合、「バイナリファイルを実行できません」というエラーが表示されます(多くの場合、32ビットシステム(x86)に64ビットアプリケーション(x64)をインストールしようとしたため)。
B. tests.pyファイルを作成します。 前述のオプション1にPhantomJSを操作するための行を追加します。
オプション3
# PhantomJS from selenium.webdriver import PhantomJS # Django Selenium from django.test import LiveServerTestCase import time # # ( FireFox) #from selenium import webdriver class SeleniumTests(LiveServerTestCase): def test_auth(self): # # webdriver Firefox #br = webdriver.Firefox() # PhantomJS br = PhantomJS() # br.set_window_size(800, 600) # , 'localhost:8081' URL br.get('%s%s' % (self.live_server_url, '/')) # br.find_element_by_xpath('//a[@href="/register/"]').click() # 3 time.sleep(3) # # username 'new' br.find_element_by_id('username').send_keys('new') # email 'new@new.ru' br.find_element_by_id('email').send_keys('new@new.ru') # 2- br.find_element_by_id('password1').send_keys('12345678') br.find_element_by_id('password2').send_keys('12345678') # br.find_element_by_id('btn_register').click() # pis = Myuser.objects.get(username='new') # - pis.is_active = True # pis.save() # br.find_element_by_xpath('//a[@href="/"]').click() # 3 time.sleep(3) # : # br.save_screenshot('screenshot_firstpage.png') # br.find_element_by_id('username').send_keys('new') br.find_element_by_id('password').send_keys('12345678') br.find_element_by_name('').click() # assert br.find_element_by_xpath('//a[@data-content=" "]').text == 'new' # , br.quit()
スクリーンショットを作成するとき、PhantomJSは背景に問題がありますが、保存すると透明になります(黒の背景)。 br.save_screenshot( 'screenshot_firstpage.png')の前にこの誤解を修正するには、次を使用できます。
そのようなコード:
br.execute_script( "" "(function(){
var style = document.createElement( 'style')、text = document.createTextNode( 'body {background:#fff}');
style.setAttribute( 'type'、 'text / css');
style.appendChild(テキスト);
document.head.insertBefore(style、document.head.firstChild);
})(); "" ")
var style = document.createElement( 'style')、text = document.createTextNode( 'body {background:#fff}');
style.setAttribute( 'type'、 'text / css');
style.appendChild(テキスト);
document.head.insertBefore(style、document.head.firstChild);
})(); "" ")
ページのスクリーンショットを作成せずにテスト実行時間(Putty SSH、Screen、Virtualenv、Debian 7.7、VirtualBox、12 Mb VideoRAM、512 Mb RAM、1コア):(14.64 + 14.89 + 13.05)/ 3 = 14.19秒
追加:
ページのスクリーンショットを使用したテスト実行時間(Putty SSH、Screen、Virtualenv、Debian 7.7、VirtualBox、12 Mb VideoRAM、512 Mb RAM、1コア):(17.63 + 17.74 + 17.94)/ 3 = 17.77秒
要約:
ページのスクリーンショットなしでオプション3を使用する-[ 14.19秒。 ]は、オプション2-[26.43秒]およびオプション1-[27.42秒]に比べて、煙切れの時間をほぼ2倍短縮し、グラフィカルシェルのない戦闘サーバーでの使用に適しています。 ただし、オプション1は、コードをバトルサーバーに展開する前の、開発中の予備テストの視覚的により有益で便利なものです。
PS。 ここでは、テストコードで合計6秒が使用されたことをさらに考慮する必要があります。 期待。
追加:
親愛なる同僚、機能テスト中にどのバンドルを使用しますか? 彼らの長所と短所は何ですか?
ご清聴ありがとうございました!