Selenium và Jenkins
Selenium
3
Jenkins
3
White

Vu Nhat Minh viết ngày 23/05/2015

Mở đầu

Trong quy trình phát triển một phần mềm, Test nói chung và UT nói riêng luôn là những process rất quan trọng. Tuy nhiên khi Application càng ngày càng lớn thì khối lượng Test càng phình to và cost sẽ vượt quá cost bỏ ra cho coding. Để giảm thiểu số công sức bỏ ra, developer thường hay dùng các test framework có sẵn và tìm cách automation quy trình test.

PHP có PHPUnit, Java có JUnit, Python có nose v.v... Tuy nhiên bên ngoài UT vẫn còn những quy trình bắt buộc phải làm bằng tay. Bạn viết ra 1 website, bạn muốn test trên website bạn có đúng những link hiện ra như bạn muốn hay ko, màu sắc có thay đổi hay không, khi user click vào link có nhảy đến page target và mang theo hàm callback đã định nghĩa hay ko v.v...

Trong bài viết này sẽ giới thiệu 2 công cụ automation UT và test khá nổi tiếng. Sủ dụng và tận dụng, đôi khi sẽ thành những tool mang lại hiệu quả bất ngờ trong cả những công việc khác :D

Selenium

Selenium - nói 1 cách đơn giản, là công cụ automator tất cả các thao tác của con người trên browser. Bạn có thể giả lập 1 set các action, VD như: < User bật browser lên, User vào trang web của bạn, User đi theo link route linh1-link2-link3-link4, User click vào download button trong link 4 >

Selenium có 2 cách dùng, Selenium Server và Selenium WebDriver. Hiện nay trên firefox đã có plugin Selenium IDE. Bạn có thể dùng nó để record lại hành động của mình và export ra test code in Python, Ruby, C#, hoặc Java. Selenium test code chạy ở chế độ bình thường sẽ tự động bật browser của bạn lên và tự hành động y như bạn đã làm trước dó :D

Tuy nhiên để quy trình test không tốn quá nhiều tài nguyên, người ta thường hay config để selenium chạy headless trên Linux. VD như Python sẽ có package Xvfb, cho phép tạo display chạy ngầm và bật web driver trên đó.

Ở dưới là VD config cho CentOS distro

pip install selenium
yum install Xvfb
yum install firefox
pip install pyvirtualdisplay
# Create virtual screen by Xvfb
Xvfb :5 -ac -screen 0 1024x768x8 &
from selenium import webdriver

class SeleniumHeadlessTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.base_url = "" #Testing URL here
        self.verificationErrors = []

export DISPLAY=:5.0
python TestMySite.py

Bypass the working attendance system

Ở phần này tôi sẽ đặt ra 1 ví dụ trực quan: giả sử, công ty bạn có hệ thống check time làm việc của nhân viên. Nhân viên khi đến công ty phải login vào page, ấn vào button "Đã đến". Tương tự khi về lại phải login vào và ấn thêm button "Đã về"

Có selenium trong tay, bạn có thể giải quyết vấn đề khá đơn giản, viết 1 test script mô phỏng toàn bộ quá trình nói trên, đặt cron cho nó chạy vào giờ đến và giờ về chỉ định

from selenium import webdriver

class SeleniumHeadlessTest(unittest.TestCase):
    def setUp(self):
        mock= ""
        self.driver = webdriver.Firefox()
        self.base_url = mock
        self.verificationErrors = []

    def test_in(self):
        name=""
        pwd=""
        driver = self.driver
        driver.get(self.base_url)
        n = driver.find_element_by_xpath("..._name_field_")
        n.send_keys(name)
        p =driver.find_element_by_xpath("..._password_field_")
        p.send_keys(pwd)
        driver.find_element_by_xpath("..._login_button_").click()

Thêm 1 ít sleep time random (VD random trong khoảng 10 phút) và đặt cron 30 10 * * 1-5. Bạn đã có 1 con bot luôn check time in cho bạn trong khoảng 10h30-10h40 mỗi ngày trong tuần
:D Với package Xvfb như đã nói ở trên, con bot sẽ chạy silent bên trong máy (hay máy ảo) và ko tạo ra 1 notice nào. Redirect log ra 1 file ẩn sẽ giúp manage quá trình chạy tốt hơn.

Khi xuất hiện 1 số ngày nghỉ ko phải thứ 7, CN mà muốn đặt lịch để con bot ko chạy, vấn đề sẽ hơi phức tạp hơn 1 chút. bạn cần phải viết 1 con bot observer khác check ngày và update lại cron job

Selenium + Nose

Nếu bạn đã dùng Python 1 thời gian, chắc hẳn sẽ biết đến Nose - UT framework cho Python. Ở phần này sẽ demo thêm 1 config cho Selenium + Nose

Yêu cầu: Trang web www.mysite.com của bạn có 100 sublink: www.mysite.com/1 , www.mysite.com/2, www.mysite.com/3 ..... www.mysite.com/100

Bạn phải test xem trong từ sublink đó có 1 file image tên là "myimage.png" với div=myimage hay không.

Như vậy có 100 test case ở đây, tuy nhiên content khá giống nhau, bạn có thể nghĩ đến chuyện tạo template

from selenium import webdriver
from selenium import unittest
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException

class SeleniumHeadlessTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.base_url = "www.mysite.com"
        self.failures = []

    def Test(self):
        driver = self.driver
        driver.get(self.base_url+ "foo")
        try: driver.find_element_by_xpath("//div[@id='myimage']")
        except NoSuchElementException:
            driver.back()
            self.failures.append("foo")
        self.assertEqual(len(self.failures),0)

    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main()

Tạo file config chứa các giá trị muốn replace cho "foo" trong template.py, ở đây cụ thể là 1..100

# any comment
! another comment
$ I am comment too, do u believe me :D
1
2
...
100

Code 1 cái test_generator, ở đây tôi dùng chính Python fabric:D

# pip install fabric
from __future__ import with_statement
from fabric.api import *
import sys, os, fileinput, textwrap

_DIR=os.getcwd()

def test_generator():
    with open('./config','r') as f:
        # Ignore comment line in config file
        prefs=["#","!","<","/","$","%","&","\n"]
        ffilter = filter(lambda item: not any(item.startswith(prefix) for prefix in prefs), f.readlines()
        for line in ffilter:
            bar=line.strip()
            with lcd(_DIR):
                # create test source
                local('cp -r template.py '+bar+'.py')
            with open('./'+bar+'.py','r+') as tf:
                # replace all "foo" with variable read from config file
                tfmap = map(lambda l: l.replace("foo","bar") if "foo" in l else l, tf.readlines())
                tf.seek(0)
                tf.writelines(tfmap)
            tf.closed
    f.closed

Done! Giờ bạn có thể

#pip install multiprocessing
export DISPLAY=:5.0
fab test_generator 2>fabErr.log
nosetest --exe -v --process=4 --process-restartworker .

Jenkins

Tiếp tục về quy trình test automation, Jenkins là 1 tool xuất sắc khác. Jenkins đại diện cho khái niệm CI (continuous integration).

Bạn muốn cả bộ UT/test chạy mỗi ngày vào 10 h sáng. Mội ngày system leader đến check log để biết có bao nhiêu test đang fail, bao nhiêu error, quản lý health theo từng ngày, bạn hoàn toàn có thể dùng test framework + cronjob

Tuy nhiên Jenkins cung cấp 1 giao diện trực quan hơn, percentage, graph, coverage report, code convention checking ,v.v..... hoàn toàn tự động, có thể wake up theo svn hoặc git. Jenkins cũng có rất nhiều plugin và support hầu hết các test framework.

VD về Jenkins jobs

alt text

Source Code Management

alt text

Execute Shell

alt text

Build Trigger

alt text

Đặt lịch, tương tự cron jobs

1 recommended config là tạo 1 jenkins job observer check svn và git, nếu có update tại subsystem nào thì run jenkins jobs tương ứng với subsystem đấy. 1 sub system lại có thể chứa nhiều test framework cần wakeup (VD với PHP + Oracle, bạn có PHPUnit và utPLSQL)

Kết luận

  • Cron jobs: package lập lịch của Linux

  • Xvfb: package tạo display ảo của Linux

  • Selenium: là công cụ giả lập action trên browser, bắt chước y hệt thao tác của user và ko loại trừ bất cứ hạn chế nào

  • Jenkins: CI Test Tool, dùng để lập lịch, theo dõi và quản lý health của system

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Vu Nhat Minh

54 bài viết.
824 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
128 30
Nếu bạn thường vào trang mua sắm của amazon, chắc sẽ chẳng lạ gì với menu Shop by Department. Tốc độ hiển thị nội dung của menu là tức thì so với d...
Vu Nhat Minh viết hơn 3 năm trước
128 30
White
100 4
Lời người dịch Người dịch là một developer , sau khi tìm đọc được bài viết này bằng bản gốc tiếng Anh đã cảm thấy như được "khai sáng" về khả năng...
Vu Nhat Minh viết hơn 3 năm trước
100 4
White
68 7
Form là thành phần quan trọng nhất khi design flow đăng ký của 1 web hay 1 app, dù là view gồm nhiều bước hay chỉ là một màn hình đơn điệu. Bài này...
Vu Nhat Minh viết gần 2 năm trước
68 7
Bài viết liên quan
White
12 2
A. Vấn đề Ở các công ty mình làm việc (không biết các chỗ khác thế nào), Developer hoạt động độc lập, không được nhiều quyền ( không được quyền ro...
Ha Nguyen viết hơn 2 năm trước
12 2
White
7 5
Mở đầu Jenkins hỗ trợ nhiều cách xác thực User khác nhau : LDAP, Jenkins Database , Unix User , ... Đối với team/company sử dụng tài khoản Gmail ,...
Ha Nguyen viết hơn 2 năm trước
7 5
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
54 bài viết.
824 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!