美文网首页
Web端自动化测试--Python+selenium+unitt

Web端自动化测试--Python+selenium+unitt

作者: 巴鶴 | 来源:发表于2021-02-03 21:03 被阅读0次

    Page Object 是 Selenium 自动化测试项目开发实践的最佳设计模式之一,Page Object 的主要体现于对界面交互细节的封装,这样可以使测试案例更关注与业务而非界面细节,提高测试案例的可读性。

    认识 Paget Object

    一、Page object 简称POM框架

    • POM提供了一种在UI层操作、业务流程与验证分离的模式,这使得测试代码变得更加清晰和高可读性;
    • 对象库与用例分离,使得我们更好的复用对象,甚至能与不同的工具进行深度结合应用;
    • 可复用的页面方法代码会变得更加优化;
    • 更加有效的命名方式使得我们更加清晰的知道方法所操作的UI元素。例如我们要回到首页,方法名命名为: gotoHomePage(),通过方法名即可清晰的知道具体的功能实现。;

    二、Page object设计模式的优点

    1. 减少代码的重复;
    2. 提高测试用例的可读性;
    3. 提高测试用例的可维护性,特别是针对 UI 频繁变化的项目;

    实战--博客园登录自动化测试发送测试报告

    思路分析:

    • 浏览器封装;
    • 页面截图函数封装,偏于后续浏览查看;
    • 页面元素基础类操作封装,包含断言设计;
    • 登录元素操作封装;
    • 登录测试用例设计;

    代码参考

    myunit.py

    # 浏览器驱动封装
    '''
    @author: Yvon_早安阳光
    '''
    from selenium import webdriver
    import unittest 
    class MyTest(unittest.TestCase):
        def setUp(self):
            self.driver = webdriver.Firefox()  
        def tearDown(self):
            self.driver.quit()
    

    function.py

    '''
    @author: Yvon_早安阳光
    '''
    import time
    from selenium import webdriver
     
    #封装截图函数
    def insert_img(driver,filename):
        file_path = 'insert_img/'
        now = time.strftime("%Y-%m-%d %H_%M_%S")
        screen_name = file_path + '\\' + now + filename
        driver.get_screenshot_as_file(screen_name)
         
    # 登录成功截图
    def success_img(driver,file_name):
        filepath = 'success_img/'
        now = time.strftime("%Y-%m-%d %H_%M_%S")
        screenname = filepath + '\\' + now + file_name
        driver.get_screenshot_as_file(screenname)    
            
    if __name__ == '__main__':
        driver = webdriver.Firefox()
        driver.quit()
    

    Base.py

    # 页面元素基础类操作封装
    '''
    @author: Yvon_早安阳光
    '''
    class Page(object):
    
      #BasePage封装所有页面都公用的方法,例如driver, url ,FindElement等
        login_url = "https://passport.cnblogs.com/user/signin"
        #实例化BasePage类时,最先执行的就是__init__方法,该方法的入参,其实就是BasePage类的入参。
        #__init__方法不能有返回值,只能返回None,self只实例本身,相较于类Page而言
    
        def __init__(self,selenium_driver,base_url = login_url,parent = None):
            self.base_url = base_url
            self.driver = selenium_driver
            self.timeout =10
            self.parent = parent
    
        '''通过title断言进入的页面是否正确。使用title获取当前窗口title,检查输入的title是否在当前title中,返回比较结果(True 或 False)'''  
    
        def on_page(self):
            return self.driver.current_url == (self.base_url + self.url)
    
        '''#打开页面,并校验页面链接是否加载正确,以单下划线_开头的方法,在使用import *时,该方法不会被导入,保证该方法为类私有的。'''
    
        def _open(self,url):
            #使用get打开访问链接地址
            url = self.base_url + url
            self.driver.get(url)
            #使用assert进行校验,打开的窗口title是否与配置的title一致。调用on_page()方法
           # assert self.on_page(), u"打开开页面失败 %s"%url
          '''定义open方法,调用_open()进行打开链接'''
    
        def open(self):
            self._open(self.url)
    
        def find_elements(self,*loc):
            return self.driver.find_elements(*loc)
    
        '''重写switch_frame方法'''
        def switch_frame(self, loc):
            return self.driver.switch_to_frame(loc)
    
        '''script方法,用于执行js脚本,范围执行结果'''
        def script(self, src):
            self.driver.execute_script(src)
    
        '''重写定义send_keys方法'''
        def send_keys(self, loc, vaule, clear_first=True, click_first=True):
            try:
                loc = getattr(self,"_%s"% loc)  #getattr相当于实现self.loc
                if click_first:
                    self.find_element(*loc).click()
                if clear_first:
                    self.find_element(*loc).clear()
                    self.find_element(*loc).send_keys(vaule)         
            except AttributeError:
                print (u"%s 页面中未能找到 %s 元素"%(self, loc))
    

    LoginPage.py

    登录元素操作封装
    '''
    @author: Yvon_早安阳光
    '''
    from selenium.webdriver.common.by import By
    from Base import Page
    from time import sleep
    
    class login(Page):
        '''博客园登录页面模型'''
        url = '/'
        # 定位器
        '''用户名'''
        username_loc = (By.ID,"input1")
        '''密码'''
        password_loc = (By.ID,"input2")
        '''登陆按钮'''
        submit_loc = (By.ID,"signin")
    
      '''输入用户名:调用send_keys对象,输入用户名'''
        def input_username(self,username):
            self.find_element(*self.username_loc).clear()
            self.find_element(*self.username_loc).send_keys(username)        
                 
     '''输入密码:调用send_keys对象,输入密码'''
        def input_password(self,password):
            self.find_element(*self.password_loc).clear()
            self.find_element(*self.password_loc).send_keys(password)
     
      '''点击登录:调用send_keys对象,点击登录''' 
        def click_submit(self):
            self.find_element(*self.submit_loc).click()
             
       # 定义统一登录入口
        def user_login(self,username = '123',password = '123'):
            '''获取用户的用户名和密码'''
            self.open()
            self.input_username(username)
            self.input_password(password)
            self.click_submit()
            sleep(2)
             
        '''用户为空'''
        user_error_hint_loc = (By.XPATH,".//*[@id='tip_input1']")
        '''密码为空'''
        pawd_error_hint_loc = (By.XPATH,".//*[@id='tip_input2']")
        '''用户名和密码不匹配'''
        user_pawd_error_hint_loc = (By.XPATH,".//*[@id='tip_btn']")
        '''登陆成功ID校验'''
        user_login_success_loc = (By.ID,"lnk_current_user")
       
        #用户名错误提示
        def user_error_hint(self):
            return self.find_element(*self.user_error_hint_loc).text
         
        #密码错误提示
        def pawd_error_hint(self):
            return self.find_element(*self.pawd_error_hint_loc).text
         
        #用户名和密码不匹配错误提示
        def user_pawd_error_hint(self):
            return self.find_element(*self.user_pawd_error_hint_loc).text
        #登录成功用户名
        def user_login_success(self):
            return self.find_element(*self.user_login_success_loc).text
    

    Login_sta.py

    登录测试用例
    '''
    @author: Yvon_早安阳光
    '''
    from time import sleep
    import unittest,random
    from Login1 import myunit
    from LoginPage import login
    from Login1 import function
    
    class LoginTest(myunit.MyTest):
        '''博客园登录'''
         
        #测试用户登录
        def user_login_verify(self,username = "",password = ""): 
            login(self.driver).user_login(username,password)
             
        def test_login1(self):
            '''用户名、密码为空'''
            self.user_login_verify()
            po = login(self.driver)
            self.assertEqual(po.user_error_hint(),'请输入登录用户名')    
            print(po.user_error_hint())
            sleep(1)
    #         '''单个截图'''
    #         screen_name = 'insert_img/' + '\\' + time.strftime("%Y-%m-%d %H_%M_%S")
    #         self.driver.get_screenshot_as_file(str(screen_name ) + "请输入登录用户名.jpg")
            u"""封装函数截图"""
            function.insert_img(self.driver,"用户名和密码为空.jpg")
      
        def test_login2(self):
            '''用户名正确、密码为空'''
            self.user_login_verify(username='a2036')
            po = login(self.driver)
            self.assertEqual(po.pawd_error_hint(),'请输入密码')       
            print(po.pawd_error_hint())
            sleep(1)
            function.insert_img(self.driver,"用户名正确-密码为空.jpg") 
                           
        def test_login3(self):
            '''用户名为空、密码正确'''
            self.user_login_verify(password ='123456')
            po = login(self.driver)
            self.assertEqual(po.user_error_hint(),'请输入登录用户名')      
            print(po.user_error_hint())
            sleep(1)
            function.insert_img(self.driver,"用户名为空-密码正确.jpg")
                    
        def test_login4(self):
            '''用户名和密码不匹配'''
            character = random.choice('zyxwvutsrqponmlkjihgfedcba')
            user_name = 'zhangsan' + character
            self.user_login_verify(username=user_name,password ='123456')
            sleep(2)
            po = login(self.driver)
            self.assertEqual(po.user_pawd_error_hint(),'该用户不存在\n\n联系 contact@cnblogs.com')
            print(po.user_pawd_error_hint())
            sleep(1)
            function.insert_img(self.driver,"用户名和密码不匹配.jpg")
              
        def test_login5(self):
            '''用户名、密码正确登录'''
            self.user_login_verify(username='a2036', password ='20A3d4p43W36#20')
            sleep(1)
            po = login(self.driver)
            sleep(1)
            self.assertEqual(po.user_login_success(),'a2036')
            print(po.user_login_success())
            function.success_img(self.driver,"登录成功.jpg")
             
    if __name__ == '__main__':
        unittest.main()
    

    Send_mail_report.py

    发送邮件包含测试报告、邮件标题、邮件正文,附件(图片、PDF)
    '''
    @author: Yvon_早安阳光
    '''
    import unittest,time,os,smtplib
    from HTMLTestRunner import HTMLTestRunner
    from email.mime.multipart import MIMEMultipart
    from email.header import Header
    from email.mime.application import MIMEApplication
    from email.mime.text import MIMEText
    #======================定义发送邮件======================
    def send_mail(file_new):
        #测试报告
        '''file_new是指最新的测试报告'''
        f = open(file_new,'rb')
        mail_body = f.read()
        f.close()
         
        msg = MIMEMultipart()
        '''邮件标题'''
        msg['Subject'] = Header('博客园登录测试报告' ,'utf-8')
         
        '''邮件正文'''
        zhengwen = "各位,详情测试结果请见附件文档"
        msg.attach(MIMEText(zhengwen, 'plain')) 
         
        '''附件测试报告 '''
        att= MIMEText(mail_body,'html','utf-8')
        att.add_header('Content-Disposition', 'attachment', filename='New_TestReport.html')
        msg.attach(att)
         
        '''附件图片'''
        jpgpart = MIMEApplication(open('fujian/测试计划.jpg','rb').read())
        jpgpart.add_header('Content-Disposition', 'attachment', filename='测试计划.jpg')
        msg.attach(jpgpart)
         
        '''附件PDF'''
        pdfpart = MIMEApplication(open('fujian/功能需求.pdf','rb').read())
        pdfpart.add_header('Content-Disposition', 'attachment', filename='功能需求.pdf')
        msg.attach(pdfpart)
     
        #发送邮件
        smtp = smtplib.SMTP()
        smtp.connect('smtp.exmail.qq.com')
        smtp.login('fajin@bertadata.com','36#20qa20A')
        smtp.sendmail('fajin@bertadata.com','huiselanse@yeah.net',msg.as_string())
        print('email has send out !')
        smtp.quit()
    #======================查找测试报告的目录,找到最新生成的测试报告======================
    def new_report(testreport):
        lists = os.listdir(testreport)
        lists.sort(key = lambda fn: os.path.getatime(testreport + '\\' + fn))
        file_new = os.path.join(testreport,lists[-1])
        print(file_new)
        return file_new
     
    if __name__ == '__main__':
        #指定测试用例为当前文件夹下的目录
        test_dir = './'
        discover = unittest.defaultTestLoader.discover(test_dir, pattern='login_sta*.py')
        
        #定义报告存放的路径
        result_report_dir= 'result_report/'
        '''实时当前的时间'''
        now = time.strftime("%Y-%m-%d %H_%M_%S")
        file_name = result_report_dir + '\\' + now +'result.html'
        fp = open(file_name,'wb')    
        #定义测试报告
        runner =HTMLTestRunner(stream = fp,title ='自动化测试报告',
                               description='用例执行情况:')
        runner.run(discover)
        fp.close() #关闭报告文件
         
        new_report = new_report(result_report_dir)
        send_mail(new_report)
    

    脚本目录

    1.本地文件目录.png
    2.图片和文档附件存放目录.png
    3.测试用例测试结果截图目录.png
    4.测试报告目录.png
    5.登录成功附件目录.png
    6.邮件接收附件和测试报告.png
    7.自动化详细测试报告.png

    相关文章

      网友评论

          本文标题:Web端自动化测试--Python+selenium+unitt

          本文链接:https://www.haomeiwen.com/subject/fyemtltx.html