วันเสาร์ที่ 17 มีนาคม พ.ศ. 2561

Test-Driven Development with Python(Chapter 5)

เนื่องจากเดิมอันเดิมยาวและติดกันเกินไปทำให้ยากต่อการอ่าน
จึงแยก (Week 3-2) - (Week 5-1) Test-Driven Development with Python ออกเป็น 7 part

Chapter 5


update template home.html ต่อจาก chapter 4 โดยใส่ html form เข้าไป แต่เมื่อ functional test กลับไม่เจอตาราง
คาดว่า เช็คเร็วเกินไปตารางยังไม่ได้โหลด จึงเพิ่ม time sleep 10 วินาที แต่เมื่อ run functional test ปรากฏว่า Forbidden(403) แล้วก็ยังไม่เจอตาราง เช่นเดิม
เพราะ ยังไม่ได้ใส่ CSRF token
จึงใส่ {% csrf_token %} แล้ว functional test จะเจอ error เดิมเพราะเรายังไม่ตั้งแต่อัพเดทที่อะไรที่พิมพ์ลงไปใน input ไปใส่ตาราง

เพราะเช่นนั้นแปลว่าไม่ใช่หน้าโหลดทัน จึงแก้ timesleep กลับไป 1 วินาทีเช่นเดิม
เพิ่ม test function test_can_save_a_POST_request() เช็คข้อมูลที่ response มา
เมื่อ unit test จะพบข้อมูลที่ response มา ไม่มี text "A new list item" เพราะเรายังไม่ได้แก้ให้ส่งข้อมูลอะไรกลับมา
ทำแก้ function home_page() ใน views.py ให้ถ้าได้รับการ POST จาก html form จะ response request POST'item_text' ใน input
- นำตัวแปร new_item_text(ยังไม่ได้สร้าง) ไปใส่ในตาราง
- แล้วทำการ update test_can_save_a_POST_request ใน unit test ให้เช็ค template home.html ว่าถูกหรือไม่ในตอนท้าย
- เมื่อ unit test จะขึ้นว่าไม่ได้ render home.html ในตอนท้าย
- แก้ home_page() ให้ render หน้า home และรับค่า item_text ไปใส่ไว้ในตัวแปร new_item_text ในตัว
- แต่ไม่รัน unit test จะติด error multikey เนื่องจาก we broke the code path where there is no POST request.
แก้โดยการตัวเป็น default ถ้าไม่มีค่าอะไรใน item_text จะไม่ส่งค่า '' แต่เป็น 'None' แทน
- จึงเพิ่ม '' ต่อหลังดังรูป
- unit test อีกรอบจะผ่าน
- แต่ functional test ยังติด error เดิม?
เป็นเพราะ แสดง Buy peacock feathers แต่ใน functional_tests.py เทียบคำว่า 1: Buy pea cock feathers
ติดปัญหาเรื่อง version ตามลิงค์

https://www.blogger.com/blogger.g?blogID=9071948380338177471#editor/target=post;postID=7119590937389645335;onPublishedMenu=allposts;onClosedMenu=allposts;postNum=19;src=postname

จึงใช้เป็นของ version เก่าแทน

- ต่อมาแก้เป็นเช็คตารางรายบรรทัดต่อบรรทัด
- functional test แล้วยังติด error 1: เช่นเดิม
- โกงตามหนังสือใส่ 1: ใน template home.html ตรงตาราง
- ต่อมา update functional test ดังนี้
    #1 - ใส่คำว่า Use peacock feathers to make a fly แล้วกด enter
    #2 - เช็ค assert ในตารางคำว่า 1: Buy peacock feathers
    #3 - เช็ค assert ในตารางคำว่า 2: Use peacock feathers to make a fly
- เมื่อ functional test จะว่าติดตรง #2 เพราะพบคำว่า 1: Use peacock feathers to make a fly แทนคำว่า 1: Buy peacock feathers เพราะหน้า home ของเราอัพอันใหม่แล้วอันเก่าหาย
จากในหนังสือเค้าเห็นว่าเช็คในตารางบ่อยจึงทำเป็น function ไปเลยเพื่อง่ายต่อการเรียกใช้

เมื่อ functional test ก็จะเจอ error เดิม (พบคำว่า 1: Use peacock feathers to make a fly แทนคำว่า 1: Buy peacock feathers เพราะหน้า home ของเราอัพอันใหม่แล้วอันเก่าหาย)
- ต่อมาเพิ่ม test class ใน unit test เพื่อ test ข้อมูลใน data base
- รัน unit test ติด error import เพราะยังไม่ได้สร้าง item ใน model
สร้าง item ใน models.py แล้ว test ตามลำดับ
- error กรอบสีแดง AttributeError เพราะ class Item เป็น object จึง save ไม่ได้
- error กรอบสีน้ำเงิน database error เพราะ ยังไม่สร้าง migration file ก่อนสร้าง database
ทำการ makemigrations แล้ว unit test จะติด error เพราะยังไม่มีตัวแปร text ใน model
- ทำการใส่ตัวแปร text เป็น TextFeild
- unit test จะแสดง database error ในอกแบบเพราะ ยังไม่ makemigration แก้ไข migration file
- ทำการ makemigration แต่ django เตือนเราว่า ยังไม่กำหนดเงื่อนไขอะไร(Null)ใน TextFeild
- กลับไปแก้ Item ใน models.py กำหนด TextFeild เป็น default
- makemigration แล้วจึงทำการ unit test และผ่าน
- ต่อมา update test_can_save_a_POST_request 3 บรรทัด
    1. object count
    2. objects.first() ทำเหมือน objects.all()[0]
    3. เช็คว่า item text ถูกหรือไม่
- unit test จะติด error ว่าไม่มี object ใน Item text (Object = 0)
ทำการแก้ใน home_page() ของเราให้ save item_text ลง database และแก้ return ให้สอดคล้องกัน
- เพิ่ม test_only_saves_items_when_necessary เข้ามาใน unit test
- แก้ home_page() ให้ save ลง database เมื่อมีการ POST เท่านั้น
- เมื่อ unit test จะผ่านทั้งหมด
- เพิ่ม test_can_save_a_POST_request โดนให้ test http status ด้วย
- ลอง unit test
unit test ไม่ผ่านเพราะดังรูป status เป็น OK ไม่ใช่ Found ดังรูปข้างล่าง
แต่เราควรจะได้ status code 302 (redirect ไปที่ location เดิมใหม่อีกครั้ง)
จึงแก้ home_page() ให้เมื่อได้รับ POST บันทึกลง database แล้ว redirect กลับหน้าเดิม
เมื่อ unit test จึงผ่าน
ทำตามหนังสือ แยก test_can_save_a_POST_request ออกเป็น 2 test function เพราะ unit test ที่ดี 1 test function ควร test แค่เพียง 1 อย่าง
- ต่อมาเพิ่ม unit test - test_displays_all_list_items เพื่อเช็คว่า template สามารถ display multiple list items ได้หรือไม่
- เมื่อ unit test ไม่ผ่านตามคาดเพราะยังไม่ได้แก้ template home.html
- update template home.html ให้วนลูป เอา item ใน database item ใส่ตาราง
- update home_page ใส่ตัวแปร item และส่งให้ home
เมื่อ unit test จะ ผ่าน


แต่เมื่อ functional test debug ของ django จะแสดง "no such table: lists_item" เพราะยังไม่ได้ migrate (ข้อมูลเพิ่มเติมช่วงต้น django tutorial 2 : django tutorial 2)
- ทำการเช็ค database setting ใน settings.py ว่าเป็น sqlite3 หรือไม่
- ทำการ migrate สร้าง database sqlite3
- แต่เมื่อ functional test อีกรอบจะ error ตรงที่เราโกงตามในหนังสือ ("1: ")
- แก้โดยการให้เลขที่นับตาม loop counter ตามด้วย : แล้วต่อด้วยตามเดิม ตัวแปร item_text
แต่เมื่อทำการทดสอบหลายๆรอบข้อมูลเดิมที่อยู่ใน database ยังไม่ถูกล้างทำให้เป็นดังภาพข้างล่าง
แก้โดยการลบ database แล้ว migrate ใหม่เป็น --noinput จะไม่ได้ไม่มีข้อมูลค้างอยู่ขณะทดสอบ

ไม่มีความคิดเห็น:

แสดงความคิดเห็น