51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1504|回复: 2
打印 上一主题 下一主题

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

[复制链接]
  • TA的每日心情
    无聊
    昨天 09:05
  • 签到天数: 1050 天

    连续签到: 1 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2016-9-13 11:34:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    转自:博客园
    最近空闲时间在探索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:
    1. __author__ = 'xua'

    2. #super class
    3. class BasePage(object):
    4.     def __init__(self, driver):
    5.         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
    1. class TestCaseInfo(object):
    2.     """description of class"""

    3.     def __init__(self, id="",name="",owner="",result="Failed",starttime="",endtime="",errorinfo=""):
    4.         self.id = id
    5.         self.name = name
    6.         self.owner = owner
    7.         self.result = result
    8.         self.starttime = starttime
    9.         self.endtime = endtime
    10.         self.errorinfo = errorinfo
    复制代码
    最后是每个测试用例的编写:(每个用例必须有自己的用例信息,这里有ID,Name等等信息,也会调用测试结果报告生成模块来添加测试结果)
    Test_Login.py
    1. __author__ = 'xua'

    2. from selenium import webdriver
    3. from selenium.webdriver.common.keys import Keys
    4. from selenium.webdriver.common.alert import Alert
    5. import unittest
    6. import time
    7. from LoginPage import LoginPage
    8. from TestCaseInfo import TestCaseInfo
    9. from TestReport import TestReport

    10. class Test_Login(unittest.TestCase):

    11.     #Setup
    12.     def setUp(self):
    13.         self.driver = webdriver.Chrome(r'C:\Users\xua\Downloads\chromedriver_win32\chromedriver.exe')
    14.         self.driver.implicitly_wait(30)
    15.         self.base_url = "http://10.222.30.145:9000/"
    16.         #test case information
    17.         self.testcaseinfo = TestCaseInfo(id="3",name="Login to floor manager lite using sbxadmin",owner="xua")
    18.         self.testResult = TestReport()
    19.   
    20.     def test_Login(self):
    21.         try:
    22.             self.testcaseinfo.starttime = str(time.asctime())
    23.             #Step1: open base site
    24.             self.driver.get(self.base_url)
    25.             #Step2: Open Login page
    26.             login_page = LoginPage(self.driver)
    27.             #Step3: Enter username
    28.             login_page.set_username("sbXadmin")
    29.             #Step4: Enter password
    30.             login_page.set_password("IGTtest1")
    31.             #Checkpoint1: Check popup dialog title
    32.             self.assertEqual(login_page.get_DiaglogTitle(),"Sign in","Not Equal")
    33.             #Step5: Cancel dialog
    34.             login_page.click_cancel()
    35.             self.testcaseinfo.result = "Pass"
    36.         except Exception as err:
    37.             self.testcaseinfo.errorinfo = str(err)
    38.         finally:
    39.             self.testcaseinfo.endtime = str(time.asctime())

    40.     #tearDown
    41.     def tearDown(self):
    42.         self.driver.close()
    43.         #write test result
    44.         self.testResult.WriteHTML(self.testcaseinfo)

    45. if __name__ == "__main__":
    46.     unittest.main()
    复制代码
    用例执行模块
    1. 借助外部文件记录需要执行的用例
    testcases.txt(带“#”标识的用例不会被执行):
    1. Test_Login.py
    2. Test_Login_2.py
    3. #Test_Login_3.py
    4. Test_Login_4.py
    复制代码
    2. 利用nose的nosetests命令执行各个用例:
    1. import subprocess

    2. class RunTests(object):
    3.     """description of class"""
    4.     def __init__(self):
    5.         self.testcaselistfile = "testcases.txt"
    6.    
    7.     #use nosetests command to execute test case list
    8.     def LoadAndRunTestCases(self):
    9.         f = open(self.testcaselistfile)
    10.         testfiles = [test for test in f.readlines() if not test.startswith("#")]
    11.         f.close()
    12.         for item in testfiles:
    13.             subprocess.call("nosetests "+str(item).replace("\\n",""),shell = True)

    14. if __name__ == "__main__":
    15.     newrun = RunTests()
    16.     newrun.LoadAndRunTestCases()
    复制代码
    测试结果报表生成模块
    测试报表模块写了两种格式:xml和html
    TestReport.py
    1. from xml.etree import ElementTree as ET
    2. import os
    3. import lxml.etree as mytree
    4. from lxml import html

    5. class TestReport(object):
    6.     """description of class"""
    7.     def __init__(self):
    8.         self.testreport = "TestResult.xml"

    9.     #If there is no "TestResult.xml", then create one
    10.     def CreateTestResultFile(self):
    11.         if os.path.exists(self.testreport) == False:
    12.             newElem = ET.Element("TestCases")
    13.             newTree = ET.ElementTree(newElem)
    14.             newTree.write(self.testreport)
    15.                         
    16.     #Write test result to xml
    17.     def WriteResult(self,testcaseInfo):
    18.         self.CreateTestResultFile()
    19.         testResultFile = ET.parse(self.testreport)
    20.         root = testResultFile.getroot()
    21.         newElem = ET.Element("TestCase")
    22.         newElem.attrib = {
    23.             "ID":testcaseInfo.id,
    24.             "Name":testcaseInfo.name,
    25.             "Owner":testcaseInfo.owner,
    26.             "Result":testcaseInfo.result,
    27.             "StartTime":testcaseInfo.starttime,
    28.             "EndTime":testcaseInfo.endtime,
    29.             "ErrorInfo":testcaseInfo.errorinfo
    30.             }
    31.         root.append(newElem)

    32.         testResultFile.write(self.testreport)

    33.     #If there is no "TestResult.html" file exists, then create one with default style
    34.     def CreateHtmlFile(self):
    35.         if os.path.exists("TestResult.html") == False:
    36.             f = open("TestResult.html",'w')
    37.             message = """<html>
    38.             <head>   
    39.                 <title>Automation Test Result</title>
    40.                 <style>
    41.                     table {
    42.                             border-collapse: collapse;
    43.                             padding: 15px;
    44.                             font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
    45.                             }
    46.                     th{
    47.                         background-color: green;
    48.                         color: white;
    49.                         border: 1px solid #ddd;
    50.                         padding-bottom: 15px;
    51.                         padding-top: 15px;
    52.                     }
    53.                     tr{
    54.                         border: 1px solid #008000;
    55.                         padding-bottom: 8px;
    56.                         padding-top: 8px;
    57.                         text-align: left;
    58.                     }
    59.                     td{
    60.                         border: 1px solid #008000;
    61.                     }
    62.                 </style>
    63.             </head>
    64.             <body>
    65.                 <h1>Automation Test Result</h1>
    66.                 <table>
    67.                     <tr>
    68.                         <th>ID</th>
    69.                         <th>Name</th>
    70.                         <th>Owner</th>
    71.                         <th>Result</th>
    72.                         <th>StartTime</th>
    73.                         <th>EndTime</th>
    74.                         <th>ErrorMessage</th>
    75.                    </tr>
    76.                 </table>
    77.             </body>
    78.             </html>
    79.             """
    80.             f.write(message)
    81.             f.close()

    82.     #append new test result to testresult file
    83.     def WriteHTML(self,testcaseinfo):

    84.         self.CreateHtmlFile()

    85.         f = open("TestResult.html","r")
    86.         
    87.         htmlcontent = f.read()
    88.         f.close()
    89.         tree = html.fromstring(htmlcontent)
    90.         tableElem = tree.find(".//table")
    91.         if testcaseinfo.result == "Failed":
    92.             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)
    93.         else:
    94.             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)
    95.         tableElem.append(mytree.HTML(str(mytablerow)))

    96.         f = open("TestResult.html","w")
    97.         #html.tostring
    98.         newContent = repr(html.tostring(tree,method="html",with_tail=False))
    99.         newContent = newContent.replace(r"\n","").replace(r"\t","").replace('b\'',"")
    100.         newContent = newContent[:len(newContent)-1]
    101.         f.write(newContent)
    102.         f.close()
    复制代码
    ok,最后看一下生成的测试报表:

    总结
    在网上有很多关于Selenium自动化的Best Practice,当然大家也可以根据自己的需求来DIY自己的框架,不管简陋与否,好用才是硬道理!

    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏5
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2019-11-4 11:04
  • 签到天数: 274 天

    连续签到: 1 天

    [LV.8]测试军长

    2#
    发表于 2016-9-13 15:37:02 | 只看该作者
    这例子看起来不错
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-22 01:31 , Processed in 0.064566 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表