• PageObjects设计模式


    先来一张图,看看整个Po架构的实现:

    operatePages:操作页面,也就是把每一个操作页面,写成一个类。

    pages:用来存放公共配置文件的一个目录。比如基础类,后续所有类都会用到基础类。

    reports:用来存放生成的测试报告。

    testCases:用例存放目录。用来存放测试用例的目录。

    1.我们先看page类的实现

    from selenium.webdriver.support.wait import WebDriverWait
    #from selenium.webdriver.support import expected_conditions as EC
    #页面基类
    class HomePage():
        #初始化页面属性
        def __init__(self,url,driver):
            self.url = url
            self.dr = driver
    
        #封装元素定位方式
        def find_element(self,*loc):
            ###----- 确保元素是可见的。
            try:
                #以下入参本身是元组,不需要加*
                #WebDriverWait(self.dr,20).until(EC.visibility_of_element_located(loc))
                #以下入参为元组的元素,需要加*
                WebDriverWait(self.dr,20).until(lambda dr:dr.find_element(*loc).is_displayed())
                return self.dr.find_element(*loc)
            except:
                print(*loc+"元素在页面中未找到!")
        

    整个page类中,我们队浏览器的驱动和地址进行了初始化动作,因为后续的用例在执行时都会使用该方法。

    在基础类Homepage类中,我们把元素定位的方法进行了改写,后续的所有元素定位都可以使用基础类中的find_element方法。

    二、我们针对登陆页面写一个类,该类继承继承类的一些属性和方法,下面我们来看整个类的实现:

    from selenium.webdriver.common.by import By
    from time import sleep
    import sys
    
    sys.path.append("../pages/")
    from homePage import *
    
    class LoginPage(HomePage):
        #元素定位器,定位页面的元素
        #用户名
        username_loc = (By.ID,"mobilePhone")
        #密码
        passwd_loc = (By.ID,"password")
        #登陆按钮
        loginBtn_loc = (By.CSS_SELECTOR,"a.btn.btn-block.fs-16")
        #退出链接
        logoutBtn_loc = (By.CSS_SELECTOR,"a.fc-blue.mr-5")
        #用户名为空的提示信息
        userNull_loc = (By.CSS_SELECTOR,"#error > span")
        #密码为空的提示信息
        passWordNull_loc = (By.CSS_SELECTOR,"#error > span")
    
        #打开登陆页面
        def openLoginPage(self):
            self.dr.get(self.url)
            sleep(0.5)
            self.dr.refresh()
            self.dr.maximize_window()
            sleep(0.05)
        #操作元素
        #输入用户名
        def input_userName(self,userName):
            self.find_element(*self.username_loc).send_keys(userName)
        #输入密码
        def input_passWord(self,passWord):
            self.find_element(*self.passwd_loc).send_keys(passWord)
        #点击登陆按钮
        def click_loginBtn(self):
            self.find_element(*self.loginBtn_loc).click()
        #获取登陆成功后的提示信息
        def get_assertText(self):
            return self.find_element(*self.logoutBtn_loc).text
        #用户名为空的提示信息
        def get_userNullText(self):
            return self.find_element(*self.userNull_loc).text
        #密码为空的提示信息
        def get_passWordNullText(self):
            return self.find_element(*self.passWordNull_loc).text

    1.operatepages类继承的是Homepage基础类;

    2.我们在登陆页面,我们把所有的登陆页面需要操作的方法都封装成方法,好处是可以方便用例层去调用。类似模块的作业,当调用时可以直接传递对应的参数就好了。。

    3.封装断言文本信息方法 比如  登陆成功后的信息、用户名为空的信息、密码为空的情况 

    三、testLogin.py文件实现代码:

    from selenium import webdriver
    from time import sleep
    import unittest,sys
    
    sys.path.append("../operatePages/")
    sys.path.append("../pages/")
    sys.path.append("./")
    from operateLoginPage import *
    from homePage import *
    
    #导入xlrd模块
    import xlrd
    #1、打开excel
    data = xlrd.open_workbook(r"E:untitled	estCases参数化数据.xlsx")
    #读取用户名和密码所在的页面的数据
    sheet1 = data.sheet_by_index(0)
    #获取用户名
    userNames = sheet1.col_values(0)
    #获取密码
    passWords = sheet1.col_values(1)
    #获取预期结果
    exceptResults = sheet1.col_values(2)
    
    class TestLogin(unittest.TestCase):
        def setUp(self):
            self.url = "https://www.gjfax.com/toLogin"
            self.dr = webdriver.Chrome()
            self.dr.implicitly_wait(20)
            #实例化一个operateLoginPage类的对象
            self.loginPage = LoginPage(self.url,self.dr)
            
        #测试正常登陆
        def testLogin(self):
            #打开登陆页面
            self.loginPage.openLoginPage()
            #输入用户名
            self.loginPage.input_userName(userNames[1])
            #输入密码
            self.loginPage.input_passWord(passWords[1])
            #点击登陆
            self.loginPage.click_loginBtn()
            #断言
            self.assertEqual(exceptResults[1],self.loginPage.get_assertText())
            
        #测试用户名为空
        def test_user_null(self):
            #打开登陆页面
            self.loginPage.openLoginPage()
            #输入用户名
            self.loginPage.input_userName(userNames[2])
            #输入密码
            self.loginPage.input_passWord(passWords[2])
            #点击登陆
            self.loginPage.click_loginBtn()
            #断言
            self.assertEqual(exceptResults[2],self.loginPage.get_userNullText())
    
        #测试密码为空
        def test_password_null(self):
            #打开登陆页面
            self.loginPage.openLoginPage()
            #输入用户名
            self.loginPage.input_userName(userNames[3])
            #输入密码
            self.loginPage.input_passWord(passWords[3])
            #点击登陆
            self.loginPage.click_loginBtn()
            #断言
            self.assertEqual(exceptResults[3],self.loginPage.get_passWordNullText())
            
        def tearDown(self):
            self.dr.quit()
    
    if __name__=="__main__":
        unittest.main()

    四、总执行文件:

    import unittest
    from HTMLTestRunner import HTMLTestRunner
    import time
    
    import sys
    #临时改变工作路径
    sys.path.append("./operatePages/")
    sys.path.append("./pages/")
    from operateLoginPage import *
    from homePage import *
    
    if __name__ == "__main__":
        #定义测试用例所在的路径
        casesPath = "./testCases/"
        #定义测试报告所在的路径
        reportPath = "./reports/"
        #定义测试报告的名称
        reportName = time.strftime("%Y-%m-%d %H%M%S",time.localtime()) + '.html'
        #定义测试报告所在的路径和名称
        reportPathName = reportPath + reportName
        #把测试用例组装到unittest的discover容器
        discover = unittest.defaultTestLoader.discover(casesPath,"*.py")
        #打开测试报告,并赋予读写权限
        fp = open(reportPathName,"wb")
        #把测试结果写进测试报告,并装载到HTHMLTestRunner模块
        run = HTMLTestRunner(stream=fp,title="ecshop自动化测试报告",description="用例执行情况")
        #运行脚本
        run.run(discover)
        #关闭打开的测试报告
        fp.close()

    纯文本邮件:

    #!/usr/bin/python3
     
    import smtplib
    from email.mime.text import MIMEText
    from email.header import Header
     
    # 第三方 SMTP 服务
    mail_host="smtp.qq.com"  #设置服务器
    mail_user="xxxxx@qq.com"    #用户名
    mail_pass="ctludyhhtzecbggg"   #口令 
     
     
    sender = 'xxxxx@qq.com'
    receivers = ['xxxx@163.com']  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
     
    message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
    message['From'] = Header("xxx自动化提升班", 'utf-8')
    message['To'] =  Header("测试", 'utf-8')
     
    subject = 'xxxx自动化提升班 -- 邮件发送测试'
    message['Subject'] = Header(subject, 'utf-8')
     
     
    try:
        smtpObj = smtplib.SMTP() 
        smtpObj.connect(mail_host)
        smtpObj.login(mail_user,mail_pass)
        smtpObj.sendmail(sender, receivers, message.as_string())
        print ("邮件发送成功")
    except smtplib.SMTPException:
        print ("无法发送邮件")

    带附件邮件:

    from HTMLTestRunner import HTMLTestRunner
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from email.header import Header
    import smtplib
    import unittest
    import time
    import os
    
    import sys
    sys.path.append("./operatePages/")
    sys.path.append("./pages/")
    
    #定义发送邮件
    def send_mail(file_new,fileName):
        f = open(file_new, 'rb').read()
        att = MIMEText(f, 'base64', 'utf-8')
        #att = MIMEText(f, 'plain', 'utf-8')
        att["Content-Type"] = 'application/octet-stream'
        #附件名称
        att["Content-Disposition"] = 'attachment;filename='+fileName
        msgRoot = MIMEMultipart("related")
        #邮件标题
        msgRoot['Subject'] = Header('ECSHOP自动化测试报告', 'utf-8')
        msgRoot['from'] = 'xxxx@qq.com'
        msgRoot['to'] = 'xxxxx@163.com'
        #msgRoot['from'] = '发送邮件的邮箱用户名'
        #msgRoot['to'] = '接收邮件的邮箱用户名'
        msgRoot.attach(att)
    
        #使用QQ邮箱进行邮件发送
        try:
            smtp = smtplib.SMTP()
            smtp.connect('smtp.qq.com',25)
            smtp.login('xxxxx@qq.com', 'ctludyhhtzecbggg')
            smtp.sendmail('xxxxxxxxxx@qq.com', 'xxxxx@163.com', msgRoot.as_string())
            #smtp.login('发送邮件的邮箱用户名', '邮箱的登录密码')
            #smtp.sendmail('发送邮件的邮箱用户名', '接收邮件的邮箱用户名', msgRoot.as_string())
            smtp.quit()
            print("邮件发送成功!")
        except:
            print("邮件发送失败!")
    
    #查找目录
    def new_report(testreport):
        lists = os.listdir(testreport)
        lists.sort(key=lambda fn : os.path.getmtime(testreport + "\" + fn))
        file_new = os.path.join(testreport,lists[-1])
        print(file_new)
        return file_new
    
    if __name__ == '__main__':
        #定义测试用例的存放路径
        test_dir = "./testCases/"
        #把测试用例加入 discover 容器
        discover = unittest.defaultTestLoader.discover(start_dir=test_dir,pattern='*.py')
    
        #定义测试报告的存放路径
        testReportDir = "./reports/"
        #定义测试报告的名字
        nowTime = time.strftime("%Y-%m-%d%H%M%S", time.localtime())
        fileName = nowTime+".html"
        #定义测试路径和测试报告名字
        testReportDir_FileName = testReportDir + fileName
    
        #打开文件,并赋予可写权限
        fp = open(testReportDir_FileName,"wb")
        #把测试结果写进测试报告,并装载到HTHMLTestRunner模块
        runner = HTMLTestRunner(stream = fp ,title = "ERP自动化测试报告",description="用例执行情况:")
        #运行测试用例
        runner.run(discover)
        #关闭文件
        fp.close()
    
        #发送邮件
        new_report = new_report(testReportDir)
        send_mail(new_report,fileName)

    整个架构图:

    operatePages:操作页面,也就是把每一个操作页面,写成一个类。

    pages:用来存放公共配置文件的一个目录。比如基础类,后续所有类都会用到基础类。

    reports:用来存放生成的测试报告。

    testCases:用例存放目录。用来存放测试用例的目录。

  • 相关阅读:
    Java基础面试操作题: 线程问题,写一个死锁(原理:只有互相都等待对方放弃资源才会产生死锁)
    Java基础面试操作题: File IO 文件过滤器FileFilter 练习 把一个文件夹下的.java文件复制到另一个文件夹下的.txt文件
    Java基础面试操作题:Java代理工厂设计模式 ProxyFactory 有一个Baby类,有Cry行为,Baby可以配一个保姆 但是作为保姆必须遵守保姆协议:能够处理Baby类Cry的行为,如喂奶、哄睡觉。
    Java中 Character方法练习:字符串中英文字母个数 5435abc54abc3AHJ5 正则:matches("[a-zA-Z0-9]{1}")
    Java 练习:字符串反转
    集合类别
    JAVA 后台
    micro focus cobol vs mainframe cobol
    Java 编码
    关于java中char占几个字节,汉字占几个字节
  • 原文地址:https://www.cnblogs.com/fighter007/p/9505723.html
Copyright © 2020-2023  润新知