• selenium+python学习总结


    学习了一个月的selenium+python,终于学有所成,下面以一个简单的项目来总结学习所得。

            1.         项目结构

     

             在项目结构中,大家要注意到:每一个源文件夹中都要有一个__init__.py文件,确记,这是规定,不解析。

             先简单解说一下项目结构:

    1)         config源文件夹,这个主要存放一些配置文件,如里面的golobalparameter.py就是存放一些公共参数的,我这个文件里面主要把一些文件存放的路径写成了公共参数,这样子,要修改路径的时候直接打开这个文件就可以修改,而不用一个个文件地找参数。

    2)         data文件夹,是个普通的文件夹,里面存放了测试数据excel文件;

    3)         error_img文件夹,一样是普通的文件夹,测试过程中如果发生异常,通过代码可以自动截图然后把图片存放到error_img文件夹中。

    4)         log文件夹,也是普通文件夹,用于存放测试过程中输出的日志文件,这个日志文件是一次生成然后不断写入的,一旦生成了log.log文件,那么不管你执行多少次测试,输出了多少日志,都会写入一个log.log文件中。当然,如果把log.log删除之后,执行测试的时候也会再次生成的。

    5)         report文件夹,也是普通的文件夹,用于存放最后生成的.html测试报告;

    6)         src源文件夹,这个源文件夹下包含了两子源文件夹,一个是common源文件夹,用于存放一些公共类;另一个是test_case源文件夹,用于存放各测试模块的代码。

    7)         runtest.py文件,用于执行测试。

    8)         runner.bat文件,是用于设置windows定时执行测试任务所要用到的的cmd命令,因为我后来用了jenkins来做定时任务,所以可以不管。

     2.         项目所有代码文件

    1)         globalparameter.py

    # coding:utf-8
    __author__ = 'helen'
    import time
    '''
    配置全局参数
    '''
    # 项目的绝对路径(因为 windows执行时需要绝对路径才能执行通过)
    project_path = "D:\for2017\SPframework-Helen\"
    # 测试用例代码存放路径(用于构建suite,注意该文件夹下的文件都应该以test开头命名)
    test_case_path = project_path+"src\test_case"
    # 日志文件存储路径
    log_path = project_path+"log\mylog.log"
    # 测试报告存储路径,并以当前时间作为报告名称前缀
    report_path = project_path+"report\"
    report_name = report_path+time.strftime('%Y%m%d%H%S', time.localtime())
    # 异常截图存储路径,并以当前时间作为图片名称前缀
    img_path = project_path+"error_img\"+time.strftime('%Y%m%d%H%S', time.localtime())
    # 设置发送测试报告的公共邮箱、用户名和密码
    smtp_sever = 'smtp.xxxx.com'  # 邮箱SMTP服务,各大运营商的smtp服务可以在网上找,然后可以在foxmail这些工具中验正
    email_name = "li***@gpdi.com"  # 发件人名称
    email_password = "*****"  # 发件人登录密码
    email_To = '50****@qq.com;5*****016@qq.com;h****@163.com'  # 收件人

    2)         excel_data.py

    # coding:utf-8
    __author__ = 'helen'
    import xlrd
    from src.common import log
    '''
    读取excel文件
    '''


    class excel:
        def __init__(self):
            self.mylog = log.log()

        def open_excel(self,file):
            try:
                data = xlrd.open_workbook(file)
                return data
            except Exception, e:
                self.mylog.error(u"打开excel文件失败")

        def excel_table(self,file, sheetName):
            data = self.open_excel(file)
            # 通过工作表名称,获取到一个工作表
            table = data.sheet_by_name(sheetName)
            # 获取行数
            Trows = table.nrows
            # 获取 第一行数据
            Tcolnames = table.row_values(0)
            lister = []
            for rownumber in range(1,Trows):
                row = table.row_values(rownumber)
                if row:
                    app = {}
                    for i in range(len(Tcolnames)):
                        app[Tcolnames[i]] = row[i]
                        lister.append(app)
            return lister

    3)         log.py

    # coding:utf-8
    __author__ = 'helen'
    import logging
    from config import globalparameter
    '''
    配置日志文件,输出INFO级别以上的日志
    '''


    class log:
        def __init__(self):
            self.logname = "mylog"

        def setMSG(self, level, msg):
            # 之前把下面定义log的一大段代码写在了__init__里面,造成了日志重复输出
            # 此大坑,谨记谨记!!!!
            logger = logging.getLogger()
            # 定义Handler输出到文件和控制台
            fh = logging.FileHandler(globalparameter.log_path)
            ch = logging.StreamHandler()
            # 定义日志输出格式
            formater = logging.Formatter("%(asctime)s %(levelname)s %(message)s' ")
            fh.setFormatter(formater)
            ch.setFormatter(formater)
            # 添加Handler
            logger.addHandler(fh)
            logger.addHandler(ch)
            # 添加日志信息,输出INFO级别的信息
            logger.setLevel(logging.INFO)
            if level=='debug':
                logger.debug(msg)
            elif level=='info':
                logger.info(msg)
            elif level=='warning':
                logger.warning(msg)
            elif level=='error':
                logger.error(msg)
            # 移除句柄,否则日志会重复输出
            logger.removeHandler(fh)
            logger.removeHandler(ch)
            fh.close()

        def debug(self, msg):
            self.setMSG('debug', msg)

        def info(self, msg):
            self.setMSG('info', msg)

        def warning(self, msg):
            self.setMSG('warning', msg)

        def error(self, msg):
            self.setMSG('error', msg)

    4)         send_email.py

    # coding:utf-8
    __author__ = 'helen'
    import os,smtplib
    from config import globalparameter
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from src.common import log
    '''
    邮件发送最新的测试报告
    '''


    class send_email:
        def __init__(self):
            self.mylog = log.log()

        # 定义邮件内容
        def email_init(self,report,reportName):
            with open(report,'rb')as f:
                mail_body = f.read()

            # 创建一个带附件的邮件实例
            msg = MIMEMultipart()
            # 以测试报告作为邮件正文
            report_file = MIMEText(mail_body,'html','utf-8')
            # 定义附件名称(附件的名称可以随便定义,你写的是什么邮件里面显示的就是什么)
            report_file["Content-Disposition"] = 'attachment;filename='+reportName
            msg.attach(report_file) # 添加附件
            msg['Subject'] = '自动化测试报告' # 邮件标题
            msg['From'] = globalparameter.email_name  #发件人
            msg['To'] = globalparameter.email_To  #收件人列表
            try:
                server = smtplib.SMTP(globalparameter.smtp_sever)
                server.login(globalparameter.email_name,globalparameter.email_password)
                server.sendmail(msg['From'],msg['To'].split(';'),msg.as_string())
                server.quit()
            except smtplib.SMTPException:
                self.mylog.error(u'邮件发送测试报告失败 at'+__file__)

        def sendReport(self):
            # 找到最新的测试报告
            lists = os.listdir(globalparameter.report_path)
            report_list = sorted(lists)
            new_report = os.path.join(globalparameter.report_path,report_list[-1])
            # 发送邮件
            self.email_init(new_report,report_list[-1])

    5)         runtest.py

    # coding:utf-8
    __author__ = 'helen'
    import unittest,time,HTMLTestRunner
    from config import globalparameter
    from src.common import send_email
    '''
    构建测试套件,并执行测试
    '''


    # 构建测试集,包含src/test_case目录下的所有以test开头的.py文件
    suite = unittest.defaultTestLoader.discover(start_dir=globalparameter.test_case_path,pattern='test*.py')

    # 执行测试
    if __name__=="__main__":
        report_name = globalparameter.report_name+"Report.html"
        fb = open(report_name,'wb')
        runner = HTMLTestRunner.HTMLTestRunner(
            stream=fb,
            title=u'自动化测试报告',
            description=u'项目描述。………'
        )
        runner.run(suite)
        fb.close()
        # 发送邮件
        time.sleep(10)  # 设置睡眠时间,等待测试报告生成完毕(这里被坑了==)
        email = send_email.send_email()
        email.sendReport()

    6)         test_baidu.py

    # -*- coding: utf-8 -*-
    from selenium import webdriver
    from selenium.common.exceptions import NoAlertPresentException
    from selenium.webdriver.common.action_chains import ActionChains
    import unittest
    from config import globalparameter
    from src.common import excel_data, log
    '''
    百度页面相关测试用例
    '''


    class TestBaidu(unittest.TestCase):
        def setUp(self):
            self.driver = webdriver.Firefox()
            self.driver.implicitly_wait(30)
            self.base_url = "https://www.baidu.com/"
            self.verificationErrors = []
            self.accept_next_alert = True
            self.mylog = log.log()
            self.excel = excel_data.excel()
       
        def test_baidu_search(self):
            u'''百度搜索功能测试'''
           
    driver = self.driver
            listdata = self.excel.excel_table("D:\for2017\SPframework-Helen\data\baidu.xlsx","search")
            print(len(listdata))
            if (len(listdata)<=0):
                self.mylog.error(u"读取excel参数异常,参数列表小于等于0")
                assert 0,u"读取excel参数异常,参数列表小于等于0"
            for i in range(0,len(listdata)):
                try:
                    driver.get(self.base_url + "/")
                    driver.find_element_by_id("kw").clear()
                    driver.find_element_by_id("kw").send_keys(listdata[i]["keyword"])
                    driver.find_element_by_id("su").click()
                    URL_title = driver.title
                    self.assertEqual(URL_title, listdata[i]['keyword']+u"_百度搜索", u"搜索失败")
                    self.mylog.info(u'百度搜索成功 '+__file__)
                except:
                    driver.get_screenshot_as_file(globalparameter.img_path+"test_baidu.png")
                    self.mylog.error(u"百度搜索失败"+__file__)

        def test_baidu_changeTo_hao123(self):
            u'''测试从百度首页跳转到hao123网站'''
           
    driver = self.driver
            try:
                driver.get(self.base_url+"/")
                driver.find_element_by_link_text("hao123").click()
                self.assertEqual(driver.current_url,"https://www.hao123.com/")
                self.mylog.info(u'从百度成功跳转到hao123网站')
            except:
                driver.get_screenshot_as_file(globalparameter.img_path+"test_baidu_changeTo_hao123.png")
                self.mylog.error(u'从百度跳转到hao123网站失败')

        def test_baidu_more(self):
            u'''打开百度产品大全页面'''
           
    driver = self.driver
            try:
                driver.get(self.base_url+"/")
                mouse = driver.find_element_by_link_text(u"更多产品")
                ActionChains(driver).move_to_element(mouse).perform()
                driver.find_element_by_link_text(u"全部产品>>").click()
                self.assertEqual(driver.current_url,"https://www.baidu.com/more/")
                self.mylog.info(u'打开百度产品页面成功')
            except:
                driver.get_screenshot_as_file(globalparameter.img_path+"test_baidu_more.png")
                self.mylog.error(u'打开百度产品页面失败')

        def is_alert_present(self):
            try: self.driver.switch_to_alert()
            except NoAlertPresentException as e: return False
            return True
       
        def close_alert_and_get_its_text(self):
            try:
                alert = self.driver.switch_to_alert()
                alert_text = alert.text
                if self.accept_next_alert:
                    alert.accept()
                else:
                    alert.dismiss()
                return alert_text
            finally: self.accept_next_alert = True
       
        def tearDown(self):
            self.driver.close()
            self.assertEqual([], self.verificationErrors)

    if __name__ == "__main__":
        unittest.main()

    7)         test_sogo.py

    # -*- coding: utf-8 -*-
    from selenium import webdriver
    from selenium.common.exceptions import NoAlertPresentException
    import unittest,time
    from src.common import log
    from config import globalparameter
    '''
    搜狗页面相关测试
    '''


    class TestSogo(unittest.TestCase):
        def setUp(self):
            self.driver = webdriver.Firefox()
            self.driver.implicitly_wait(30)
            self.base_url = "https://www.sogou.com/"
            self.verificationErrors = []
            self.accept_next_alert = True
            self.mylog = log.log()
       
        def test_sogo(self):
            u'''搜狗搜索功能测试'''
           
    try:
                driver = self.driver
                driver.get(self.base_url + "/")
                driver.find_element_by_id("query").clear()
                driver.find_element_by_id("query").send_keys("selenium")
                driver.find_element_by_id("query").submit()
                time.sleep(5)
                self.assertEqual(driver.title, u"selenium - 搜狗搜索", u"sogo搜索模块出错")
                self.mylog.info(u"sogo搜索模块成功 "+__file__)
            except:
                driver.get_screenshot_as_file(globalparameter.img_path+"test_sogo.png")
                self.mylog.error(u"sogo搜索模块失败 "+__file__)

        def is_alert_present(self):
            try: self.driver.switch_to_alert()
            except NoAlertPresentException as e: return False
            return True
       
        def close_alert_and_get_its_text(self):
            try:
                alert = self.driver.switch_to_alert()
                alert_text = alert.text
                if self.accept_next_alert:
                    alert.accept()
                else:
                    alert.dismiss()
                return alert_text
            finally: self.accept_next_alert = True
       
        def tearDown(self):
            self.driver.close()
            self.assertEqual([], self.verificationErrors)

    if __name__ == "__main__":
        unittest.main()

     3.         使用jenkins设置定时执行测试任务

             这个傻瓜式配置即可,不写了。

  • 相关阅读:
    vue axios接口封装、Promise封装、简单的axios方法封装、vue接口方法封装、vue post、get、patch、put方法封装
    vue-router 报错、:Avoided redundant navigation to current location 错误、路由重复
    微信小程序支付、小程序支付功能、小程序支付方法、微信小程序支付方法
    微信小程序热更新,小程序提示版本更新,版本迭代,强制更新,微信小程序版本迭代
    微信小程序动态修改title,动态配置title,动态配置头部,微信小程序动态配置头部
    响应式布局rem、rem方法封装、移动端响应式布局
    jquery 选项卡切换、选项卡封装、简单的jquery选项卡封装、tab切换效果
    js获取url并截取相应的字段,js解决url获取中文字段乱码问题
    微信小程序接口封装、原生接口封装、request、promise封装
    20193327《Python程序设计》实验报告三
  • 原文地址:https://www.cnblogs.com/helenMemery/p/6230284.html
Copyright © 2020-2023  润新知