เปรียบเทียบราคาสินค้า
1. ดัชมิลล์ดีมอลต์ รสช็อคโกแลต
ขนาด 180 มล. แพค 4 กล่อง ราคา 40 บาท : ขนาด 90 มล. แพค 4 กล่อง ราคา 21 บาท
2. เป๊ปซี่
ขนาด 245 มล. แพค 6 กระป๋อง ราคา 55 บาท : ขนาด 245 มล. 1 กระป๋อง ราคา 11 บาท
3. มันฝรั่งทอดกรอบ เลย์
ขนาด 55 กรัม แพค 6 ถุง ราคา 99 บาท : ขนาด 55 กรัม 1 ถุง ราคา 20 บาท
4. โออิชิ กรีนที รสต้นตำรับ
ขนาด 250 มล. แพค 4 กล่อง ราคา 34 บาท : ขนาด 250 มล. 1 กล่อง ราคา 10 บาท
5. เคลียร์ แชมพู กลิ่นซากูระ
ขนาด 480 มล. 1 ขวด ราคา 179 บาท : ขนาด 340 มล. 1 ขวด ราคา 99 บาท
Building System II summer
วันพฤหัสบดีที่ 19 มิถุนายน พ.ศ. 2557
วันอาทิตย์ที่ 15 มิถุนายน พ.ศ. 2557
Chapter 5. Saving User Input
Chapter 5. Saving User Input
รันไฟล์ Functional_test.py จะแสดงผลดังนี้ คือ โปรแกรม Error และไม่สามารถหาองค์ประกอบของ method : id , selector : id_list_table
แก้ไขไฟล์ functional_tests.py.
ทำการรันไฟล์ functional_test.py จะทำให้เกิด Error ดังนี้ คือ page จะแสดง CSRF Error
แก้ไขไฟล์ lists/templates/home.html เพื่อไม่ให้เกิด CSRF Error
เมื่อทำการรันไฟล์ functional_test.py จะแสดง browser ขึ้นมา ทำให้เห็นว่าในช่องข้อความนั้นว่างเปล่า
และแสดงผลดังนี้ คือ ไม่พบรายการใหม่ในตาราง
แก้ไขไฟล์ functional_tests.py. โดยทำการลบ time.sleep ออก
ทำการรันไฟล์ test.py จะแสดงผลดังนี้คือ ไม่พบ A new list item
เราจะทำการทดสอบให้ผ่านโดยการเพิ่มและให้ code path ที่แตกต่างกันสำหรับ POST request ในรูปแบบของ TDD เราจะเริ่มต้นด้วยการ return ค่า
แก้ไขไฟล์ lists/views.py
ทำการรันไฟล์ test.py จะแสดงผลการรันผ่านสำเร็จ
แก้ไขไฟล์ lists/tests.py. ซึ่งจะทำการ render เป็นสตริง และทำการเปรียบเทียบกับ new item
ทำการรันไฟล์ test.py จะแสดงผล Error ดังนี้
แก้ไขไฟล์ lists/views.py
รันไฟล์ test.py จะแสดง error ดังนี้คือ key error ที่ item_text
แก้ไขไฟล์ lists/views.py เพื่อให้สามารถรันผ่าน
ทำการรันไฟล์ test.py จะแสดงผลดังนี้ คือสามารถผ่าน
และทำการรันไฟล์ functional_test.py จะแสดงผลดังนี้คือ ไม่พบ New to-do item ไม่ปรากฏในตาราง
เราจะใช้ functional test เป็นเทคนิคการแก้ไขข้อผิดพลาด นี่อาจเป็นเทคนิคที่สร้างสรรค์ เพราะ การปรับปรุงข้อผิดพลาดจะอยู่รอบๆข้อความความ error และจะทำให้แก้ไขข้อผิดพลาดในอนาคตได้
แก้ไขไฟล์ functional_tests.py.
รันไฟล์ test.py จะแสดงผลดังนี้ คือ New to-do item ไม่พบในตาราง ข้อความจะเป็น Buy peacock feathers
ทำการแก้ไขไฟล์ functional_tests.py.
รันไฟล์ functional_test.py จะแสดงผลดังนี้
ทำการแก้ไขไฟล์ lists/templates/home.html. โดยใส่ข้อมูลเข้าไปในตาราง
ทำการรันไฟล์ functional_test.py จะแสดงผลดังนี้ คือจะรันผ่าน
ถ้าเราต้องการตรวจสอบรายการลำดับที่ 2 ในตาราง
ทำการแก้ไขไฟล์ functional_tests.py
รันไฟล์ functional_test.py จะแสดงผลดังนี้
คำสั่ง git commit เพื่อคอมมิทการแก้ไขไฟล์
กลับมาที่ functional test เราจะเพิ่ม method เข้าไปเพื่อช่วยในการจดจำ
แก้ไขไฟล์ functional_tests.py.
แก้ไขไฟล์ functional_test.py
รันไฟล์ functional_test.py จะแสดงผลดังนี้
คำสั่ง git diff เพื่อดูการแก้ไขไฟล์
คำสั่ง git commit คอมมิทการแก้ไขไฟล์
ทำการรันไฟล์ test.py จะแสดงผลดังนี้ คือ ไม่สามารถ import ชื่อ item ได้
แก้ไขไฟล์ lists/models.py.
ทำการรันไฟล์ test.py จะแสดงผลดังนี้ คือ Item ไม่มี attribute 'save'
แก้ไขไฟล์ lists/models.py.
ทำการรันไฟล์ test lists จะแสดงผลดังนี้ คือ Item ไม่มี attribute 'text'
แก้ไขไฟล์ lists/models.py.
ทำการรันไฟล์ test lists จะแสดงผลดังนี้ คือ รันผ่าน
ทำการเช็คสถานะไฟล์ แอด lists และ คอมมิทโดยใช้ชื่อ Model for list Items and associated migration
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ 0 != 1
แก้ไขไฟล์ lists/views.py.
ทำการรันไฟล์ test จะแสดงผลดังนี้คือ สามารถรันผ่าน
แก้ไขไฟล์ lists/views.py.
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ รันผ่าน
แก้ไขไฟล์ lists/tests.py. ในคลาส HomePageTest เพิ่มฟังก์ชั่น test_home_page_only_saves_item_when_necessary(self):
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ 1 != 0
แก้ไขไฟล์ lists/views.py.
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ สามารถรันผ่าน
Redirect After a POST
แก้ไขไฟล์ lists/tests.py
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ 200 != 302
แก้ไขไฟล์ lists/views.py
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ รันผ่าน
ทำการรันไฟล์ test จะแสดงผลดังนี้คือ รันผ่าน
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ 'itemey 1' ไม่พบใน '<html>\n [...]
แก้ไขไฟล์ lists/templates/home.html.
แก้ไขไฟล์ lists/views.py.
เมื่อทำการรันไฟล์ functional_test แล้วจะมีหน้าบราวเซอร์ เด้งขึ้นมาดังรูป
และในโปรแกรมจะ Error ดังนี้
แก้ไขไฟล์ lists/templates/home.html.
ทำการลบดาต้าเบส และสร้างดาต้าเบสอันใหม่ขึ้นมาโดยใช้คำสั่ง
และทำการรันไฟล์ functional_tests จะมีหน้า browser เด้งขึ้นมาดังรูป
และโปรแกรมจะแสดงผลว่ารันผ่าน
ทำการคอมมิทโดยใช้ชื่อว่า "Redirect after Post, and sshow all item in template"
Wiring Up Our Form to Send a POST Request
แก้ไขไฟล์ lists/templates/home.html.
<h1>Your To-Do list</h1> <form method="POST"> <input name="item_text" id="id_new_item" placeholder="Enter a to-do item" /> </form> <table id="id_list_table">
รันไฟล์ Functional_test.py จะแสดงผลดังนี้ คือ โปรแกรม 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/tmpVZoONB/extensions/fxdriver@googlecode.com/components/driver_component.js:8905) at fxdriver.Timer.prototype.setTimeout/<.notify (file:///tmp/tmpVZoONB/extensions/fxdriver@googlecode.com/components/driver_component.js:396) ---------------------------------------------------------------------- Ran 1 test in 17.221s FAILED (errors=1)
แก้ไขไฟล์ functional_tests.py.
# 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
)
import
time
time
.
sleep
(
10
)
table
=
self
.
browser
.
find_element_by_id
(
'id_list_table'
)
ทำการรันไฟล์ functional_test.py จะทำให้เกิด Error ดังนี้ คือ page จะแสดง CSRF Error
แก้ไขไฟล์ lists/templates/home.html เพื่อไม่ให้เกิด CSRF Error
<form
method=
"POST"
>
<input
name=
"item_text"
id=
"id_new_item"
placeholder=
"Enter a to-do item"
/>
{% csrf_token %}</form>
เมื่อทำการรันไฟล์ functional_test.py จะแสดง browser ขึ้นมา ทำให้เห็นว่าในช่องข้อความนั้นว่างเปล่า
และแสดงผลดังนี้ คือ ไม่พบรายการใหม่ในตาราง
$ 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 46, 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 26.127s FAILED (failures=1)
แก้ไขไฟล์ functional_tests.py. โดยทำการลบ time.sleep ออก
# "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'
)
Processing a POST Request on the Server
จะเพิ่ม unit test อันใหม่สำหรับ home_page
แก้ไขไฟล์ lists/tests.py โดยจะแอด method เพิ่มเข้าไป ซึ่งก่อนหน้านี้ทำการปรับให้เพิ่มคำขอ POST และตรวจสอบการ return ของ HTML ว่าจะมีข้อความใหม่
def
test_home_page_returns_correct_html
(
self
):
[
...
]
def
test_home_page_can_save_a_POST_request
(
self
):
request
=
HttpRequest
()
request
.
method
=
'POST'
request
.
POST
[
'item_text'
]
=
'A new list item'
response
=
home_page
(
request
)
self
.
assertIn
(
'A new list item'
,
response
.
content
.
decode
())
ทำการรันไฟล์ test.py จะแสดงผลดังนี้คือ ไม่พบ A new list item
$ python manage.py test Creating test database for alias 'default'... F.. ====================================================================== FAIL: test_home_page_can_save_a_POST_request (lists.tests.HomePageTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 37, in test_home_page_can_save_a_POST_request self.assertIn('A new list item', response.content.decode()) AssertionError: 'A new list item' not found in u'<html>\n <head>\n <title>To-Do lists</title>\n </head>\n <body>\n <h1>Your To-Do list</h1>\n <form method="POST">\n \t<input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />\n \t\n\t</form>\n\n\t<table id="id_list_table">\n </table>\n </body>\n</html>\n' ---------------------------------------------------------------------- Ran 3 tests in 0.013s FAILED (failures=1) Destroying test database for alias 'default'...
เราจะทำการทดสอบให้ผ่านโดยการเพิ่มและให้ code path ที่แตกต่างกันสำหรับ POST request ในรูปแบบของ TDD เราจะเริ่มต้นด้วยการ return ค่า
แก้ไขไฟล์ lists/views.py
from
django.http
import
HttpResponse
from
django.shortcuts
import
render
def
home_page
(
request
):
if
request
.
method
==
'POST'
:
return
HttpResponse
(
request
.
POST
[
'item_text'
])
return
render
(
request
,
'home.html'
)
ทำการรันไฟล์ test.py จะแสดงผลการรันผ่านสำเร็จ
$ python manage.py test Creating test database for alias 'default'... ... ---------------------------------------------------------------------- Ran 3 tests in 0.005s OK Destroying test database for alias 'default'...
Passing Python Variables to Be Rendered in the Template
แก้ไขไฟล์ lists/templates/home.html เพื่อแสดง objects เป็นสตริง
<body>
<h1>
Your To-Do list</h1>
<form
method=
"POST"
>
<input
name=
"item_text"
id=
"id_new_item"
placeholder=
"Enter a to-do item"
/>
{% csrf_token %}</form>
<table
id=
"id_list_table"
>
<tr><td>
{{ new_item_text }}</td></tr>
</table>
</body>
แก้ไขไฟล์ lists/tests.py. ซึ่งจะทำการ render เป็นสตริง และทำการเปรียบเทียบกับ new item
self
.
assertIn
(
'A new list item'
,
response
.
content
.
decode
())
expected_html
=
render_to_string
(
'home.html'
,
{
'new_item_text'
:
'A new list item'
}
)
self
.
assertEqual
(
response
.
content
.
decode
(),
expected_html
)
ทำการรันไฟล์ test.py จะแสดงผล Error ดังนี้
$ python manage.py test Creating test database for alias 'default'... F.. ====================================================================== FAIL: test_home_page_can_save_a_POST_request (lists.tests.HomePageTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 42, in test_home_page_can_save_a_POST_request self.assertEqual(response.content.decode(), expected_html) AssertionError: u'A new list item' != u'<html>\n <head>\n <title>To-Do lists</title>\n </head>\n <body>\n <h1>Your To-Do list</h1>\n <form method="POST">\n <input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />\n \n </form>\n\n <table id="id_list_table">\n <tr><td>A new list item</td></tr>\n </table>\n </body>\n</html>\n' ---------------------------------------------------------------------- Ran 3 tests in 0.006s FAILED (failures=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/views.py
def
home_page
(
request
):
return
render
(
request
,
'home.html'
,
{
'new_item_text'
:
request
.
POST
[
'item_text'
],
})
รันไฟล์ test.py จะแสดง error ดังนี้คือ key error ที่ item_text
$ 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 25, in test_home_page_returns_correct_html response = home_page(request) File "/home/jutamas/Desktop/summer/superlists/lists/views.py", line 6, in home_page 'new_item_text': request.POST['item_text'], KeyError: 'item_text' ---------------------------------------------------------------------- Ran 3 tests in 0.005s FAILED (errors=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/views.py เพื่อให้สามารถรันผ่าน
def
home_page
(
request
):
return
render
(
request
,
'home.html'
,
{
'new_item_text'
:
request
.
POST
.
get
(
'item_text'
,
''
),
})
ทำการรันไฟล์ test.py จะแสดงผลดังนี้ คือสามารถผ่าน
$ python manage.py test Creating test database for alias 'default'... ... ---------------------------------------------------------------------- Ran 3 tests in 0.007s OK Destroying test database for alias 'default'...
และทำการรันไฟล์ functional_test.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 5.958s FAILED (failures=1)
เราจะใช้ functional test เป็นเทคนิคการแก้ไขข้อผิดพลาด นี่อาจเป็นเทคนิคที่สร้างสรรค์ เพราะ การปรับปรุงข้อผิดพลาดจะอยู่รอบๆข้อความความ error และจะทำให้แก้ไขข้อผิดพลาดในอนาคตได้
แก้ไขไฟล์ 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 -- its text was:
\n
%s
"
%
(
table
.
text
,
)
)
รันไฟล์ test.py จะแสดงผลดังนี้ คือ New to-do item ไม่พบในตาราง ข้อความจะเป็น Buy peacock feathers
$ 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 45, in test_can_start_a_list_and_retrieve_it_later table.text, AssertionError: New to-do item did not appear in table -- its text was: Buy peacock feathers ---------------------------------------------------------------------- Ran 1 test in 6.133s FAILED (failures=1)
ทำการแก้ไขไฟล์ functional_tests.py.
self
.
assertIn
(
'1: Buy peacock feathers'
,
[
row
.
text
for
row
in
rows
])
รันไฟล์ functional_test.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 42, in test_can_start_a_list_and_retrieve_it_later self.assertIn('1: Buy peacock feathers', [row.text for row in rows]) AssertionError: '1: Buy peacock feathers' not found in [u'Buy peacock feathers'] ---------------------------------------------------------------------- Ran 1 test in 6.205s FAILED (failures=1)
ทำการแก้ไขไฟล์ lists/templates/home.html. โดยใส่ข้อมูลเข้าไปในตาราง
<tr><td>
1: {{ new_item_text }}</td></tr>
ทำการรันไฟล์ functional_test.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 47, in test_can_start_a_list_and_retrieve_it_later self.fail('Finish the test!') AssertionError: Finish the test! ---------------------------------------------------------------------- Ran 1 test in 6.026s FAILED (failures=1)
ถ้าเราต้องการตรวจสอบรายการลำดับที่ 2 ในตาราง
ทำการแก้ไขไฟล์ functional_tests.py
# 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)
inputbox
=
self
.
browser
.
find_element_by_id
(
'id_new_item'
)
inputbox
.
send_keys
(
'Use peacock feathers to make a fly'
)
inputbox
.
send_keys
(
Keys
.
ENTER
)
# The page updates again, and now shows both items on her list
table
=
self
.
browser
.
find_element_by_id
(
'id_list_table'
)
rows
=
table
.
find_elements_by_tag_name
(
'tr'
)
self
.
assertIn
(
'1: Buy peacock feathers'
,
[
row
.
text
for
row
in
rows
])
self
.
assertIn
(
'2: Use peacock feathers to make a fly'
,
[
row
.
text
for
row
in
rows
]
)
# Edith wonders whether the site will remember her list. Then she sees
# that the site has generated a unique URL for her -- there is some
# explanatory text to that effect.
self
.
fail
(
'Finish the test!'
)
# She visits that URL - her to-do list is still there.
รันไฟล์ functional_test.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 55, in test_can_start_a_list_and_retrieve_it_later self.assertIn('1: Buy peacock feathers', [row.text for row in rows]) AssertionError: '1: Buy peacock feathers' not found in [u'1: Use peacock feathers to make a fly'] ---------------------------------------------------------------------- Ran 1 test in 6.297s FAILED (failures=1)
Three Strikes and Refactor
คำสั่ง git diff ดูการแก้ไขไฟล์
$ git diff diff --git a/functional_tests.py b/functional_tests.py index 5487abb..94ed2a3 100644 --- a/functional_tests.py +++ b/functional_tests.py @@ -36,19 +36,35 @@ class NewVisitorTest(unittest.TestCase): #1 # "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') + 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), - "New to-do item did not appear in table" - ) + self.assertIn('1: Buy peacock feathers', [row.text 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!') :
คำสั่ง git commit เพื่อคอมมิทการแก้ไขไฟล์
$ git commit -a [master 0cc6302] Test home page can save a POST request 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 8 files changed, 110 insertions(+), 22 deletions(-)
กลับมาที่ functional test เราจะเพิ่ม method เข้าไปเพื่อช่วยในการจดจำ
แก้ไขไฟล์ functional_tests.py.
def
tearDown
(
self
):
self
.
browser
.
quit
()
def
check_for_row_in_list_table
(
self
,
row_text
):
table
=
self
.
browser
.
find_element_by_id
(
'id_list_table'
)
rows
=
table
.
find_elements_by_tag_name
(
'tr'
)
self
.
assertIn
(
row_text
,
[
row
.
text
for
row
in
rows
])
def
test_can_start_a_list_and_retrieve_it_later
(
self
):
[
...
]
แก้ไขไฟล์ functional_test.py
# 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)
self.check_for_row_in_list_table('1: Buy peacock feathers')
# 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)
inputbox = self.browser.find_element_by_id('id_new_item')
inputbox.send_keys('Use peacock feathers to make a fly')
inputbox.send_keys(Keys.ENTER)
# The page updates again, and now shows both items on her list
self.check_for_row_in_list_table('1: Buy peacock feathers')
self.check_for_row_in_list_table('2: Use peacock feathers to make a fly')
# Edith wonders whether the site will remember her list. Then she sees
[...]
รันไฟล์ functional_test.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 53, in test_can_start_a_list_and_retrieve_it_later self.check_for_row_in_list_table('1: Buy peacock feathers') File "functional_tests.py", line 17, in check_for_row_in_list_table self.assertIn(row_text, [row.text for row in rows]) AssertionError: '1: Buy peacock feathers' not found in [u'1: Use peacock feathers to make a fly'] ---------------------------------------------------------------------- Ran 1 test in 6.404s FAILED (failures=1)
คำสั่ง git diff เพื่อดูการแก้ไขไฟล์
$ git diff diff --git a/functional_tests.py b/functional_tests.py index 94ed2a3..d2643be 100644 --- a/functional_tests.py +++ b/functional_tests.py @@ -10,6 +10,11 @@ class NewVisitorTest(unittest.TestCase): #1 def tearDown(self): #3 self.browser.quit() + + def check_for_row_in_list_table(self, row_text): + table = self.browser.find_element_by_id('id_list_table') + rows = table.find_elements_by_tag_name('tr') + self.assertIn(row_text, [row.text for row in rows]) 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 @@ -33,30 +38,20 @@ class NewVisitorTest(unittest.TestCase): #1 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) - :
คำสั่ง git commit คอมมิทการแก้ไขไฟล์
$ git commit -a [master 05d06bb] Three Strikes and Refactor 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 2 files changed, 19 insertions(+), 19 deletions(-)
The Django ORM and Our First Model
แก้ไขไฟล์ lists/tests.py.
from
lists.models
import
Item
[
...
]
class
ItemModelTest
(
TestCase
):
def
test_saving_and_retrieving_items
(
self
):
first_item
=
Item
()
first_item
.
text
=
'The first (ever) list item'
first_item
.
save
()
second_item
=
Item
()
second_item
.
text
=
'Item the second'
second_item
.
save
()
saved_items
=
Item
.
objects
.
all
()
self
.
assertEqual
(
saved_items
.
count
(),
2
)
first_saved_item
=
saved_items
[
0
]
second_saved_item
=
saved_items
[
1
]
self
.
assertEqual
(
first_saved_item
.
text
,
'The first (ever) list item'
)
self
.
assertEqual
(
second_saved_item
.
text
,
'Item the second'
)
ทำการรันไฟล์ test.py จะแสดงผลดังนี้ คือ ไม่สามารถ import ชื่อ item ได้
$ python manage.py test Creating test database for alias 'default'... E ====================================================================== ERROR: lists.tests (unittest.loader.ModuleImportFailure) ---------------------------------------------------------------------- ImportError: Failed to import test module: lists.tests Traceback (most recent call last): File "/usr/lib/python2.7/unittest/loader.py", line 252, in _find_tests module = self._get_module_from_name(name) File "/usr/lib/python2.7/unittest/loader.py", line 230, in _get_module_from_name __import__(name) File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 6, in <module> from lists.models import Item ImportError: cannot import name Item ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/models.py.
from django.db import models class Item(object): pass
ทำการรันไฟล์ test.py จะแสดงผลดังนี้ คือ Item ไม่มี attribute 'save'
$ python manage.py test Creating test database for alias 'default'... ...E ====================================================================== ERROR: test_saving_and_retrieving_items (lists.tests.ItemModelTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 50, in test_saving_and_retrieving_items first_item.save() AttributeError: 'Item' object has no attribute 'save' ---------------------------------------------------------------------- Ran 4 tests in 0.007s FAILED (errors=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/models.py.
from
django.db
import
models
class
Item
(
models
.
Model
):
pass
ทำการรันไฟล์ test lists จะแสดงผลดังนี้ คือ Item ไม่มี attribute 'text'
$ python manage.py test lists Creating test database for alias 'default'... ...E ====================================================================== ERROR: test_saving_and_retrieving_items (lists.tests.ItemModelTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 61, in test_saving_and_retrieving_items self.assertEqual(first_saved_item.text, 'The first (ever) list item') AttributeError: 'Item' object has no attribute 'text' ---------------------------------------------------------------------- Ran 4 tests in 0.008s FAILED (errors=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/models.py.
class
Item
(
models
.
Model
):
text
=
models
.
TextField
()
ทำการรันไฟล์ test lists จะแสดงผลดังนี้ คือ รันผ่าน
$ python manage.py test lists Creating test database for alias 'default'... .... ---------------------------------------------------------------------- Ran 4 tests in 0.010s OK Destroying test database for alias 'default'...
ทำการเช็คสถานะไฟล์ แอด lists และ คอมมิทโดยใช้ชื่อ Model for list Items and associated migration
$ git status $ git diff $ git add lists $ git commit -m"
Model for list Items and associated migration"
Saving the POST to the Database
แก้ไขไฟล์ lists/tests.py. โดยเพิ่มฟังก์ชั่น test_home_page_can_save_a_POST_request(selft) เพื่อทดสอบว่าสามารถคำร้องขอได้หรือไม่
def
test_home_page_can_save_a_POST_request
(
self
):
request
=
HttpRequest
()
request
.
method
=
'POST'
request
.
POST
[
'item_text'
]
=
'A new list item'
response
=
home_page
(
request
)
self
.
assertEqual
(
Item
.
objects
.
count
(),
1
)
#
![]()
new_item
=
Item
.
objects
.
first
()
#
![]()
self
.
assertEqual
(
new_item
.
text
,
'A new list item'
)
#
![]()
self
.
assertIn
(
'A new list item'
,
response
.
content
.
decode
())
expected_html
=
render_to_string
(
'home.html'
,
{
'new_item_text'
:
'A new list item'
}
)
self
.
assertEqual
(
response
.
content
.
decode
(),
expected_html
)
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ 0 != 1
$ python manage.py test Creating test database for alias 'default'... F... ====================================================================== FAIL: test_home_page_can_save_a_POST_request (lists.tests.HomePageTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 38, in test_home_page_can_save_a_POST_request self.assertEqual(Item.objects.count(), 1) #1 AssertionError: 0 != 1 ---------------------------------------------------------------------- Ran 4 tests in 0.009s FAILED (failures=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/views.py.
from
django.shortcuts
import
render
from
lists.models
import
Item
def
home_page
(
request
):
item
=
Item
()
item
.
text
=
request
.
POST
.
get
(
'item_text'
,
''
)
item
.
save
()
return
render
(
request
,
'home.html'
,
{
'new_item_text'
:
request
.
POST
.
get
(
'item_text'
,
''
),
})
ทำการรันไฟล์ test จะแสดงผลดังนี้คือ สามารถรันผ่าน
$ python manage.py test
Creating test database for alias 'default'...
....
----------------------------------------------------------------------
Ran 4 tests in 0.010s
OK
Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/views.py.
return
render
(
request
,
'home.html'
,
{
'new_item_text'
:
item
.
text
})
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ รันผ่าน
$ python manage.py test Creating test database for alias 'default'... .... ---------------------------------------------------------------------- Ran 4 tests in 0.010s OK Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/tests.py. ในคลาส HomePageTest เพิ่มฟังก์ชั่น test_home_page_only_saves_item_when_necessary(self):
class
HomePageTest
(
TestCase
):
[
...
]
def
test_home_page_only_saves_items_when_necessary
(
self
):
request
=
HttpRequest
()
home_page
(
request
)
self
.
assertEqual
(
Item
.
objects
.
count
(),
0
)
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ 1 != 0
$ python manage.py test Creating test database for alias 'default'... .F... ====================================================================== FAIL: test_home_page_only_saves_items_when_necessary (lists.tests.HomePageTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 52, in test_home_page_only_saves_items_when_necessary self.assertEqual(Item.objects.count(), 0) AssertionError: 1 != 0 ---------------------------------------------------------------------- Ran 5 tests in 0.011s FAILED (failures=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/views.py.
def
home_page
(
request
):
if
request
.
method
==
'POST'
:
new_item_text
=
request
.
POST
[
'item_text'
]
#
![]()
Item
.
objects
.
create
(
text
=
new_item_text
)
#
![]()
else
:
new_item_text
=
''
#
![]()
return
render
(
request
,
'home.html'
,
{
'new_item_text'
:
new_item_text
,
#
![]()
})
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ สามารถรันผ่าน
$ python manage.py test Creating test database for alias 'default'... ..... ---------------------------------------------------------------------- Ran 5 tests in 0.012s OK Destroying test database for alias 'default'...
Redirect After a POST
def
test_home_page_can_save_a_POST_request
(
self
):
request
=
HttpRequest
()
request
.
method
=
'POST'
request
.
POST
[
'item_text'
]
=
'A new list item'
response
=
home_page
(
request
)
self
.
assertEqual
(
Item
.
objects
.
count
(),
1
)
new_item
=
Item
.
objects
.
first
()
self
.
assertEqual
(
new_item
.
text
,
'A new list item'
)
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
[
'location'
],
'/'
)
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ 200 != 302
$ python manage.py test Creating test database for alias 'default'... F.... ====================================================================== FAIL: test_home_page_can_save_a_POST_request (lists.tests.HomePageTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 42, in test_home_page_can_save_a_POST_request self.assertEqual(response.status_code, 302) AssertionError: 200 != 302 ---------------------------------------------------------------------- Ran 5 tests in 0.010s FAILED (failures=1) Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/views.py
from
django.shortcuts
import
redirect
,
render
from
lists.models
import
Item
def
home_page
(
request
):
if
request
.
method
==
'POST'
:
Item
.
objects
.
create
(
text
=
request
.
POST
[
'item_text'
])
return
redirect
(
'/'
)
return
render
(
request
,
'home.html'
)
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ รันผ่าน
$ python manage.py test Creating test database for alias 'default'... ..... ---------------------------------------------------------------------- Ran 5 tests in 0.012s OK Destroying test database for alias 'default'...
Better Unit Testing Practice: Each Test Should Test One Thing
แก้ไขไฟล์ lists/tests.py. def
test_home_page_can_save_a_POST_request
(
self
):
request
=
HttpRequest
()
request
.
method
=
'POST'
request
.
POST
[
'item_text'
]
=
'A new list item'
response
=
home_page
(
request
)
self
.
assertEqual
(
Item
.
objects
.
count
(),
1
)
new_item
=
Item
.
objects
.
first
()
self
.
assertEqual
(
new_item
.
text
,
'A new list item'
)
def
test_home_page_redirects_after_POST
(
self
):
request
=
HttpRequest
()
request
.
method
=
'POST'
request
.
POST
[
'item_text'
]
=
'A new list item'
response
=
home_page
(
request
)
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
[
'location'
],
'/'
)
ทำการรันไฟล์ test จะแสดงผลดังนี้คือ รันผ่าน
$ python manage.py test
Creating test database for alias 'default'...
......
----------------------------------------------------------------------
Ran 6 tests in 0.011s
OK
Destroying test database for alias 'default'...
Rendering Items in the Template
การแสดงรายการใน template
แก้ไขไฟล์ lists/tests.py
แก้ไขไฟล์ lists/tests.py
class
HomePageTest
(
TestCase
):
[
...
]
def
test_home_page_displays_all_list_items
(
self
):
Item
.
objects
.
create
(
text
=
'itemey 1'
)
Item
.
objects
.
create
(
text
=
'itemey 2'
)
request
=
HttpRequest
()
response
=
home_page
(
request
)
self
.
assertIn
(
'itemey 1'
,
response
.
content
.
decode
())
self
.
assertIn
(
'itemey 2'
,
response
.
content
.
decode
())
ทำการรันไฟล์ test จะแสดงผลดังนี้ คือ 'itemey 1' ไม่พบใน '<html>\n [...]
$ python manage.py test
Creating test database for alias 'default'...
.F.....
======================================================================
FAIL: test_home_page_displays_all_list_items (lists.tests.HomePageTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jutamas/Desktop/summer/superlists/lists/tests.py", line 65, in test_home_page_displays_all_list_items
self.assertIn('itemey 1', response.content.decode())
AssertionError: 'itemey 1' not found in u'<html>\n <head>\n <title>To-Do lists</title>\n </head>\n <body>\n <h1>Your To-Do list</h1>\n <form method="POST">\n <input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />\n \n </form>\n\n <table id="id_list_table">\n <tr><td>1: </td></tr>\n </table>\n </body>\n</html>\n'
----------------------------------------------------------------------
Ran 7 tests in 0.012s
FAILED (failures=1)
Destroying test database for alias 'default'...
แก้ไขไฟล์ lists/templates/home.html.
<table
id=
"id_list_table"
>
{% for item in items %}<tr><td>
1: {{ item.text }}</td></tr>
{% endfor %}</table>
แก้ไขไฟล์ lists/views.py.
def
home_page
(
request
):
if
request
.
method
==
'POST'
:
Item
.
objects
.
create
(
text
=
request
.
POST
[
'item_text'
])
return
redirect
(
'/'
)
items
=
Item
.
objects
.
all
()
return
render
(
request
,
'home.html'
,
{
'items'
:
items
})
เมื่อทำการรันไฟล์ functional_test แล้วจะมีหน้าบราวเซอร์ เด้งขึ้นมาดังรูป
และในโปรแกรมจะ Error ดังนี้
$ 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 25, in test_can_start_a_list_and_retrieve_it_later
self.assertIn('To-Do', self.browser.title)
AssertionError: 'To-Do' not found in u'OperationalError at /'
----------------------------------------------------------------------
Ran 1 test in 5.945s
FAILED (failures=1)
Creating Our Production Database with migrate
การสร้างฐานข้อมูล
การสร้างฐานข้อมูล
แก้ไขไฟล์ superlists/settings.py
[
...
]
# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
DATABASES
=
{
'default'
:
{
'ENGINE'
:
'django.db.backends.sqlite3'
,
'NAME'
:
os
.
path
.
join
(
BASE_DIR
,
'db.sqlite3'
),
}
}
แก้ไขไฟล์ lists/templates/home.html.
{% for item in items %}<tr><td>
{{ forloop.counter }}: {{ item.text }}</td></tr>
{% endfor %}
ทำการลบดาต้าเบส และสร้างดาต้าเบสอันใหม่ขึ้นมาโดยใช้คำสั่ง
$ python manage.py syncdb
และทำการรันไฟล์ functional_tests จะมีหน้า browser เด้งขึ้นมาดังรูป
และโปรแกรมจะแสดงผลว่ารันผ่าน
$ 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 59, in test_can_start_a_list_and_retrieve_it_later
self.fail('Finish the test!')
AssertionError: Finish the test!
----------------------------------------------------------------------
Ran 1 test in 7.346s
FAILED (failures=1)
ทำการคอมมิทโดยใช้ชื่อว่า "Redirect after Post, and sshow all item in template"
$ git commit -m"Redirect after Post, and show all items in template"
วันพฤหัสบดีที่ 5 มิถุนายน พ.ศ. 2557
Chapter 4. What Are We Doing with All These Tests?
Chapter 4. What Are We Doing with All These Tests?
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(-)
สมัครสมาชิก:
บทความ (Atom)