小小糖 发表于 2018-3-14 14:12:27

简易selenium自动化测试框架(Python)

最近空闲时间在探索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/div/div/div/h3')
    cancelButton = (By.XPATH,'//html/body/div/div/div/div/button')

    #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 =
      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,最后看一下生成的测试报表:





梦想家 发表于 2018-5-14 15:57:38

:victory:
页: [1]
查看完整版本: 简易selenium自动化测试框架(Python)