zoukankan      html  css  js  c++  java
  • selenium实例:unittest框架+PO开发模式

    这是《selenium2+python学习总结》的升级版。

    1. 1.         项目结构

     

     

    1. 2.         项目代码

    1)         globalparameter.py

    # coding:utf-8
    __author__ = 'helen'
    import time,os
    '''
    配置全局参数
    '''
    # 项目的绝对路径(因为 windows执行时需要绝对路径才能执行通过)
    # project_path = "D:\for2017\SPframework-Helen_2.0\"
    # 获取项目路径
    project_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)[0]), '.'))
    print project_path
    # 测试用例代码存放路径(用于构建suite,注意该文件夹下的文件都应该以test开头命名)
    test_case_path = project_path+"\src\test_case"
    # excel测试数据文档存放路径
    test_data_path = project_path+"\data\testData.xlsx"
    # 日志文件存储路径
    log_path = project_path+"\log\mylog.log"
    print u'日志路径:'+log_path
    # 测试报告存储路径,并以当前时间作为报告名称前缀
    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 = 'mail.**.com'  # 邮箱SMTP服务,各大运营商的smtp服务可以在网上找,然后可以在foxmail这些工具中验正
    email_name = "SDS@**.com"  # 发件人名称
    email_password = "****"  # 发件人登录密码
    email_To = '5047**0@qq.com;54*0016@qq.com;hel**ter@163.com'  # 收件人

    2)         log.py

    # coding:utf-8
    __author__ = 'helen'
    import logging
    from config import globalparameter as gl
    '''
    配置日志文件,输出INFO级别以上的日志
    '''
    
    
    class log:
        def __init__(self):
            self.logname = "mylog"
    
        def setMSG(self, level, msg):
            # 之前把下面定义log的一大段代码写在了__init__里面,造成了日志重复输出
            # 此大坑,谨记谨记!!!!
            logger = logging.getLogger()
            # 定义Handler输出到文件和控制台
            fh = logging.FileHandler(gl.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)

    3)         send_mail.py

    # coding:utf-8
    __author__ = 'helen'
    import os,smtplib,os.path
    from config import globalparameter as gl
    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()
            # 以测试报告作为邮件正文
            msg.attach(MIMEText(mail_body,'html','utf-8'))
            report_file = MIMEText(mail_body,'html','utf-8')
            # 定义附件名称(附件的名称可以随便定义,你写的是什么邮件里面显示的就是什么)
            report_file["Content-Disposition"] = 'attachment;filename='+reportName
            msg.attach(report_file) # 添加附件
            msg['Subject'] = '自动化测试报告:'+reportName # 邮件标题
            msg['From'] = gl.email_name  #发件人
            msg['To'] = gl.email_To  #收件人列表
            try:
                server = smtplib.SMTP(gl.smtp_sever)
                server.login(gl.email_name,gl.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):
            # 找到最新的测试报告
            report_list = os.listdir(gl.report_path)
            report_list.sort(key=lambda fn: os.path.getmtime(gl.report_path+fn) if not os.path.isdir(gl.report_path+fn) else 0)
            new_report = os.path.join(gl.report_path,report_list[-1])
            # 发送邮件
            self.email_init(new_report,report_list[-1])

    4)         excel_data.py

    # coding:utf-8
    __author__ = 'helen'
    import xlrd
    from src.common import log
    from config.globalparameter import test_data_path
    '''
    读取excel文件
    '''
    
    
    class excel:
        def __init__(self):
            self.mylog = log.log()
    
        def open_excel(self,file):
            u'''读取excel文件'''
            try:
                data = xlrd.open_workbook(file)
                return data
            except Exception, e:
                self.mylog.error(u"打开excel文件失败")
    
        def excel_table(self,file, sheetName):
            u'''装载list'''
            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
    
        def get_list(self,sheetname):
            try:
                data_list = self.excel_table(test_data_path, sheetname)
                assert len(data_list)>=0,u'excel标签页:'+sheetname+u'为空'
                return data_list
            except Exception as e:
                self.mylog.error(u'excel标签页:'+sheetname+u'为空')
                raise e

    5)         Base_Page.py

    # coding:utf-8
    __author__ = 'helen'
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from src.common import log
    from config.globalparameter import img_path
    
    
    '''
    project:封装页面公用方法
    '''
    
    
    class BasePage(object):
        def __init__(self, selenium_driver, base_url, page_title):
            self.driver = selenium_driver
            self.url = base_url
            self.title = page_title
            self.mylog = log.log()
    
        #   打开页面,并校验链接是否加载正确
        def _open(self, url, page_title):
            try:
                self.driver.get(url)
                self.driver.maximize_window()
    #           通过断言输入的title是否在当前title中
                assert page_title in self.driver.title, u'打开页面失败:%s' % url
            except:
                self.mylog.error(u'未能正确打开页面:'+url)
    
        #   重写find_element方法,增加定位元素的健壮性
        def find_element(self, *loc):
            try:
                WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(loc))
                return self.driver.find_element(*loc)
            except:
                self.mylog.error(u'找不到元素:'+str(loc))
    
        #   重写send_keys方法
        def send_keys(self, value, clear=True, *loc):
            try:
                if clear:
                    self.find_element(*loc).clear()
                    self.find_element(*loc).send_keys(value)
            except AttributeError:
                self.mylog.error(u'输入失败,loc='+str(loc)+u';value='+value)
    
        #   截图
        def img_screenshot(self, img_name):
            try:
                self.driver.get_screenshot_as_file(img_path+img_name+'.png')
            except:
                self.mylog.error(u'截图失败:'+img_name)

    6)         baidu_page.py

    # coding:utf-8
    __author__ = 'helen'
    from selenium.webdriver.common.by import By
    from src.common.Base_Page import BasePage
    from selenium.webdriver.common.action_chains import ActionChains
    
    
    class BaiduPage(BasePage):
        # 定位器
        keywords_loc = (By.ID, 'kw')
        submit_loc = (By.ID, 'su')
        hao123_loc = (By.NAME, 'tj_trhao123')
        more_loc = (By.LINK_TEXT, u'更多产品')
        zhidao_loc = (By.NAME,'tj_zhidao')
    
        #   打开页面
        def open(self):
            self._open(self.url, self.title)
    
        #   输入关键词
        def input_keywords(self, keywords):
            self.find_element(*self.keywords_loc).send_keys(keywords)
    
        #   点击搜索按钮
        def click_submit(self):
            self.find_element(*self.submit_loc).click()
    
        #   点击hao123链接
        def click_hao123(self):
            self.find_element(*self.hao123_loc).click()
    
        #   鼠标悬停在"更多产品"上
        def ActionChains_more(self):
            mouse = self.find_element(*self.more_loc)
            ActionChains(self.driver).move_to_element(mouse).perform()
    
        #   点击“全部产品”
        def click_zhidao(self):
            self.find_element(*self.zhidao_loc).click()

    7)         test_baidu.py

    # coding:utf-8
    __author__ = 'helen'
    import unittest
    from selenium import webdriver
    from src.pages.baidu_page import BaiduPage
    from time import sleep
    '''
    project:百度页面测试
    '''
    
    
    class TestBaiduSearch(unittest.TestCase):
        def setUp(self):
            self.driver = webdriver.Firefox()
            self.url = 'https://www.baidu.com/'
            self.keyword = 'python'
            self.baidu_page = BaiduPage(self.driver, self.url, u'百度')
    
        def test_baidu_search(self):
            u'''百度搜索'''
            try:
                self.baidu_page.open()
                self.baidu_page.input_keywords(self.keyword)
                self.baidu_page.click_submit()
                sleep(2)
                self.assertIn(self.keyword, self.driver.title)
            except Exception as e:
                self.baidu_page.img_screenshot(u'百度搜索')
                raise e
    
        def test_baidu_changeto_hao123(self):
            u'''从百度首页打开hao123'''
            try:
                self.baidu_page.open()
                self.baidu_page.click_hao123()
                self.assertEqual(self.driver.current_url, 'https://www.hao123.com/')
            except Exception as e:
                self.baidu_page.img_screenshot(u'从百度首页打开hao123')
                raise e
    
        def test_baidu_more(self):
            u'''打开百度知道'''
            try:
                self.baidu_page.open()
                self.baidu_page.ActionChains_more()
                self.baidu_page.click_zhidao()
                self.assertEqual(self.driver.current_url, 'https://zhidao.baidu.com/')
            except Exception as e:
                self.baidu_page.img_screenshot(u'打开百度知道')
                raise e
    
        def tearDown(self):
            self.driver.close()

    8)         sogou_page.py

    # coding:utf-8
    __author__ = 'helen'
    from selenium.webdriver.common.by import By
    from src.common.Base_Page import BasePage
    '''
    project:sogo页面元素管理
    '''
    class sogou_page(BasePage):
        # 定位
        keyword_loc = (By.ID, 'query')
        sumit_loc = (By.ID, 'stb')
    
        def open(self):
            self._open(self.url,self.title)
    
        #   输入关键词
        def input_keyword(self, value):
            self.find_element(*self.keyword_loc).send_keys(value)
    
        #   点击搜索
        def click_sumit(self):
            self.find_element(*self.sumit_loc).click()

    9)         test_sogou.py

    # coding:utf-8
    __author__ = 'helen'
    import unittest
    from selenium import webdriver
    from src.pages.sogou_page import sogou_page
    from src.common.log import log
    from src.common import excel_data
    '''sogou页面测试
    '''
    
    
    class test_sogou(unittest.TestCase):
        def setUp(self):
            self.mylog = log()
            self.driver = webdriver.Firefox()
            self.url = 'https://www.sogou.com/'
            self.sogou_page = sogou_page(self.driver,self.url,u'搜狗')
            self.excel = excel_data.excel()
    
        def test_search(self):
            u'''搜狗搜索:excel数据驱动'''
            keyword_list = self.excel.get_list('sogou_search')
            for i in range(0, len(keyword_list)):
                keyword = keyword_list[i]["keyword"]
                try:
                    self.sogou_page.open()
                    self.sogou_page.input_keyword(keyword)
                    self.sogou_page.click_sumit()
                    # 因为assert对比是的str所以要判断keyword类型如何不是str, 就要进行转换
                    if type(keyword)!=str:
                        keyword = str(keyword)
                    self.assertIn(keyword,self.driver.title)
                except Exception as e:
                    self.mylog.error('error for search keyword:'+str(keyword))
                    self.sogou_page.img_screenshot(u'搜狗搜索')
                    raise e
    
        def tearDown(self):
            self.driver.close()
    if __name__=='__main__':
        unittest.main()

    10)         runtest.py

    # coding:utf-8
    __author__ = 'helen'
    import unittest,time,HTMLTestRunner
    from config.globalparameter import test_case_path,report_name
    from src.common import send_email
    '''
    构建测试套件,并执行测试
    '''
    
    
    # 构建测试集,包含src/test_case目录下的所有以test开头的.py文件
    suite = unittest.defaultTestLoader.discover(start_dir=test_case_path,pattern='test*.py')
    
    # 执行测试
    if __name__=="__main__":
        report = report_name+"Report.html"
        fb = open(report,'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()
  • 相关阅读:
    做正确的事,正确的做事
    博客园翻车启示录
    从一次线下读书会获得的收获
    坚持一个好习惯该有多难?
    有道云笔记
    Leetcode 10. 正则表达式匹配
    C++版
    VS 2013 professional版在win10上安装出错的解决方法
    华为校招2016.09机试 第1题: 字符串按指定长度重新分割
    C#版
  • 原文地址:https://www.cnblogs.com/helenMemery/p/6687669.html
Copyright © 2011-2022 走看看