|
最近空闲时间在探索Selenium的自动化测试,简单的写了一个小框架来测试公司的一个web产品。该
框架包括以下模块:
1. Test case编写模式(page模式,参考之前的博文http://www.cnblogs.com/AlwinXu/p/5537955.html)
2. Test case的管理及执行 (主要是用nose)
该模块借助了一个外部txt文件来记录测试用例,每个用例为自身的文件名,如果不需要在本次执
行,只需在文件名前添加一个“#”标识符就可以跳过该用例的执行。
3. 测试报告的生成(xml和html两种格式)
对于自动化测试而言,这些模块应该是最基本的配置了,当然还有一些辅助模块比如日志,其他公
共库模块等需要根据具体的业务逐渐丰富。闲话少说,用代码交流吧。
测试用例编写
该模块用了Page模式,之前介绍过,这次只贴代码了
- BasePage.py:
- __author__ = 'xua'
- #super class
- class BasePage(object):
- def __init__(self, driver):
- self.driver = driver
- 然后是各个web page继承BasePage,LoginPage.py:
- 复制代码
- from BasePage import BasePage
- from selenium.webdriver.common.by import By
- from selenium.webdriver.common.keys import Keys
- class LoginPage(BasePage):
- """description of class"""
- #page element identifier
- usename = (By.ID,'username')
- password = (By.ID, 'password')
- dialogTitle = (By.XPATH,'//html/body/div[7]/div/div/div[1]/h3')
- cancelButton = (By.XPATH,'//html/body/div[7]/div/div/div[3]/button[2]')
- #Get username textbox and input username
- def set_username(self,username):
- name = self.driver.find_element(*LoginPage.usename)
- name.send_keys(username)
-
- #Get password textbox and input password, then hit return
- def set_password(self, password):
- pwd = self.driver.find_element(*LoginPage.password)
- pwd.send_keys(password + Keys.RETURN)
- #Get pop up dialog title
- def get_DiaglogTitle(self):
- digTitle = self.driver.find_element(*LoginPage.dialogTitle)
- return digTitle.text
- #Get "cancel" button and then click
- def click_cancel(self):
- cancelbtn = self.driver.find_element(*LoginPage.cancelButton)
- cancelbtn.click()
- 复制代码
- 测试用例信息类:
- TestCaseInfo.py
- 复制代码
- class TestCaseInfo(object):
- """description of class"""
- def __init__(self, id="",name="",owner="",result="Failed",starttime="",endtime="",errorinfo=""):
- self.id = id
- self.name = name
- self.owner = owner
- self.result = result
- self.starttime = starttime
- self.endtime = endtime
- self.errorinfo = errorinfo
- 复制代码
-
- 最后是每个测试用例的编写:(每个用例必须有自己的用例信息,这里有ID,Name等等信息,也会
- 调用测试结果报告生成模块来添加测试结果)
- Test_Login.py
- 复制代码
- __author__ = 'xua'
- from selenium import webdriver
- from selenium.webdriver.common.keys import Keys
- from selenium.webdriver.common.alert import Alert
- import unittest
- import time
- from LoginPage import LoginPage
- from TestCaseInfo import TestCaseInfo
- from TestReport import TestReport
- class Test_Login(unittest.TestCase):
- #Setup
- def setUp(self):
- self.driver = webdriver.Chrome(r'C:\Users\xua\Downloads\chromedriver_win32\chromedriver.
- exe')
- self.driver.implicitly_wait(30)
- self.base_url = "http://10.222.30.145:9000/"
- #test case information
- self.testcaseinfo = TestCaseInfo(id="3",name="Login to floor manager lite using sbxadmin",own
- er="xua")
- self.testResult = TestReport()
-
- def test_Login(self):
- try:
- self.testcaseinfo.starttime = str(time.asctime())
- #Step1: open base site
- self.driver.get(self.base_url)
- #Step2: Open Login page
- login_page = LoginPage(self.driver)
- #Step3: Enter username
- login_page.set_username("sbXadmin")
- #Step4: Enter password
- login_page.set_password("IGTtest1")
- #Checkpoint1: Check popup dialog title
- self.assertEqual(login_page.get_DiaglogTitle(),"Sign in","Not Equal")
- #Step5: Cancel dialog
- login_page.click_cancel()
- self.testcaseinfo.result = "Pass"
- except Exception as err:
- self.testcaseinfo.errorinfo = str(err)
- finally:
- self.testcaseinfo.endtime = str(time.asctime())
- #tearDown
- def tearDown(self):
- self.driver.close()
- #write test result
- self.testResult.WriteHTML(self.testcaseinfo)
- if __name__ == "__main__":
- unittest.main()
复制代码
复制代码
用例执行模块
1. 借助外部文件记录需要执行的用例
testcases.txt(带“#”标识的用例不会被执行):
Test_Login.py
Test_Login_2.py
#Test_Login_3.py
Test_Login_4.py
2. 利用nose的nosetests命令执行各个用例:
复制代码
- import subprocess
- class RunTests(object):
- """description of class"""
- def __init__(self):
- self.testcaselistfile = "testcases.txt"
-
- #use nosetests command to execute test case list
- def LoadAndRunTestCases(self):
- 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)
- if __name__ == "__main__":
- newrun = RunTests()
- newrun.LoadAndRunTestCases()
复制代码
复制代码
测试结果报表生成模块
测试报表模块写了两种格式:xml和html
- TestReport.py
- 复制代码
- from xml.etree import ElementTree as ET
- import os
- import lxml.etree as mytree
- from lxml import html
- class TestReport(object):
- """description of class"""
- def __init__(self):
- self.testreport = "TestResult.xml"
- #If there is no "TestResult.xml", then create one
- def CreateTestResultFile(self):
- if os.path.exists(self.testreport) == False:
- newElem = ET.Element("TestCases")
- newTree = ET.ElementTree(newElem)
- newTree.write(self.testreport)
-
- #Write test result to xml
- def WriteResult(self,testcaseInfo):
- self.CreateTestResultFile()
- testResultFile = ET.parse(self.testreport)
- root = testResultFile.getroot()
- newElem = ET.Element("TestCase")
- newElem.attrib = {
- "ID":testcaseInfo.id,
- "Name":testcaseInfo.name,
- "Owner":testcaseInfo.owner,
- "Result":testcaseInfo.result,
- "StartTime":testcaseInfo.starttime,
- "EndTime":testcaseInfo.endtime,
- "ErrorInfo":testcaseInfo.errorinfo
- }
- root.append(newElem)
- testResultFile.write(self.testreport)
- #If there is no "TestResult.html" file exists, then create one with default style
- def CreateHtmlFile(self):
- if os.path.exists("TestResult.html") == False:
- f = open("TestResult.html",'w')
- message = """<html>
- <head>
- <title>Automation Test Result</title>
- <style>
- table {
- border-collapse: collapse;
- padding: 15px;
- font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
- }
- th{
- background-color: green;
- color: white;
- border: 1px solid #ddd;
- padding-bottom: 15px;
- padding-top: 15px;
- }
- tr{
- border: 1px solid #008000;
- padding-bottom: 8px;
- padding-top: 8px;
- text-align: left;
- }
- td{
- border: 1px solid #008000;
- }
- </style>
- </head>
- <body>
- <h1>Automation Test Result</h1>
- <table>
- <tr>
- <th>ID</th>
- <th>Name</th>
- <th>Owner</th>
- <th>Result</th>
- <th>StartTime</th>
- <th>EndTime</th>
- <th>ErrorMessage</th>
- </tr>
- </table>
- </body>
- </html>
- """
- f.write(message)
- f.close()
- #append new test result to testresult file
- def WriteHTML(self,testcaseinfo):
- self.CreateHtmlFile()
- f = open("TestResult.html","r")
-
- htmlcontent = f.read()
- f.close()
- tree = html.fromstring(htmlcontent)
- tableElem = tree.find(".//table")
- if testcaseinfo.result == "Failed":
- mytablerow = "<tr><td>{0}</td><td>{1}</td><td>{2}</td><td bgcolor=\"#FF0000\">{3}</td><td>{4}</td><td>{5}</td><td>{6}</td></tr>".format(testcaseinfo.id,testcaseinfo.name,testcaseinfo.owner,testcaseinfo.result,testcaseinfo.starttime,testcaseinfo.endtime,testcaseinfo.errorinfo)
- else:
- mytablerow = "<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td><td>{6}</td></tr>".format(testcaseinfo.id,testcaseinfo.name,testcaseinfo.owner,testcaseinfo.result,testcaseinfo.starttime,testcaseinfo.endtime,testcaseinfo.errorinfo)
- tableElem.append(mytree.HTML(str(mytablerow)))
- f = open("TestResult.html","w")
- #html.tostring
- newContent = repr(html.tostring(tree,method="html",with_tail=False))
- newContent = newContent.replace(r"\n","").replace(r"\t","").replace('b\'',"")
- newContent = newContent[:len(newContent)-1]
- f.write(newContent)
- f.close()
复制代码
复制代码
ok,最后看一下生成的测试报表:
|
|