Thursday, August 24, 2006

Functional test with Selenium RC

ลองใช้ Selenium มาทั้ง 3 แบบแล้ว
core, firefox extension, remote-control
สุดท้ายก็ชอบแบบ remote-control มากที่สุด
โดยเฉพาะการใช้ร่วมกับ ruby

ภาพรวมการทำงานของ Selenium remote-control ก็คือ
เราจะ start selenium server ขึ้นมาตัวหนึ่ง
เวลาจะ test เราก็จะเขียน program เพื่อส่ง command ที่ต้องการ test
ไปยัง server, โดย server จะสื่อสารและสั่งงานให้ browser ทำตาม command ที่เราสั่ง



ที่นี้ลองมาดูการทำงานภายในของ Selenium ดูบ้าง
วิธีการที่ selenium ใช้ควบคุม browser ก็คือการใช้ javascript
เช่นสมมติว่าเราต้องการให้เกิดการ click ที่ปุ่มๆหนึ่ง

<a href="xxxx" id="myButton">click me</a>

ในแง่ของ test script เราก็จะส่งคำสั่งต่อไปนี้

cmd = "click"
param1 = "id=myButton"

ทีนี้ selenium จะทำอย่างไร ปุ่มนี้จึงจะ click ได้
ขั้นที่ 1 ก็คือหา element ที่ต้องการ click ให้เจอก่อน
โดยวิธีการหา จะขึ้นอยู่กับ prefix ที่เรากำหนดไปใน parameter
เช่นถ้ากำหนด id= นำหน้า, selenium ก็จะใช้วิธี getElementById
แต่ถ้าเป็นพวก xpath=//img[@alt='The image alt text'] ก็จะใช้ xpath
หรือถ้านำหน้าด้วย css= ก็จะใช้ css selector ในการหา

ขั้นที่ 2 ก็คือเมื่อเจอ element ที่ต้องการแล้ว ก็ต้องทำให้เกิดการ click ขึ้นมา
ลองดูตัวอย่างของการ simulate mouse click ใน Firefox ดู
MozillaPageBot.prototype.clickElement = function(element, clientX, clientY) {

triggerEvent(element, 'focus', false);

// Add an event listener that detects if the default action has been prevented.
// (This is caused by a javascript onclick handler returning false)
var preventDefault = false;

...

// Trigger the click event.
triggerMouseEvent(element, 'click', true, clientX, clientY);

...

if (this.windowClosed()) {
return;
}

triggerEvent(element, 'blur', false);
};

จะเห็นว่า มันทำการ simulate event focus จากนั้นก็ทำการสร้าง event mouse click
สุดท้ายก็ส่ง event blur
ส่วนการทำงานภายในของ function triggerMouseEvent
ถ้าเป็น mozilla ดูเหมือนจะใช้วิธีนี้
var evt = document.createEvent('MouseEvents');
.. // init event
element.dispatchEvent(evt);

จะเห็นได้ว่า วิธีการทำงานนั้นน่าสนใจทีเดียว

ประเด็นที่ตามมาของการใช้ javascript control ก็คือ
javascript นั้นจะ run ใน domain name ที่เราต้องการ test อย่างไร
เนื่องจาก javascript จะทำงานได้กับ domain name ที่เรา load javascript นั้นมาเท่ากัน
Selenium เลยใช้วิธีการ start proxy server ขึ้นมา
เพื่อบังคับให้ request ของ browser วิ่งผ่านมันก่อน
เพื่อที่มันจะได้ inject javascript ที่ต้องการลงไปได้



หันไปดูด้านผู้ใช้ดูบ้าง
ลองดูตัวอย่าง ruby code ที่ผมเขียน test

def setup
@domain = 'http://wcfweb.test:8080'
@sel = Selenium::SeleneseInterpreter.new("selenium.server.test", 4444,
"*firefox", @domain, 15000)
@sel.start
@home = "#{@domain}/fin/app?page=wcf2000/Wcf2110_1&service=page"
end

def submit_cheque(no, date, bank, amount)
to_page2
@sel.click("link=0.00")
type_cheque(no, date, bank, amount)
calc_charge
@sel.click("save_btn")
@sel.wait_for_page_to_load(15000)
end

def t_cheque_amount_entry_but_no_other_info
submit_cheque("", "", "", 2000)
assert(@sel.is_text_present("กรุณาระบุเลขที่เช็ค"))
assert(@sel.is_text_present("กรุณาระบุวันที่เช็ค"))
assert(@sel.is_text_present("กรุณาระบุรหัสธนาคาร"))
end

def t_cheque_entry_wrong_date
submit_cheque("1234567", nextDay(2), "", 2000)
assert(@sel.is_text_present("วันที่เช็ครับลงล่วงหน้ามากกว่า 1 วัน"))
end

def t_cheque_entry_wrong_bank_code
submit_cheque("1234567", nextDay(1), 1234, 2000)
assert(! @sel.is_text_present("วันที่เช็ครับลงล่วงหน้ามากกว่า 1 วัน"))
assert(@sel.is_text_present("รหัสธนาคารไม่ถูกต้อง"))
end


เวลา run, Selenium ก็จะเปิด browser ทำงาน
โดย browser มีหน้าตาแบบนี้

Related link from Roti

No comments: