测试自动化学习11

unittest框架
import unittest
import HTMLTestRunner
import parameterized
import BeautifulReport as bf  # 给导入的模块起别名


def calc(a,b):
    return a+b


# 1、正常,正数, 2、负数
# unitest执行时不是按照编顺序写从上到下执行,而是按照函数名排序执行

class CalcTestCase(unittest.TestCase):

    def testh2(self):
        print('test2')
        '''负数'''
        result = calc(-1,2)
        self.assertNotEqual(1,result) #不同

    def testh3(self):
        print('test3')
        '''负数'''
        result = calc(-1,3)
        self.assertEqual(1,result,msg='计算加法结果不正确,h3')#不通过

    def testh1(self):
        print('test1')
        '''正数'''
        result = calc(1,2)
        self.assertEqual(3,result,msg='计算加法结果不正确')


#运行当前文件所有的测试用例
# 1、 unittest.main()
#2、用testrunner运行测试用例才可以产生报告

suite = unittest.makeSuite(CalcTestCase)

#不好看的报告
# f = open('report.html','wb')
# runner = HTMLTestRunner.HTMLTestRunner(f,title='端午节测试报告',description='这个端午节的接口测试')
# runner.run(suite)

#下面是好看的报告
runner  = bf.BeautifulReport(suite)
runner.report('端午节测试报告','bf_report.html') # html文件在pycharm打开后,晃几下鼠标会在右上角显示用浏览器打开





# TestCase 测试用例
# TestSuite 测试套件,可以解决用例按照用例名顺序执行的问题,以及组织多个文件进行测试
# TestLoader 寻找并载入测试用例
# TestRunner 运行测试用例,顺便生成测试报告

 

 setUpClass和tearDownClass进行测试进行前和结束后进行一次操作,setUpClass用来为测试准备环境,tearDownClass用来清理环境,以备之后的测试(如连接数据库测试前备份一下数据库,测试完成后,将数据库直接还原,这样就可以不用重复造数据)。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest
 
 
class MyTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print '开始执行'
 
    @classmethod
    def tearDownClass(cls):
        print '结束执行'
 
    # 测试用例
    def test_case1(self):
        print '用例1'
 
    # 测试用例
    def test_case2(self):
        print '用例2'
 
if __name__ == '__main__':
    unittest.main()

 

testsuit测试套件

 

转自: https://www.cnblogs.com/eastonliu/p/9145255.html

在前面一章中示例了如何编写一个简单的测试,但有两个问题:

 

我们知道测试用例的执行顺序是根据测试用例名称顺序执行的,在不改变用例名称的情况下,我们怎么来控制用例执行的顺序呢?
一个测试文件,我们直接执行该文件即可,但如果有多个测试文件,怎么进行组织,总不能一个个文件执行吧?
要解决上面两个问题,我们就要用到测试套件(TestSuite)了

 

# coding = utf-8
import unittest
import warnings
from selenium import webdriver
from time import sleep
# 驱动文件路径
driverfile_path = r'D:\coship\Test_Framework\drivers\IEDriverServer.exe'

class CmsLoginTest(unittest.TestCase):
    def setUp(self):
        # 这行代码的作用是忽略一些告警打印
        warnings.simplefilter("ignore", ResourceWarning)
        self.driver = webdriver.Ie(executable_path=driverfile_path)
        self.driver.get("http://172.21.13.83:28080/")

    def tearDown(self):
        self.driver.quit()

    def test_login1(self):
        '''用户名、密码为空'''
        self.driver.find_element_by_css_selector("#imageField").click()
        error_message1 = self.driver.find_element_by_css_selector("[for='loginName']").text
        error_message2 = self.driver.find_element_by_css_selector("[for='textfield']").text
        self.assertEqual(error_message1, '用户名不能为空')
        self.assertEqual(error_message2, '密码不能为空')

    def test_login3(self):
        '''用户名、密码正确'''
        self.driver.find_element_by_css_selector("[name='admin.loginName']").send_keys("autotest")
        self.driver.find_element_by_css_selector("[name='admin.password']").send_keys("111111")
        self.driver.find_element_by_css_selector("#imageField").click()
        sleep(1)
        self.driver.switch_to.frame("topFrame")
        username = self.driver.find_element_by_css_selector("#nav_top>ul>li>a").text
        self.assertEqual(username,"autotest")

    def test_login2(self):
        '''用户名正确,密码错误'''
        self.driver.find_element_by_css_selector("[name='admin.loginName']").send_keys("autotest")
        self.driver.find_element_by_css_selector("[name='admin.password']").send_keys("123456")
        self.driver.find_element_by_css_selector("#imageField").click()
        error_message = self.driver.find_element_by_css_selector(".errorMessage").text
        self.assertEqual(error_message, '密码错误,请重新输入!')

    def test_login4(self):
        '''用户名不存在'''
        self.driver.find_element_by_css_selector("[name='admin.loginName']").send_keys("test007")
        self.driver.find_element_by_css_selector("[name='admin.password']").send_keys("123456")
        self.driver.find_element_by_css_selector("#imageField").click()
        error_message = self.driver.find_element_by_css_selector(".errorMessage").text
        self.assertEqual(error_message, '用户不存在!')


if __name__ == "__main__":
    # 构造测试套件
    suite = unittest.TestSuite()
    suite.addTest(CmsLoginTest("test_login1"))
    suite.addTest(CmsLoginTest("test_login2"))
    suite.addTest(CmsLoginTest("test_login4"))
    suite.addTest(CmsLoginTest("test_login3"))
    # 执行测试
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

注:verbosity 参数可以控制输出的错误报告的详细程度,默认是 1;如果设为 0,则不输出每一用例的执行结果;如果设为 2,则输出详细的执行结果

执行结果:

"C:\Program Files\Python36\python.exe" D:/Git/Test_Framework/utils/1.py
test_login1 (__main__.CmsLoginTest)
用户名、密码为空 ... ok
test_login2 (__main__.CmsLoginTest)
用户名正确,密码错误 ... ok
test_login4 (__main__.CmsLoginTest)
用户名不存在 ... ok
test_login3 (__main__.CmsLoginTest)
用户名、密码正确 ... ok

----------------------------------------------------------------------
Ran 4 tests in 44.818s

OK

Process finished with exit code 0

从用例的执行结果中我们可以看到,用例的执行顺序是按照添加用例时的顺序来执行的

一个一个地添加测试用例到测试套件中,有点麻烦,其实我们可以把要执行的测试用例用个列表来管理,然后再把这个列表添加到测试套件中,如下代码:

if __name__ == "__main__":
    # 构造测试套件
    suite = unittest.TestSuite()
    test_cases = [CmsLoginTest("test_login1"),CmsLoginTest("test_login2"),CmsLoginTest("test_login4"),
                  CmsLoginTest("test_login3")]
    suite.addTests(test_cases)
    # 执行测试
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

下面我们就来讲讲多个文件的测试用例组织。

假如我有两个系统的登录需要测试,测试用例分别放在两个文件中(cmslogin.py,smelogin.py),现在我需要把这两个文件中的用例添加到一个测试套件中来执行,为此我们要重新建立一个叫run_all.py的文件

import unittest
from cmslogin import CmsLoginTest
from smelogin import SmeLoginTest

if __name__ == "__main__":
    # 构造测试套件
    suite = unittest.TestSuite()
    test_cases = [CmsLoginTest("test_login1"),CmsLoginTest("test_login2"),CmsLoginTest("test_login4"),
                  CmsLoginTest("test_login3"),SmeLoginTest("test_login1"),SmeLoginTest("test_login2")]
    suite.addTests(test_cases)
    # 执行测试
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

还可以用addTests + TestLoader方法来添加用例,但是这种方法是无法对case进行排序的

import unittest
from cmslogin import CmsLoginTest
from smelogin import SmeLoginTest

if __name__ == "__main__":
    # 构造测试套件
    suite = unittest.TestSuite()
    # 第一种方法:传入'模块名.TestCase名'
    suite.addTests(unittest.TestLoader().loadTestsFromName('cmslogin.CmsLoginTest'))
    suite.addTests(unittest.TestLoader().loadTestsFromName('smelogin.SmeLoginTest'))
    # 这里还可以把'模块名.TestCase名'放到一个列表中
    suite.addTests(unittest.TestLoader().loadTestsFromNames(['cmslogin.CmsLoginTest','smelogin.SmeLoginTest']))
    # 第二种方法:传入TestCase
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(CmsLoginTest))
    # 执行测试
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

 

unittest参数化

import requests
import unittest
from parameterized import parameterized as pd

# 文件内容为
# http://xxx/api/user/stu_info,stu_name=矿泉水,矿泉水
def read_file(file_name):
    result = []
    with open(file_name,encoding='utf-8') as fr:
        for line in fr:
            line = line.strip()
            if line:
                result.append(line.split(','))
    return result

def read_excel():
    pass

def get_data_from_mysql(sql):
    pass

class InterFaceCase(unittest.TestCase):

    # @pd.expand([
    #     ['http://api.nnzhp.cn/api/user/stu_info','stu_name=矿泉水','矿泉水'],
    #     ['http://api.nnzhp.cn/api/user/stu_info','stu_name=小黑','小黑'],
    #     ['http://api.nnzhp.cn/api/user/stu_info','stu_name=','小黑'],
    # ])
    @pd.expand(read_file('login.txt'))
    def testlogin(self,url,data,check):
        # username=abc&password=1234  
        url = url+'?'+data
        result = requests.get(url).text
        self.assertIn(check,result)  # 检查check是否在result里面

 

查找测试用例

import unittest
import BeautifulReport as bf


suite = unittest.defaultTestLoader.discover('all_cases', '*.py')  # 查找all_cases文件夹下面所有以 .py 为结尾的文件
report = bf.BeautifulReport(suite)
report.report('端午节测试报告','dwj_report.html')  # 报告标题,报告文件名

print(report.failure_count)  # 已经封装了统计失败次数
print(report.success_count)  # 成功次数

 

参数传递,上下关联关系的接口

import unittest

class BaseTest(unittest.TestCase):

    def register(self,username,password):
        username,password = 'user1','password1'
        print('注册成功!')
        return username,password

    def login(self,username,password):
        print('test login',username,password)
        return 'token1'

    def add_basket(self,sku_id,count,token):
        print('加入购物车',sku_id,count)


    def order(self,token):
        print('产生订单!!')
        return 'order_id'

    def pay(self,order_id):
        print('支付')


class TestOrder(BaseTest):
    def testOrder(self):
        '''生成订单的流程'''  # 这个注释可以在beautifulreport中显示用例备注
        token = self.login('user1','test1')
        order_id = self.order(token)

    def testOrder2(self):
        '''生成订单的异常流程'''
        token = self.login('user1', 'test1')
        order_id = self.order(token)


class TestPay(BaseTest):
    def testPay(self):
        self.register('u','pass')

装饰器
可以在不改变原代码情况下添加新功能,其实是将原来代码加入到新功能的函数里面进行实现
import time


def log_w(str):
    with open('a.log', 'a+') as f:
        f.write(str)


def TimeStampToStr(timestamp=None, format='%Y-%m-%d %H:%M:%S'):
    if timestamp:
        time_tuple = time.localtime(timestamp)
        res = time.strftime(format, time_tuple)
        return res
    else:
        return time.strftime(format)


def write_record(func):
    def new_func():
        func()
        print('%s 调用了 %s 函数' % (TimeStampToStr(), func))
        log_w('%s 调用了 %s 函数\n' % (TimeStampToStr(), func))

    return new_func()


# a.log say 2019-06-07 18:33:44 调用了xx函数
# @write_record

@write_record
def say_hello():
    print('Hello World!')


@write_record
def get_time():
    print(time.localtime())

 



posted @ 2019-06-14 09:22  fatenet  阅读(253)  评论(0编辑  收藏  举报