Using Selenium to Test User Interactions
ใช้ Selenium ในการทดสอบปััญหา เมื่อทำการทดสอบ functional_tests.py ผ่านแล้วเมื่อรันไฟล์จะแสดงผลดังนี้
$ python functional_tests.py F ====================================================================== FAIL: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "functional_tests.py", line 20, in test_can_start_a_list_and_retrieve_it_later self.fail('Finish the test!') #6 AssertionError: Finish the test! ---------------------------------------------------------------------- Ran 1 test in 5.422s FAILED (failures=1)
ทำการแก้ไขไฟล์ functional_tests.py
from selenium import webdriver import unittest class NewVisitorTest(unittest.TestCase): #1 def setUp(self): #2 self.browser = webdriver.Firefox() self.browser.implicitly_wait(3) def tearDown(self): #3 self.browser.quit() def test_can_start_a_list_and_retrieve_it_later(self): #4 # Edith has heard about a cool new online to-do app. She goes # to check out its homepage self.browser.get('http://localhost:8000') # She notices the page title and header mention to-do lists self.assertIn('To-Do', self.browser.title) header_text = self.browser.find_element_by_tag_name('h1').text self.assertIn('To-Do', header_text) # She is invited to enter a to-do item straight away inputbox = self.browser.find_element_by_id('id_new_item') self.assertEqual( inputbox.get_attribute('placeholder'), 'Enter a to-do item' ) # She types "Buy peacock feathers" into a text box (Edith's hobby # is tying fly-fishing lures) inputbox.send_keys('Buy peacock feathers') # When she hits enter, the page updates, and now the page lists # "1: Buy peacock feathers" as an item in a to-do list table inputbox.send_keys(Keys.ENTER) table = self.browser.find_element_by_id('id_list_table') rows = table.find_elements_by_tag_name('tr') self.assertTrue( any(row.text == '1: Buy peacock feathers' for row in rows) ) # There is still a text box inviting her to add another item. She # enters "Use peacock feathers to make a fly" (Edith is very # methodical) self.fail('Finish the test!') # The page updates again, and now shows both items on her list if __name__ == '__main__': #7 unittest.main() #8
ทำการรันไฟล์ functional_tests.py จะมี browser เด้งขึ้นมา
และโปรแกรม Error ดังนี้ คือ ไม่สามารถหาองค์ประกอบของ method : tagname , selector : h1
$ python functional_tests.py E ====================================================================== ERROR: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "functional_tests.py", line 20, in test_can_start_a_list_and_retrieve_it_later header_text = self.browser.find_element_by_tag_name('h1').text File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 319, in find_element_by_tag_name return self.find_element(by=By.TAG_NAME, value=name) File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 655, in find_element {'using': by, 'value': value})['value'] File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 166, in execute self.error_handler.check_response(response) File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/errorhandler.py", line 164, in check_response raise exception_class(message, screen, stacktrace) NoSuchElementException: Message: u'Unable to locate element: {"method":"tag name","selector":"h1"}' ; Stacktrace: at FirefoxDriver.prototype.findElementInternal_ (file:///tmp/tmpKvc9ez/extensions/fxdriver@googlecode.com/components/driver_component.js:8905) at fxdriver.Timer.prototype.setTimeout/<.notify (file:///tmp/tmpKvc9ez/extensions/fxdriver@googlecode.com/components/driver_component.js:396) ---------------------------------------------------------------------- Ran 1 test in 8.403s FAILED (errors=1)
ใช้คำสั่ง git diff เพื่อดูการแก้ไขไฟล์
$ git diff diff --git a/functional_tests.py b/functional_tests.py index b6322b7..23fe36f 100644 --- a/functional_tests.py +++ b/functional_tests.py @@ -16,11 +16,37 @@ class NewVisitorTest(unittest.TestCase): #1 self.browser.get('http://localhost:8000') # She notices the page title and header mention to-do lists - self.assertIn('To-Do', self.browser.title) #5 - self.fail('Finish the test!') #6 + self.assertIn('To-Do', self.browser.title) + header_text = self.browser.find_element_by_tag_name('h1').text + self.assertIn('To-Do', header_text) # She is invited to enter a to-do item straight away - #[...rest of comments as before] + inputbox = self.browser.find_element_by_id('id_new_item') + self.assertEqual( + inputbox.get_attribute('placeholder'), + 'Enter a to-do item' + ) + + # She types "Buy peacock feathers" into a text box (Edith's hobby :
คอมมิทโดยใช้ชื่อ "Functional test now checks we can input a to-do item"
$ git commit -am "Functional test now checks we can input a to-do item" [master 935ab70] Functional test now checks we can input a to-do item Committer: jutamas <jutamas@jutamas.(none)> Your name and email address were configured automatically based on your username and hostname. Please check that they are accurate. You can suppress this message by setting them explicitly: git config --global user.name "Your Name" git config --global user.email you@example.com After doing this, you may fix the identity used for this commit with: git commit --amend --reset-author 1 file changed, 29 insertions(+), 3 deletions(-)
The “Don’t Test Constants” Rule, and Templates to the Rescue
"อย่าทดสอบค่าคงที่" ทำการทดสอบหน่วยใน list/tests.py
ทำการรันไฟล์ test จะแสดงผลการรันผ่าน ดังนี้
$ python manage.py test Creating test database for alias 'default'... .. ---------------------------------------------------------------------- Ran 2 tests in 0.003s OK Destroying test database for alias 'default'...
จากนั้นสร้างโฟล์เดอร์ใหม่ชื่อ templates ใน list และสร้างไฟล์ home.html จะเป็น lists/templates/home.html และทำการแก้ไขไฟล์ดังนี้
<html> <title>To-Do lists</title> </html>
และแก้ไขไฟล์ lists/views.py ดังนี้ เพื่อจะเรียกใช้ไฟล์ home.html
from django.shortcuts import render def home_page(request): return render(request, 'home.html')
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ โปรแกรมจะหา home.html ไม่เจอ
$ python manage.py test Creating test database for alias 'default'... E. ====================================================================== ERROR: test_home_page_returns_correct_html (lists.tests.HomePageTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 17, in test_home_page_returns_correct_html response = home_page(request) #2 File "/home/jutamas/Desktop/summer/superlists/lists/views.py", line 4, in home_page return render(request, 'home.html') File "/usr/local/lib/python2.7/dist-packages/django/shortcuts/__init__.py", line 53, in render return HttpResponse(loader.render_to_string(*args, **kwargs), File "/usr/local/lib/python2.7/dist-packages/django/template/loader.py", line 162, in render_to_string t = get_template(template_name) File "/usr/local/lib/python2.7/dist-packages/django/template/loader.py", line 138, in get_template template, origin = find_template(template_name) File "/usr/local/lib/python2.7/dist-packages/django/template/loader.py", line 131, in find_template raise TemplateDoesNotExist(name) TemplateDoesNotExist: home.html ---------------------------------------------------------------------- Ran 2 tests in 0.135s FAILED (errors=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ superlists/settings.py โดยการเพิ่ม list เข้าไปเพราะ templates อยู่ใน lists
INSTALLED_APPS
=
(
'django.contrib.admin'
,
'django.contrib.auth'
,
'django.contrib.contenttypes'
,
'django.contrib.sessions'
,
'django.contrib.messages'
,
'django.contrib.staticfiles'
,
'lists'
,
)
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ Error เนื่องจากต้องมี </html> ปิดท้าย
$ python manage.py test Creating test database for alias 'default'... F. ====================================================================== FAIL: test_home_page_returns_correct_html (lists.tests.HomePageTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 20, in test_home_page_returns_correct_html self.assertTrue(response.content.endswith(b'</html>')) #5 AssertionError: False is not true ---------------------------------------------------------------------- Ran 2 tests in 0.005s FAILED (failures=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/tests.py
self
.
assertTrue
(
response
.
content
.
strip
()
.
endswith
(
b
'</html>'
))
ทำการรันไฟล์ test จะแสดงผลการรันผ่านดังนี้
$ python manage.py test Creating test database for alias 'default'... .. ---------------------------------------------------------------------- Ran 2 tests in 0.005s OK Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/tests.py เพื่อเป็นการเรียกใช้ไฟล์ templates แต่จะบันทึกผลเป็นสตริง
from
django.template.loader
import
render_to_string
[
...
]
def
test_home_page_returns_correct_html
(
self
):
request
=
HttpRequest
()
response
=
home_page
(
request
)
expected_html
=
render_to_string
(
'home.html'
)
self
.
assertEqual
(
response
.
content
.
decode
(),
expected_html
)
On Refactoring
ใช้คำสั่ง git status เพื่อดูสถานะไฟล์
$ git status # On branch master # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: lists/tests.py # modified: lists/tests.py~ # modified: lists/views.py # modified: superlists/settings.py # modified: superlists/settings.pyc # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # Untitled Document~ # functional_tests.py~ # lists/templates/ # lists/views.py~ # superlists/settings.py~ # superlists/urls.py~ no changes added to commit (use "git add" and/or "git commit -a")
ใช้คำสั่ง git add . เพื่อ add ไฟล์เข้ามา
$ git add .
ใช้คำสั่ง git diff --staged ดูการแก้ไขไฟล์
$ git diff --staged diff --git a/Untitled Document~ b/Untitled Document~ new file mode 100644 index 0000000..e69de29 diff --git a/functional_tests.py~ b/functional_tests.py~ new file mode 100644 index 0000000..b6322b7 --- /dev/null +++ b/functional_tests.py~ @@ -0,0 +1,26 @@ +from selenium import webdriver +import unittest + +class NewVisitorTest(unittest.TestCase): #1 + + def setUp(self): #2 + self.browser = webdriver.Firefox() + self.browser.implicitly_wait(3) + + def tearDown(self): #3 + self.browser.quit() + + def test_can_start_a_list_and_retrieve_it_later(self): #4 + # Edith has heard about a cool new online to-do app. She goes :
ใช้คำสั่ง git commit -m "Refactor home page view to use a template"
git commit -m"Refactor home page view to use a template" [master b417b4a] Refactor home page view to use a template Committer: jutamas <jutamas@jutamas.(none)> Your name and email address were configured automatically based on your username and hostname. Please check that they are accurate. You can suppress this message by setting them explicitly: git config --global user.name "Your Name" git config --global user.email you@example.com After doing this, you may fix the identity used for this commit with: git commit --amend --reset-author 10 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 Untitled Document~ create mode 100644 functional_tests.py~ create mode 100644 lists/templates/home.html create mode 100644 lists/templates/home.html~ create mode 100644 lists/views.py~ create mode 100644 superlists/settings.py~ create mode 100644 superlists/urls.py~
A Little More of Our Front Page
แก้ไขไฟล์ lists/templates/home.html ดังนี้
<html> <head> <title>To-Do lists</title> </head> <body> <h1>Your To-Do list</h1> </body> </html>
ทำการรันไฟล์ functional_tests.py จะแสดง browser ขึ้นมาดังนี้
และโปรแกรมจะแสดงผล Error ดังนี้ คือ ไม่สามารถหา meyhod : id , selector : id_new_item ได้
$ python functional_tests.py E ====================================================================== ERROR: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "functional_tests.py", line 24, in test_can_start_a_list_and_retrieve_it_later inputbox = self.browser.find_element_by_id('id_new_item') File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 199, in find_element_by_id return self.find_element(by=By.ID, value=id_) File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 655, in find_element {'using': by, 'value': value})['value'] File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 166, in execute self.error_handler.check_response(response) File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/errorhandler.py", line 164, in check_response raise exception_class(message, screen, stacktrace) NoSuchElementException: Message: u'Unable to locate element: {"method":"id","selector":"id_new_item"}' ; Stacktrace: at FirefoxDriver.prototype.findElementInternal_ (file:///tmp/tmpqHTZux/extensions/fxdriver@googlecode.com/components/driver_component.js:8905) at fxdriver.Timer.prototype.setTimeout/<.notify (file:///tmp/tmpqHTZux/extensions/fxdriver@googlecode.com/components/driver_component.js:396) ---------------------------------------------------------------------- Ran 1 test in 8.079s FAILED (errors=1)
ทำการแก้ไขไฟล์ lists/templates/home.html คือการเพิ่มช่องใส่ข้อมูล
[...] <h1>
Your To-Do list</h1>
<input
id=
"id_new_item"
/>
</body>
[...]
ทำการรันไฟล์ functional_tests.py จะแสดงผลดังนี้คือ
$ python functional_tests.py F ====================================================================== FAIL: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "functional_tests.py", line 27, in test_can_start_a_list_and_retrieve_it_later 'Enter a to-do item' AssertionError: u'' != 'Enter a to-do item' ---------------------------------------------------------------------- Ran 1 test in 4.872s FAILED (failures=1)
lists/templates/home.html.
[...]<input
id=
"id_new_item"
placeholder=
"Enter a to-do item"
/> [...]
ทำการรันไฟล์ functional_tests.py จะแสดง browser ดังนี้
และโปรแกรม Error ดังนี้ คือ ไม่สามารถหาองค์ประกอบของ method : id , selector : id_list_table
$ python functional_tests.py E ====================================================================== ERROR: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "functional_tests.py", line 39, in test_can_start_a_list_and_retrieve_it_later table = self.browser.find_element_by_id('id_list_table') File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 199, in find_element_by_id return self.find_element(by=By.ID, value=id_) File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 655, in find_element {'using': by, 'value': value})['value'] File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py", line 166, in execute self.error_handler.check_response(response) File "/usr/local/lib/python2.7/dist-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/errorhandler.py", line 164, in check_response raise exception_class(message, screen, stacktrace) NoSuchElementException: Message: u'Unable to locate element: {"method":"id","selector":"id_list_table"}' ; Stacktrace: at FirefoxDriver.prototype.findElementInternal_ (file:///tmp/tmpQbTAZ2/extensions/fxdriver@googlecode.com/components/driver_component.js:8905) at fxdriver.Timer.prototype.setTimeout/<.notify (file:///tmp/tmpQbTAZ2/extensions/fxdriver@googlecode.com/components/driver_component.js:396) ---------------------------------------------------------------------- Ran 1 test in 15.109s FAILED (errors=1)
แก้ไขไฟล์ lists/templates/home.html ดังนี้
[...]<input
id=
"id_new_item"
placeholder=
"Enter a to-do item"
/>
<table
id=
"id_list_table"
>
</table>
</body> [...]
ทำการรันไฟล์ functional_tests.py จะแสดงผลดังนี้ คือ row.text == 1 ไม่เป็นความจริง
$ python functional_tests.py F ====================================================================== FAIL: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "functional_tests.py", line 42, in test_can_start_a_list_and_retrieve_it_later any(row.text == '1: Buy peacock feathers' for row in rows) AssertionError: False is not true ---------------------------------------------------------------------- Ran 1 test in 15.094s FAILED (failures=1)
ทำการแก้ไขไฟล์ functional_tests.py.
self
.
assertTrue
(
any
(
row
.
text
==
'1: Buy peacock feathers'
for
row
in
rows
),
"New to-do item did not appear in table"
)
ทำการรันไฟล์ functional_tests.py จะแสดงผลดังนี้คือ New to-do item ไม่ปรากฏในตาราง
$ python functional_tests.py F ====================================================================== FAIL: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "functional_tests.py", line 44, in test_can_start_a_list_and_retrieve_it_later "New to-do item did not appear in table" AssertionError: New to-do item did not appear in table ---------------------------------------------------------------------- Ran 1 test in 15.179s FAILED (failures=1)
$ git diff
diff --git a/functional_tests.py b/functional_tests.py
index 23fe36f..5487abb 100644
--- a/functional_tests.py
+++ b/functional_tests.py
@@ -1,15 +1,16 @@
from selenium import webdriver
+from selenium.webdriver.common.keys import Keys
import unittest
class NewVisitorTest(unittest.TestCase): #1
def setUp(self): #2
self.browser = webdriver.Firefox()
- self.browser.implicitly_wait(3)
+ self.browser.implicitly_wait(10)
def tearDown(self): #3
self.browser.quit()
-
+
def test_can_start_a_list_and_retrieve_it_later(self): #4
# Edith has heard about a cool new online to-do app. She goes
# to check out its homepage
:
ใช้คำสั่งคอมมิท ใช้ชื่อ "Front page HTML now generated from a template"
$ git commit -am"Front page HTML now generated from a template" [master b47c562] Front page HTML now generated from a template Committer: jutamas <jutamas@jutamas.(none)> Your name and email address were configured automatically based on your username and hostname. Please check that they are accurate. You can suppress this message by setting them explicitly: git config --global user.name "Your Name" git config --global user.email you@example.com After doing this, you may fix the identity used for this commit with: git commit --amend --reset-author 4 files changed, 61 insertions(+), 11 deletions(-)
ไม่มีความคิดเห็น:
แสดงความคิดเห็น