由于资源有限,需要在一台 Linux 机器上跑 UI 自动化测试脚本,于是想到用 PhantomJS 进行测试,这样便无需打开任何浏览器,只需要做好各项结果校验即可。
同样,PhantomJS 也可以进行截图验证,不过在 Linux 下需要安装相应字库,否则会出现 PhantomJS 截图无法显示中文的情况。

原理

关于 Selenium

Selenium 是一个 Web 的自动化测试工具,可以在多平台下操作多种浏览器进行各种动作,比如运行浏览器,访问页面,点击按钮,提交表单,浏览器窗口调整,鼠标右键和拖放动作,下拉框和对话框处理等。

关于 PhantomJs

PhantomJs 可以看作一个没有页面的浏览器,有渲染引擎(QtWebkit)和 JS 引擎(JavascriptCore)。PhantomJs 有 DOM 渲染,JS 运行,网络访问,网页截图等多个功能。
使用 PhantomJS,而不用 Chromedriver 和 firefox,主要是因为 PhantomJS 的静默方式(后台运行,不打开浏览器)。

安装

Linux

sudo pip install selenium
sudo apt-get install PhantomJS

Windows

以一个简单的 UI 自动化代码进行示例:

# coding=utf-8
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re
import BSTestRunner

class operation_test(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.PhantomJS("/Downloads/phantomjs-2.1.1-macosx/bin/phantomjs") 
        self.driver.implicitly_wait(30)
        self.base_url = "https://www.xxxxxxxxxx.cn/"
        self.verificationErrors = []
        self.accept_next_alert = True

    def test_operation(self):
        driver = self.driver
        driver.get(self.base_url + "/tenant/#/login?return_insite=https://xxxxxxxxx.cn/")
        driver.set_window_size(1680,1050)
        driver.find_element_by_id("email").clear()
        driver.find_element_by_id("email").send_keys("XXXXX") # 隐藏账号
        driver.find_element_by_id("passwd").clear()
        driver.find_element_by_id("passwd").send_keys("XXXX") # 隐藏密码
        driver.find_element_by_css_selector("button[type=\"submit\"]").click()
        driver.find_element_by_xpath("/html/body/aside/nav/ul/li[4]/a").click()

        driver.find_element_by_xpath("/html/body/div[1]/div/div[2]/div/div[1]/div[2]/span/div/div/div/div[2]/a").click()
        driver.find_element_by_css_selector("input").clear()
        driver.find_element_by_css_selector("input").send_keys(u"自动化新建操作")
        driver.find_element_by_xpath("//div[@id='layout-content']/div/div[2]/div/section/div[3]/div/span/i").click()
        time.sleep(5)
        driver.find_element_by_xpath("/html/body/div[6]/div/div/ul[1]/li[2]").click()
        time.sleep(3)
        driver.find_element_by_xpath("/html/body/div[6]/div/div/ul[2]/li[2]").click()
        driver.find_element_by_xpath("/html/body/div[6]/div/div/ul[1]/li[1]").click
        time.sleep(2)
        driver.find_element_by_css_selector("textarea").clear()
        driver.find_element_by_css_selector("textarea").send_keys(u"自动化输入描述")
        time.sleep(3)

        ActionChains(self.driver).send_keys(Keys.TAB).perform()
        time.sleep(3)
        ActionChains(self.driver).send_keys(Keys.TAB).perform()
        time.sleep(3)
        ActionChains(self.driver).send_keys(Keys.TAB).perform()
        time.sleep(3)
        ActionChains(self.driver).send_keys(Keys.TAB).perform()
        time.sleep(3)
        ActionChains(self.driver).send_keys("print").perform()
        time.sleep(3)
        driver.find_element_by_xpath("//*[@id='layout-content']/div/div[2]/div/section[5]/button[2]").click()
        time.sleep(5)
        text = driver.find_element_by_xpath('//*[@id="layout-content"]/div/div[2]/div/div[1]/div[2]/span/div/div/div/div[3]/div/div/div/div/table/tbody/tr[1]/td[2]/a').text
        #print text
        try:
            self.assertEqual(operation_name.decode('utf-8'), text)
        except AssertionError as e:
            print '创建操作异常'


    def is_element_present(self, how, what):
        try: self.driver.find_element(by=how, value=what)
        except NoSuchElementException as e: return False
        return True

    def is_alert_present(self):
        try: self.driver.switch_to.alert()
        except NoAlertPresentException as e: return False
        return True

    def close_alert_and_get_its_text(self):
        try:
            alert = self.driver.switch_to.alert()
            alert_text = alert.text
            if self.accept_next_alert:
                alert.accept()
            else:
                alert.dismiss()
            return alert_text
        finally: self.accept_next_alert = True

    def tearDown(self):
        self.driver.quit()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    #unittest.main()
    BSTestRunner.main() # 使用BSTestRunner调用unittest

这样,我在调用该脚本的时候,selenium 不会打开任何浏览器,而是以静默方式运行。


↙↙↙阅读原文可查看相关链接,并与作者交流