|
2#
楼主 |
发表于 2018-4-9 10:55:07
|
只看该作者
可维护性好
由于测试目标页面的多变性,页面元素的定位经常需要改变,利用了页面模式后,只需要修改一遍其页面类
中的定位就可以对所用用到该元素的测试用例生效;而在未使用该模式的情况下,必须修改每一个用到该元
素的测试用例,非常容易遗漏,工作量也非常大。
综合以上页面模式的各种优点,我们在以后的web自动化中可以多使用该模式来组织页面。
3.3.2 公共库模块
公共库模块是为创建测试用例服务的,它主要包括常量、公共函数、日志管理、报表管理以及发
送邮件管理等。
公共库模块涉及到的功能一般多而杂,在设计的时候只要遵循高内聚低耦合就可以了。比如常量、
变量和一些公共函数可以放在同一个文件中Common.py:
复制代码
- from datetime import datetime
- def driverPath():
- return r'C:\Users\xua\Downloads\chromedriver_win32\chromedriver.exe'
- def baseUrl():
- return "https://xxx.xxx.xxx.xxx:9000"
- #change time to str
- def getCurrentTime():
- format = "%a %b %d %H:%M:%S %Y"
- return datetime.now().strftime(format)
- # Get time diff
- def timeDiff(starttime,endtime):
- format = "%a %b %d %H:%M:%S %Y"
- return datetime.strptime(endtime,format) - datetime.strptime(starttime,format)
复制代码
复制代码
测试用例信息类用来标识测试用例,并且包括执行用例执行结果信息,主要包括以下字段:
复制代码
- class TestCaseInfo(object):
- """description of class"""
- def __init__(self, id="",name="",owner="",result="Failed",starttime="",endtime="",secondsDuration="",e
- rrorinfo=""):
- self.id = id
- self.name = name
- self.owner = owner
- self.result = result
- self.starttime = starttime
- self.endtime = endtime
- self.secondsDuration = secondsDuration
- self.errorinfo = errorinfo
复制代码
复制代码
测试用例信息需要在每个测试用例中实例化,以便对测试用例进行标记,并最终体现在测试报告中。
日志主要用来记录测试用例执行步骤及产生的错误信息,不同的信息有不同的日志级别,比如Information,
Warning,Critical和Debug。由于每个测试用例产生的日志条目比较少,所以在测试框架中只利用了最高级
别的日志打印,即Debug级别,该级别也会将其他所有的日志级别的信息同样打印出来。在具体的实现中
引用了Python标准库中的logging类库,以便更方便的控制日志输出:
复制代码
- import logging
- import ResultFolder
- logger = logging.getLogger()
- logger.setLevel(logging.DEBUG)
- def CreateLoggerFile(filename):
- try:
- fulllogname = ResultFolder.GetRunDirectory()+"\\"+filename+".log"
- fh = logging.FileHandler(fulllogname)
- fh.setLevel(logging.DEBUG)
- formatter = logging.Formatter('%(asctime)s [line:%(lineno)d] %(message)s')
- fh.setFormatter(formatter)
- logger.addHandler(fh)
- except Exception as err:
- logger.debug("Error when creating log file, error message: {}".format(str(err)))
- def Log(message):
- logger.debug(message)
复制代码
复制代码
报表管理及发送邮件模块实现了报表(html格式)的生成及自动发送邮件的功能。报表和邮件依附于当前
测试的执行,每次执行都会独立的触发报表生成和邮件发送。该模块主要运用了Python中的lxml、smtplib
和email库。
3.3.3 用例仓库
用例仓库主要用来组织自动化测试用例。每条测试用例都被抽象成一个独立的类,并且均继承
自unittest.TestCase类。 Python中的unittest库提供了丰富的测试框架支持,包括测试用例的setUp和tearD
own方法,在实现用例的过程中可以重写。依托页面管理和公共库模块实现的页面方法和公共函数,每一
个测试用例脚本的书写都会非常清晰简洁,一个简单的Floor Manager Lite的登录用例如下:
复制代码
- class Test_TC_Login(unittest.TestCase):
- def setUp(self):
- self.driver = webdriver.Chrome(cc.driverPath())
- self.base_url = cc.baseUrl()
- self.testCaseInfo = TestCaseInfo(id=1,name="Test case name",owner='xua')
- self.testResult = TestReport()
- LogUtility.CreateLoggerFile("Test_TC_Login")
- def test_A(self):
- try:
- self.testCaseInfo.starttime = cc.getCurrentTime()
- #Step1: open base site
- LogUtility.Log("Open Base site"+self.base_url)
- self.driver.get(self.base_url)
- #Step2: Open Login page
- login_page = LoginPage(self.driver)
- #Step3: Enter username & password
- LogUtility.Log("Login web using username")
- login_page.set_username("username")
- login_page.set_password("password")
- time.sleep(2)
- #Checkpoint1: Check popup dialog title
- LogUtility.Log("Check whether sign in dialog exists or not")
- self.assertEqual(login_page.get_DiaglogTitle(),"Sign in")
- #time.sleep(3)
- #Step4: Cancel dialog
- login_page.click_cancel()
- self.testCaseInfo.result = "Pass"
- except Exception as err:
- self.testCaseInfo.errorinfo = str(err)
- LogUtility.Log(("Got error: "+str(err)))
- finally:
- self.testCaseInfo.endtime = cc.getCurrentTime()
- self.testCaseInfo.secondsDuration = cc.timeDiff(self.testCaseInfo.starttime,self.testCaseInfo.endtime)
- def tearDown(self):
- self.driver.close()
- self.testResult.WriteHTML(self.testCaseInfo)
- if __name__ == '__main__':
- unittest.main()
复制代码
复制代码
从这个测试用例中,我们可以看到
Setup中定义了执行测试用例前的一些实例化工作
tearDown对执行完测试做了清理和写日志文件工作
测试步骤、测试数据和测试检查点非常清晰,易修改(比如用户名密码)
日志级别仅有Debug,所以写日志仅需用同一Log方法
3.3.4 用例执行模块(控制器)
执行模块主要用来控制测试用例脚本的批量执行,形成一个测试集。用例的执行引用了Python标
准库中的subprocess来执行nosetests的shell命令,从而执行给定测试用例集中的用例。测试用例集是一个简
单的纯文本文件,实现过程中利用了.txt文件testcases.txt:
- Test_Login_pass.py
- Test_Login_Fail.py
- #Test_MainPage_CheckSecurityTableInfo.py
- Test_MainPage_EditSecurityInfo.py
复制代码
用例前没有“#“标记的测试用例脚本会被执行,而有”#“标记的则会被忽略,这样可以很方便的控制测试集
的执行,当然也可以创建不同的文件来执行不同的测试集。
具体的调用代码如下:
复制代码
- def LoadAndRunTestCases(self):
- try:
- f = open(self.testcaselistfile)
- testfiles = [test for test in f.readlines() if not test.startswith("#")]
- f.close()
- for item in testfiles:
- subprocess.call("nosetests "+str(item).replace("\\n",""),shell = True)
- except Exception as err:
- LogUtility.logger.debug("Failed running test cases, error message: {}".format(str(err)))
- finally:
- EmailUtils.send_report()
复制代码
复制代码
3.4 执行结果
测试用例执行完毕后主要有两种输出:日志和测试报告。测试报告会html附件的形式通过邮件发出,例如:
4 需要改进的模块
对于现有实现的测试框架,已经可以满足web对象的自动化需求,但还是有些可以改进提高的地方,比如:
针对部分测试用例是否可以尝试数据驱动
添加屏幕截图功能
封装selenium中By库中的函数,以便更高效的定位页面元素等
结合业界优秀的自动化框架和实践持续改进
5 总结
基于selenium实现的web自动化框架不仅轻量级而且灵活,可以快速的开发自动化测试用例。结合本
篇中的框架设计以及一些好的实践,希望对大家以后的web自动化框架的设计和实现有所帮助。
|
|