自动化测试-数据驱动实践(登录)

测试流程:
1、账号密码手动写入Excel中
2、使用ddt读取Excel中的账号密码
3、使用unittest进行单元测试,登录公司某个系统
4、断言是否用例是否执行成功(登录成功判断页面中是否有“退出”,登录失败的判断页面提示是否正确)
5、最后生成HTML测试报告

在本地磁盘D:\test\DataDrivenTesting目录中新建一个“登录测试.xlsx”,工作表名为“账号密码”,内容如下:
序号  账号           密码           期望结果
1     chenyl1      a123456      退出
2     chenyl2      a123456      退出
3     chenyl3      a123456      退出
4     chenyl4      a123456      退出
5     chenyl4                          请输入密码
6                        a123456      请输入用户名
7                                            请输入用户名
8     abc1234      a123456     该用户不存在
9     chenyl1       xx112233     密码错误
10    acbd123    1123aaxx     该用户不存在


在PyCharm中创建MyLoginProject的Python工程,并在工程下创建以下文件:ExcelUtil.py ,ReportTemplate.py,MyLoginDataDrivenByExcel.py
ExcelUtil.py文件用于编写读取Excel的脚本,具体内容如下:

#encoding=utf-8
from openpyxl import load_workbook

class ParseExcel(object):

    def __init__(self, excelPath, sheetName):
        # 将要读取的excel加载到内存
        self.wb = load_workbook(excelPath)
        # 通过工作表名称获取一个工作表对象
        self.sheet = self.wb.get_sheet_by_name(sheetName)
        # 获取工作表中存在数据的区域的最大行号
        self.maxRowNum = self.sheet.max_row

    def getDatasFromSheet(self):
        # 用于存放从工作表中读取出来的数据
        dataList = []
        for line in self.sheet.rows:
            # 遍历工作表中数据区域的每一行,
            # 并将每行中各个单元格的数据取出存于列表tmpList中,
            # 然后再将存放一行数据的列表添加到最终数据列表dataList中
            tmpList = []
            #如果单元格为空,则在列表中插入一个为空的unicode字符串,以免输入账号密码时报错
            if line[1].value == None:
                tmpList.append(u"")
            else:
                tmpList.append(line[1].value)
            if line[2].value == None:
                tmpList.append(u"")
            else:
                tmpList.append(line[2].value)
            tmpList.append(line[3].value)
            dataList.append(tmpList)
        # 将获取工作表中的所有数据的迭代对象返回
        # 因为工作表中的第一行是标题行,所以需要去掉
        return dataList[1:]

if __name__ == '__main__':
    excelPath = u'D:\\test\\DataDrivenTesting\\登录测试.xlsx'
    sheetName = u"账号密码"
    pe = ParseExcel(excelPath, sheetName)
    print pe.getDatasFromSheet()
    for i in pe.getDatasFromSheet():
        print i[0],type(i[0])
        #i[1],i[2]

  文件ReportTemplate.py用于生成自定义HTML测试报告,具体内容如下:

# encoding=utf-8

def htmlTemplate(url, trData):
    htmlStr = u'''<!DOCTYPE HTML>
    <html>
    <head><meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>单元测试报告</title>
    <style>
    body {
        width: 80%; /*整个body区域占浏览器的宽度百分比*/
        margin: 40px auto; /*整个body区域相对浏览器窗口摆放位置(左右,上下)*/
        font-weight: bold; /*整个body区域的字体加粗*/
        font-family: 'trebuchet MS', 'Lucida sans', SimSun; /*表格中文字的字体类型*/
        font-size: 18px; /*表格中文字字体大小*/
        color: #000; /*整个body区域字体的颜色*/
    }
    table {
        *border-collapse: collapse; /*合并表格边框*/
        border-spacing: 0;  /*表格的边框宽度*/
        width: 100%;     /*整个表格相对父元素的宽度*/
    }
    .tableStyle {
        /*border: solid #ggg 1px;*/
        border-style: outset; /*整个表格外边框样式*/
        border-width: 2px; /*整个表格外边框宽度*/
        /*border: 2px;*/
        border-color: blue; /*整个表格外边框颜色*/
    }
    .tableStyle tr:hover {
        background: rgb(173,216,230); /*鼠标滑过一行时,动态显示的颜色146,208,80*/
    }

    .tableStyle td,.tableStyle th {
        border-left: solid 1px rgb(146,208,80); /*表格的竖线颜色*/
        border-top: 1px solid rgb(146,208,80);  /*表格的横线颜色 */
        padding: 15px;                       /*表格内边框尺寸*/
        text-align: center;                   /*表格内容显示位置*/
    }
    .tableStyle th {
        padding: 15px;        /*表格标题栏,字体的尺寸*/
        background-color: rgb(146,208,80); /*表格标题栏背景颜色*/
        /*表格标题栏设置渐变颜色*/
        background-image: -webkit-gradient(linear, left top, left bottom, from(#92D050), to(#A2D668));
        /*rgb(146,208,80)*/
    }
    </style>
    </head>
    <body>
        <center><h1>测试报告</h1></center><br /><br /><br />

        <table class="tableStyle">
            <thead>
            <tr>
            <th>No</th>
            <th>Username</th>
            <th>Password</th>
            <th>Assert Words</th>
            <th>Start Time</th>
            <th>Waste Time(s)</th>
            <th>Status</th>
            </tr>
            </thead>'''
    endStr = u'''
        </table>
    </body>
    </html>'''
    # 拼接完整的测试报告HTML页面代码
    html = htmlStr + u"<b>测试网址: " + url + u"</b>" + trData + endStr
    #print html
    # 生成.html文件
    with open(u"D:\\test\\DataDrivenTesting\\testTemplate.html", "w") as fp:
        fp.write(html.encode("gbk"))

  MyLoginDataDrivenByExcel.py用于编写数据驱动测试脚本,具体内容如下:

#encoding=utf-8
from selenium import webdriver
import unittest,time,os
import logging,traceback
import ddt
from ExcelUtil import ParseExcel
from ReportTemplate import htmlTemplate
from selenium.common.exceptions import NoSuchElementException

# 初始化日志对象
logging.basicConfig(
    # 日志级别
    level=logging.INFO,
    # 日志格式
    # 时间、代码所在文件名、代码行号、日志级别名字、日志信息
    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
    # 打印日志的时间
    datefmt='%a, %Y-%m-%d %H:%M:%S',
    # 日志文件存放的目录(目录必须存在)及日志文件名
    filename='D:\\test\\DataDrivenTesting\\report.log',
    # 打开日志文件的方式
    filemode='w'
)

excelPath = u"D:\\test\\DataDrivenTesting\\登录测试.xlsx"
sheetName = u"账号密码"
#ParseExcel类的实例对象
excel = ParseExcel(excelPath,sheetName)

@ddt.ddt
class TestDemo(unittest.TestCase):
#公司地址保密,使用xxx代替 url
= "xxx" no = 0 @classmethod def setUpClass(cls): # 整个测试过程只被调用一次 TestDemo.trStr = "" def setUp(self): self.driver = webdriver.Ie(executable_path="D:\\IEDriverServer") status = None # 用于存放测试结果状态,失败'fail',成功'pass' flag = 0 # 数据驱动测试结果的标志,失败置0,成功置1 TestDemo.no += 1 @ddt.data(*excel.getDatasFromSheet()) def test_dataDrivenByFile(self, data): # 决定测试报告中状态单元格中内容的颜色 flagDict = {0: 'red', 1: '#00AC4E'} # 访问系统 self.driver.get(TestDemo.url) # 将浏览器窗口最大化 self.driver.maximize_window() #print data # 读取Excel中的账号密码及期望结果 username,password, expectdata = tuple(data) # 设置隐式等待时间为10秒 self.driver.implicitly_wait(10) try: # 获取当前的时间戳,用于后面计算查询耗时用 start = time.time() # 获取当前时间的字符串,表示测试开始时间 startTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) # 找到用户名输入框,并输入测试数据 self.driver.find_element_by_id("username").send_keys(username) # 找到密码输入框,并输入测试数据 self.driver.find_element_by_id("password").send_keys(password) # 找到登录按钮,并点击 self.driver.find_element_by_id("button").click() time.sleep(5) # 断言期望结果是否出现在页面源代码中 self.assertTrue(expectdata in self.driver.page_source) except NoSuchElementException, e: logging.error(u"查找的页面元素不存在,异常堆栈信息:" + str(traceback.format_exc())) status = 'fail' flag = 0 except AssertionError, e: logging.info(u"登录账号:“%s”,期望“%s”,失败" % (username, expectdata)) status = 'fail' flag = 0 except Exception, e: logging.error(u"未知错误,错误信息:" + str(traceback.format_exc())) status = 'fail' flag = 0 else: logging.info(u"登录账号:“%s”,期望“%s”通过" % (username, expectdata)) status = 'pass' flag = 1 # 计算耗时,从将测试数据输入到输入框中到断言期望结果之间所耗时 wasteTime = time.time() - start - 5 # 减去强制等待的3秒 # 每一组数据测试结束后,都将其测试结果信息插入表格行 # 的HTML代码中,并将这些行HTML代码拼接到变量trStr变量中, # 等所有测试数据都被测试结束后,传入htmlTemplate()函数中 # 生成完整测试报告的HTML代码 TestDemo.trStr += u''' <tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%.2f</td> <td style="color:%s">%s</td> </tr><br />''' % (TestDemo.no, username,password, expectdata, startTime, wasteTime, flagDict[flag], status) def tearDown(self): self.driver.quit() @classmethod def tearDownClass(cls): # 写自定义的html测试报告 # 整个测试过程只被调用一次 htmlTemplate(TestDemo.url, TestDemo.trStr) if __name__ == '__main__': unittest.main()

 

posted @ 2019-05-14 15:16  测试小子  阅读(601)  评论(0编辑  收藏  举报