经过前三章我们对自动化相关内容的学习,我们了解了什么是自动化测试,测试环境的搭建和WebDriver API的介绍,定位方法及检测点儿设置等相关知识点。从本章开始,我们讲探讨测试用例的编写,以及其相关的知识点。
4.1 第一个测试用例Hello World
几乎所有编程语言的第一个程序就是输出Hello World,那我们也沿袭这个传统,第一个测试用例就是用百度搜索Hello World。
首先我们先写一下这个测试用例的手工测试步骤:
(1)用浏览器打开百度首页。
(2)输入Hello World,然后单击“百度一下”按钮,进行查找。
(3)检测查找到的结果页面,第一项是否包含Hello World。
这是我们手工测试的步骤,如果要转化成自动化测试用例,需要转化成我们需要的脚本语言编写的程序。
4.1.1 Selenium IDE录制
如我们前面讲到的,可以利用Selenium IDE来录制测试步骤,然后添加上检测点,就可以形成一个测试用例。转化成我们需要的脚本语言格式,如python,然后保存文件,放到我们的开发环境下就可以调试运行了。
具体的录制方法如下:
(1)打开火狐浏览器,打开Selenium IDE,在IDE的Base URL中输入要录制的网站地址:http://www.baidu.com。
(2)IDE默认是处于录制状态的,如果没有,单击红色按钮,录制。在火狐浏览器的地址栏中输入http://www.baidu.com,打开百度首页。
(3)输入“Hello World”,单击“百度一下”按钮,进行搜索。
(4)在搜索结果页,右击第一个结果项,如图4.1.1.1所示,选择assert判断项,设置检测点。
图4.1.1.1 设置检测点
(5)单击Selenium IDE的回放按钮,检测录制的测试步骤,如图4.1.1.2所示,不过此时检测点会报错,原因是执行太快,页面没有刷新出来。
图4.1.1.2 回放录制的测试步骤
(6)为了解决这个问题,我们在检测点前添加一个等待。等待我们要检测的内容出现后,再去执行判断。如图:4.1.1.3所示,回放验证成功。
图4.1.1.3 添加等待命令
(7)现在说明我们录制的测试用例没有问题,导出录制的测试用例为python(webdriver)格式的,保存为helloworld.py.如图4.1.1.4所示:
图4.1.1.4 导出录制的测试用例
(8)检查导出的代码,Selenium IDE帮我们导出的代码如下:
# -*-coding: utf-8 -*-
fromselenium import webdriver
fromselenium.webdriver.common.by import By
fromselenium.webdriver.common.keys import Keys
fromselenium.webdriver.support.ui import Select
fromselenium.common.exceptions import NoSuchElementException
fromselenium.common.exceptions import NoAlertPresentException
importunittest, time, re
classHelloworld(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url ="http://www.baidu.com/"
self.verificationErrors = []
self.accept_next_alert = True
def test_helloworld(self):
driver = self.driver
driver.get(self.base_url +"/")
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys("HelloWorld")
driver.find_element_by_id("su").click()
for i in range(60):
try:
if u"hello world_百度百科"==driver.find_element_by_xpath("//div[@id='content_left']/div/h3/a").text:break
except: pass
time.sleep(1)
else: self.fail("time out")
self.assertEqual(u"hello world_百度百科",driver.find_element_by_link_text(u"hello world_百度百科").text)
def is_element_present(self, how, what):
try: self.driver.find_element(by=how,value=what)
except NoSuchElementException, e: returnFalse
return True
def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException, 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()
代码讲解:
Ø 最前面是引用Webdriver相关的一些儿函数或方法。
Ø 创建一个测试类Helloworld,类里是具体的一些儿测试方法。
Ø 函数setUp,初始化火狐浏览器,要测试的网站URL等一些儿常用的变量。
Ø 函数test_helloworld() 是我们具体的操作步骤及验证点的检测。
Ø 函数is_element_present():判断元素是否在当前页面显示;is_alert_present():当前页面是否有浮层;close_alert_and_get_its_text():关闭浮层,并返回浮层标题。这几个函数由SeleniumIDE自动生成,在本例是没有用到。
Ø 函数tearDown()关闭浏览器,判断是否有错误。
Ø 运行测试用例,这是python的功能,不做详解。
(9)将代码导入到开发环境中。打开Eclipse,新建PyDev工程如:WebAuto。将刚刚保存的helloworld.py文件导入到这个工程中,如图4.1.1.5所示:
图4.1.1.5导入保存的文件
(10) 运行验证刚刚导入的代码,右击这个文件,“Run as”-->”python run”,查看运行结果。程序打开火狐,执行了测试用例,执行完成后关闭浏览器。如图4.1.1.6所示:
图4.1.1.6 程序运行结果
(11) 至此,利用Selenium IDE来录制测试用例,并且在开发环境下运行通过。可是我们发现这样录制测试用例还是存在问题的,转化后会有很多用不到的代码存在,而且不符合模块化编程的规范。所以我们还是喜欢自己编写测试用例,录制转化只能当作参考。
4.1.2 手动编写自动化测试用例
兼于用Selenium IDE录制转化测试用例会出现很多没有用的代码,并且代码复用性差,转化后的方法也不是最完美的,所以很多自动化高手是不会用这种方法来写自动化测试用例的。
现在我们来讲解一下高手最常用的方法,自己编写自动化测试用例。当然编写之前也会有代码架构组织,公用函数编写,测试数据和测试用例代码的分离等工作要做。我们在本章就不涉及这些儿方面,只按一个普通的测试用例,以测试流程为序来编写测试用例,其他的内容将在后面的章节讲解。
手工编写自动化测试用例的步骤,我们还以上面的Hello World为例:
Ø 打开Eclipse,创建pydev工程,为了方便起见,我们就用上面创建的WebAuto工程。
Ø 创建测试脚本文件:文件à新建àotheràPyDev&Module,然后在打开的对话框中输入 HelloWorld_demo,单击“fininsh”。最后在弹出的对话框中选择“Module:Unittest”。如图4.1.2.1所示:
图4.1.2.1新建文件unittest
Ø 此时会自动生成代码文件,内容如下:
'''
Created on 2015-3-4
@author: sxf
'''
import unittest
class Test(unittest.TestCase):
def testName(self):
pass
if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.testName']
unittest.main()
这是一个默认的文件内容,引用了unittest,创建Test类,测试方法testName,以及运行接口unittest.main().
Ø 我们需要在此基础上加上我们的测试用例,首先要修改类名为HelloWorld_Demo,测试函数为testSearch(注:测试函数必须以test开头,否则unittest将不识别。)然后开始加入我们的测试步骤及设置检测点。
Ø 测试用例代码及分析。
最后我们的测试用例代码如下:
# -*- coding: utf-8 -*-
'''
Created on 2015-3-4
@author: sxf
'''
import unittest
from selenium import webdriver
import time
class HelloWorld_Demo(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.base_url = "http://www.baidu.com/"
def testSearch(self):
'''
Search Hello World!
'''
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys("HelloWorld")
driver.find_element_by_id("su").click()
time.sleep(3)
#检查查询的结果
self.assertEqual(u"hello world_百度百科", driver.find_element_by_xpath("//div[@id='content_left']/div/h3/a").text)
def tearDown(self):
self.driver.quit()
if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.testName']
unittest.main()
代码讲解:
(1)首先我们要引入用例要用到的Webdriver,time.
(2)创建初始化函数setUp(),用于初始化火狐浏览器,及测试的baseURL.
(3)创建具体的测试函数testSearch(),将测试步骤及检测点添加进去。此处我们用的检测点是利用Xpath定位获取要检测的文本,然后和我们预期的相比较。其中的定位操作,还有测试步骤相对应的代码,我们可以从刚刚录制的代码中拷过来,也可以自己写,这样看你的编码水平了。
(4)创建测试用例清理函数tearDown(),关闭浏览器。
(5)这是一个测试用例最基本的结构,再复杂的测试用例,也是这样的结构,只不过测试步骤变多,检测点多些儿而已。
Ø 用Eclipse运行刚刚编写的测试代码,发现和SeleniumIDE录制的结果一样。而我们的代码比录制转换后的代码简洁很多,这个才是我们想要的结果。
4.2 测试用例代码结构
通过上面我们对百度搜索hello world测试用例的讲解,我们对自动化测试用例有了一定程度的了解。就是用代码来完成我们手工测试的步骤,然后利用检测点来检测执行的结果。可是要写好自动化测试用例,单单知道这些儿还是不够的,我们需要了解一下自动化测试用例的结构。
4.2.1 自动化测试代码结构
通常一个完整的自动化测试用例包含以下几部分:
(1)测试用例执行的先决条件。
测试用例执行之前的公用变量的定义,或是测试用例执行之前的一些儿先决条件,如用户A和B要相互发私信操作时,必须相互关注等。而Python Unittest是用setUp()来处理的,因为所有测试用例执行前,先执行这个函数。
(2)具体的测试用例。
根据不同的测试需要,来组织不同的测试用例。测试用例必须包含测试步骤,测试步骤执行完后对执行结果的检测。测试用例命名要以test开头,一个测试类中可以包含多个测试用例。
(3)测试用例执行完后的清理。
测试用例执行完成后,如果对被测试对象产生了一些儿测试数据,则必须清除。如发布了一些儿文字,或是测试操作影响了两个测试账号间的关系等。如果不清除,则会影响下次测试用例的执行或是在并发过程中其他的测试用例的执行。
(4)测试用例的调用。
在Python编写的自动化测试用例,可加上对测试用例的调用,否则测试用例将无法执行。
4.2.2 测试用例编写过程中常见的问题
在我们编写测试用例的过程中,会经常遇到一些儿问题的,这些儿问题影响着我们测试用例的质量。所以我们要在编写之前就在脑海里对它们提高警惕,避免这样的错误:
(1)随意命名测试用例类和函数名。
这涉及到编码规范的问题,变量,函数,类的命名必须有意义,不可随意命名。在自动化测试用例中,不正规的命名,会影响测试用例的可读性,而且一旦执行出错,不便于定位问题。
(2)前提条件写到具体的测试用例中。
setup()函数是每个测试用例执行之前都会调用的,所以这个函数里面写的是所有测试用例都要用到的前提条件。而有很多初学的同学,会把测试步骤都写到具体的测试函数中,这样就会造成把前提条件写了很多次,不符合代码重用机制。
(3)测试用例耦合度高。
测试用例之间应该没有太多的耦合性,各自执行完测试用例,判断检测点之后,退出浏览器。这样不影响其他测试用例的执行,如果我们测试用例之间有耦合,可是使用相同的测试账号的话,单线程执行没有问题,多线程运行的时候,就会造成死锁或是相互影响。
(4)执行完测试用例,不对测试数据进行清理。
执行完测试用例后,要对测试数据是行清理。而执行线上回归任务的自动化测试用例原则是不产生测试数据的。如果本次执行的测试数据不清理,下次就算执行失败了,检测执行结果的时候,如果检测到上次产生的测试数据了,也不会报错的。
(5)测试用例中没有注释。
不管是什么样的语言写的程序,都要求有注释的。由于我们做自动化测试,大多没有经过详细的编码规范的培训,所有不喜欢写注释。可是如果不加注释,时间长了,你就不清楚这个测试用例是做什么的了,需要一步一步地去看代码分析,多费时啊!如果加上注释,只需要看一下注释即可。
4.3 本章小结
本章我们以一个传统的hello world测试用例讲解了如何利用Selenium IDE录制自动化测试用例,以及如何手工编写自动化测试用例。同时还讲解了自动化测试用例的结构及常见错误,从具体的自动化测试用例来介绍如何编写自动化测试用例。接下来的章节,我们将讲述常用的页面元素的自动化测试用例操作,请大家继续学习。