2012-12-18 [長年日記]

そういえばテスト書いてないじゃん。

Web観点のテストなので、twill か selenium が使えるはず。 JQueryが絡むので、twillだとちょっと荷が重いかな。seleniumを使うことにする。

selenium の構造はこんな感じ。テストコードから Selenium Server を経由してWebブラウザを操作したり Assert する。

http://seleniumhq.org/download/ から Selenium Server と Internet Explorer Driver Server を入手して、jarファイルをダブルクリックして実行しておく。

Python クライアントドライバは、easy_install で導入できる:

> "C:\Program Files\BitNami\python\Scripts\easy_install.exe" selenium
Searching for selenium
Reading http://pypi.python.org/simple/selenium/
Reading http://code.google.com/p/selenium/
Reading http://www.openqa.org/
Reading http://seleniumhq.org/
Best match: selenium 2.28.0
Downloading http://pypi.python.org/packages/source/s/selenium/selenium-2.28.0.tar.gz#md5=fd253a2ea94fe14cc5f3e8328cda7a53
Processing selenium-2.28.0.tar.gz
Running selenium-2.28.0\setup.py -q bdist_egg --dist-dir c:\users\matobaa\appdata\local\temp\easy_install-lzspr6\selenium-2.28.0\egg-dist-tmp-gmwns0
C:\PROGRA~1\BitNami\python\lib\distutils\dist.py:267: UserWarning: Unknown distribution option: 'src_root'
  warnings.warn(msg)
warning: no files found matching 'docs\api\py\index.rst'
Adding selenium 2.28.0 to easy-install.pth file
    
Installed c:\progra~1\bitnami\python\lib\site-packages\selenium-2.28.0-py2.7.egg
    
Processing dependencies for selenium
Finished processing dependencies for selenium
>

テストコードを書く

PyDev Package Explorer で QueryStatusHelperPlugin を選択した状態から、Ctrl-N で、Python Module を作る。uiassist.testsパッケージに、Templateは Unittestを選択して、checkboxtest という名前でモジュールを作る。

で、これにソースをがりがり書いていく。こんな感じ:

from selenium import selenium
import time
import unittest
    
class Test(unittest.TestCase):
    def setUp(self):
        self.verificationErrors = []
        self.selenium = selenium("localhost", 4444, "*chrome", "http://localhost:8080/1.0/")
        self.selenium.start()
    
    def test_double_click_field_from_uri(self):
        sel = self.selenium
        sel.open("query?status=!closed")
        sel.double_click("label_0_status")
        self.failUnless(not sel.is_checked("_0_status_accepted"))
        self.failUnless(not sel.is_checked("_0_status_assigned"))
        self.failUnless(sel.is_checked("_0_status_closed"))
        self.failUnless(not sel.is_checked("_0_status_new"))
        self.failUnless(not sel.is_checked("_0_status_reopened"))
    
    def test_double_click_field_added_by_adder(self):
        sel = self.selenium
        sel.open("query?status=!closed")
        time.sleep(2)*1
        sel.select("add_filter_0", "Vote")
        sel.double_click("label_0_vote")
        self.failUnless(sel.is_checked("0_vote_a"))
        self.failUnless(sel.is_checked("0_vote_b"))
        self.failUnless(sel.is_checked("0_vote_c"))
        self.failUnless(sel.is_checked("0_vote_d"))
        # regression
        sel.double_click("label_0_status")
        self.failUnless(not sel.is_checked("_0_status_accepted"))
        self.failUnless(not sel.is_checked("_0_status_assigned"))
        self.failUnless(sel.is_checked("_0_status_closed"))
        self.failUnless(not sel.is_checked("_0_status_new"))
        self.failUnless(not sel.is_checked("_0_status_reopened"))
    
    def test_double_click_field_added_by_adder_repeatly(self):
        sel = self.selenium
        sel.open("query?status=!closed")
        time.sleep(2)
        sel.select("add_filter_0", "Vote")
        sel.double_click("label_0_vote")
        sel.uncheck("0_vote_c")
        sel.double_click("label_0_vote")
        self.failUnless(not sel.is_checked("0_vote_a"))
        self.failUnless(not sel.is_checked("0_vote_b"))
        self.failUnless(sel.is_checked("0_vote_c"))
        self.failUnless(not sel.is_checked("0_vote_d"))
    
    def test_double_click_on_checkbox(self):
        sel = self.selenium
        sel.open("query?status=!closed")
        sel.double_click("_0_status_accepted")
        self.failUnless(sel.is_checked("_0_status_accepted"))
        self.failUnless(not sel.is_checked("_0_status_assigned"))
        self.failUnless(not sel.is_checked("_0_status_closed"))
        self.failUnless(not sel.is_checked("_0_status_new"))
        self.failUnless(not sel.is_checked("_0_status_reopened"))
    
    def test_double_click_on_checkbox_label(self):
        sel = self.selenium
        sel.open("query?status=!closed")
        sel.double_click("//label[@for='_0_status_accepted']")
        self.failUnless(sel.is_checked("_0_status_accepted"))
        self.failUnless(not sel.is_checked("_0_status_assigned"))
        self.failUnless(not sel.is_checked("_0_status_closed"))
        self.failUnless(not sel.is_checked("_0_status_new"))
        self.failUnless(not sel.is_checked("_0_status_reopened"))
    
    def test_double_click_on_checkbox_label_added_by_adder(self):
        sel = self.selenium
        sel.open("query?status=!closed")
        time.sleep(2)
        sel.select("add_filter_0", "Vote")
        sel.double_click("//label[@for='0_vote_a']")
        sel.double_click("//label[@for='0_vote_c']")
        self.failUnless(not sel.is_checked("0_vote_a"))
        self.failUnless(not sel.is_checked("0_vote_b"))
        self.failUnless(sel.is_checked("0_vote_c"))
        self.failUnless(not sel.is_checked("0_vote_d"))
    
    def tearDown(self):
        self.selenium.stop()
        self.assertEqual([], self.verificationErrors)

trac.iniはこんな感じ:

[ticket-custom]
vote = radio
vote.options = a|b|c|d
checkboxtest.py を右クリックして、Run as - python unit test で実行してやって、グリーンを確認する。OK。

*1 このコード動作させるのにすごく苦労した。time.sleep(2)が重要。

次回は

気になってたことはクリアしたので、いよいよtrac-Hacks.orgで公開しよう


«前の日記(2012-12-17) 最新 次の日記(2012-12-19)»