หน้าเว็บ

วันพุธที่ 28 มกราคม พ.ศ. 2558

CHAPTER 4 What Are We Doing with All These Tests?

Using Selenium to Test User Interaction 





Note : TDD จะไม่สนใจสิ่งที่ต้องทำงานต่อไป คือจะสนใจเฉพาะสิ่งที่ทดสอบและจะบอกเราในสิ่งที่ทดสอบได้

เข้าไปที่ superlists  เปิด server ขึ้นมา
$python3 manage.py runserver

เข้าไปแก้ไข functional_tests.py ตามโค้ด

from selenium import webdriver

from selenium.webdriver.common.keys import Keys

import unittest



class NewVisitorTest(unittest.TestCase):


    def setUp(self):

        self.browser = webdriver.Firefox()

        self.browser.implicitly_wait(3)



    def tearDown(self):

        self.browser.quit()



    def test_can_start_a_list_and_retrieve_it_later(self):

        # 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

        [...]


Note : ระวังข้อแตกต่างระหว่าง Selenium find_element_by... และ find_elements_by... functions คือตัวหนึ่งจะส่งค่า element กลับและจะเกิดข้อยกเว้นในกรณีที่หาไม่พบ ในขณะที่อีกตัวจะส่งค่ากลับเป็น list ที่เป็นพื้นที่ว่างๆ

$ python3 functional_tests.py



[...]
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: {"method":"tag name","selector":"h1"} [...]

error : บอกว่า ไม่เจอ <h1> บน page นี้ เราสามารถเพิ่ม html ใน home page (function ใน view.py)

$ git diff
$ git commit -am "Functional test now checks we can input a to-do item"

ใน Templates ไม่ควรทดสอบค่าคงที่
ไปดูที่ unit test ของเรา (lists/tests.py) ตอนนี้เราทดสอบ ข้อความ HTML แต่ไม่ใช่วิธีที่มีประสิทธิภาพโดยเฉพาะอย่างยิ่งในการทดสอบ HTML กฏข้อหนึ่งในการทดสอบ unit test คือไม่ทดสอบค่าคงที่ (constant) และในการทเสอบ HTML ก็ไม่ควรทดสอบค่าคงที่

ใน code html :
  wibble = 3

แต่ใน code Test :
  from myprogram import wibble
  assert wibble == 3

ถ้าเราสร้าง Test เป็นการทดสอบค่าคงที่ใน HTML เมื่อแก้ไขโค้ด HTML ต้องมาแก้ไขที่ Test ด้วย


Refactoring to use a Template.
Refactoring : โค้ดที่ผ่านการ test แล้วต้องการปรับปรุงให้ดีขึ้น
Template : ต้องการแยกโค้ด html จากฟังก์ชันที่ใช้ในการ request

1. สร้าง directory ใน lists ชื่อ templates และสร้าง gedit ไฟล์ home.html.


แก้ไขใน home.html
<html><br />
    <title>To-Do lists</title>
</html> 

แก้ไขใน view.py
from django.shortcuts import render

def home_page(request):
return render(request, 'home.html')

จากนั้น run : python3 manage.py test




2. แก้ไข superlists/settings.py.

# Application definition

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'lists',
)

จากนั้น run : python3 manage.py test


แก้ไข ใน tests.py ตรงบรรทัดที่ 3 : self.assertTrue(response.content.endswith(b'</html>'))
เป็น : self.assertTrue(response.content.strip().endswith(b'</html>'))
จากนั้น run : python3 manage.py test

3. แก้ไข tests


# Application definition

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'lists',
)

จากนั้น run : python3 manage.py test
4. แก้ไข HTML

<html>
    <head>
        <title>To-Do lists</title>
    </head>
    <body>
        <h1>Your To-Do list</h1>
        <input id="id_new_item" placeholder="Enter a to-do item" />
        <table id="id_list_table">
        </table>
    </body>
</html>
จากนั้น run : python3 functional_tests.py



ข้อแนะนำที่ควรทำตาม Refactoring to use a Template.
  • แก้ไขเฉพาะโค้ดเท่านั้น บางทีก็แก้ไขส่วนที่เป็น test ด้วย แต่อย่าทำพร้อมกันเพราะจะเกิดความสับสน
  • ไม่ check html (url) constant ค่าคงที่ เพราะการแก้ไขโค้ด html จะทำให้ test เปลี่ยน
  • ใช้ Template นี้สื่อความหมายว่าอะไร เอา Template ที่ถูกต้องมาเท่านั้น ไม่ check html
กระบวนการทำงาน TDD




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

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