一、单元测试
工具:unittest\node\pytest
主要作用:测试类、方法、函数
第一步:要用类来组织所有的测试用例,继承于testcase的基类
架构部分:有setup【环境准备】\test_run【测试逻辑】\tearDown【环境清理】\
作用:做回归测试,验证原来的代码没问题
1.1 实例一
#coding=utf-8
class Calc(object):
def add(self,x,y,*d):
#加法计算
result=x+y
for i in d:
result+=i
return result
def sub(self,x,y,*d):
#减法计算
result=x-y
for i in d:
result-=i
return result
@classmethod
def mul(cls,x,y,*d):
#乘法计算
result=x*y
for i in d:
result*=i
return result
@staticmethod
def div(x,y,*d):
#除法计算
if y!=0:
result =x/y
else:
return -1
for i in d:
if i !=0:
result /=i
else:
return -1
return result
if __name__=="__main__":
c=Calc()
print(c.add(1,2,3,4))
#print(c.add(1,2,[3,4],5,a=3))
print(c.sub(1,2,3,4))
print(c.mul(2,3,4))
print(c.div(10,5,1))
print(c.div(1,0,0))
print(c.div(1,1,0))
print(Calc.mul(1,2,3,4))
print(Calc.div(100,10,5,1))
1.2实例二
#encoding=utf-8
import unittest
import random
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
#初始化一个递增序列
self.seq=list(range(10))
print("setup completed!")
def test_run(self):
#从序列seq中随机选取一个元素
element=random.choice(self.seq)
#验证随机元素确实属于列表中
self.assertTrue(element in self.seq)
def test_sth(self):
assert 1==1
def tearDown(self):
print("tearDown completed")
class TestDictValueFormatFunctions(unittest.TestCase):
def setUp(self):
self.seq=list(range(10))
def test_shuffle(self):
#随机打乱原seq的顺序
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq,list(range(10)))
#验证执行函数时抛出TypeError异常
self.assertRaises(TypeError,random.shuffle,(1,2,3))
if __name__=="__main__":
unittest.main()

备注:.是执行成功,可以数点
1.3 实例三
import unittest
import random
import Calc
class TestCalc(unittest.TestCase):
def setUp(self):
#生成实例
self.cal=Calc.Calc()
print("setup completed!")
def test_add(self):
result=self.cal.add(1,2,3,4)
assert 10==result
def tearDown(self):
print("tearDown completed!")
if __name__=="__main__":
unittest.main()
或者
import unittest
import random
import Calc
class TestCalc(unittest.TestCase):
def setUp(self):
#生成实例
self.cal=Calc.Calc()
print("setup completed!")
def test_add(self):
result=self.cal.add(1,2,3,4)
self.assertTrue (10==result)
def tearDown(self):
print("tearDown completed!")
if __name__=="__main__":
unittest.main()
1.4 实例四:只连一次
#比如测试数据库
#encoding=utf-8
import unittest
#被测试类
class myclass(object):
@classmethod
def sum(self,a,b):
return a+b
@classmethod
def sub(self,a,b):
return a-b
class TestMyClass(unittest.TestCase):
@classmethod
def setUpClass(cls):
"初始化类固件"
print("--setUpClass")
@classmethod
def tearDownClass(cls):
"重构类固件"
print("--tearDownClass")
#初始化工作
def setUp(self):
self.a=3
self.b=1
print("--setUp")
#退出清理工作
def tearDown(self):
print("--tearDown")
#具体的测试用例,一定要以test开头
def testsum(self):
#断言两数之和的结果是否是4
self.assertEqual(myclass.sum(self.a,self.b),4,"test sum fail")
def testsub(self):
#断言两数之差的结果是否是2
self.assertEqual(myclass.sub(self.a,self.b),2,"test sub fail")
if __name__=="__main__":
unittest.main() #启用单元测试

小知识:时间复杂度
n=1 -O(1)
for i in range(n):
print(i) --->O(n)
for i in range(n):
for j in range(n):
print(i) --->O(n^2)
for i in range(n):
for j in range(n):
for n in range(n):
print(i) --->O(n^3)
二分法:----》O(nlogn)
1.5 实例五:顺序执行
#encoding=utf-8
import unittest
from Calc import Calc
class MyTest(unittest.TestCase):
@classmethod
def setUpClass(self):
print(u"单元测试前,创建Calc类的实例")
self.c=Calc()
#具体的测试用例,一定要以test开头,执行顺序按照字母顺序开头
def test_0add(self):
print("run add()")
self.assertEqual(self.c.add(1,2,12),15,"test add fail")
def test_1sub(self):
print("run sub()")
self.assertEqual(self.c.sub(2,1,3),-2,"test fail")
def test_2mul(self):
print("run mul()")
self.assertEqual(Calc.mul(2,3,5),30,"test mul fail")
def test_3div(self):
print("run div()")
self.assertEqual(Calc.div(8,2,4),1,"test div fail")
if __name__=="__main__":
unittest.main() #启动单元测试

1.5.1 实例六:跳过用例
#coding=utf-8
import random
import unittest
import sys
class TestSequenceFunctions(unittest.TestCase):
a=1
def setUp(self):
self.seq=list(range(10))
@unittest.skip("skipping") #无条件忽略该测试方法
def test_shuffle(self):
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq,list(range(10)))
self.assertRaises(TypeError,random.shuffle,(1,2,3))
#如果变量a>5,则忽略该测试方法
@unittest.skipIf(a>5,"condition is not satisfied!")
def test_choice(self):
element=random.choice(self.seq)
self.assertTrue(element in self.seq)
#除非执行测试用例的平台是Linux平台,否则忽略该测试方法 win32是windows
@unittest.skipUnless(sys.platform.startswith('linux'),"requirees linux")
def test_sample(self):
with self.assertRaises(ValueError):
random.sample(self.seq,20)
for element in random.sample(self.seq,5):
self.assertTrue(element in self.seq)
if __name__=="__main__":
#unittest.main()
suite=unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
suite=unittest.TestSuite(suite)
unittest.TextTestRunner(verbosity=2).run(suite)

1.6 实例六:执行多个测试用例【测试套件】
#encoding=utf-8
import random
import unittest
from TestCalc import TestCalcFunctions
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
self.seq = list(range(10))
def tearDown(self):
pass
def test_choice(self):
# 从序列seq中随机选取一个元素
element = random.choice(self.seq)
# 验证随机元素确实属于列表中
self.assertTrue(element in self.seq)
def test_sample(self):
# 验证执行的语句是否抛出了异常
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq)
class TestDictValueFormatFunctions(unittest.TestCase):
def setUp(self):
self.seq = list(range(10))
def tearDown(self):
pass
def test_shuffle(self):
# 随机打乱原seq的顺序
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq, list(range(10)))
# 验证执行函数时抛出了TypeError异常
self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
if __name__ == '__main__':
# 根据给定的测试类,获取其中的所有以“test”开头的测试方法,并返回一个测试套件
suite1 = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
suite2 = unittest.TestLoader().loadTestsFromTestCase(TestDictValueFormatFunctions)
suite3 = unittest.TestLoader().loadTestsFromTestCase(TestCalcFunctions)
# 将多个测试类加载到测试套件中
suite = unittest.TestSuite([suite2, suite1,suite3]) #通过调整suit2和suite1的顺序,可以设定执行顺序
# 设置verbosity = 2,可以打印出更详细的执行信息
unittest.TextTestRunner(verbosity = 2).run(suite)

1.7 实例七
#encoding=utf-8
import unittest
import random
# 被测试类
class MyClass(object):
@classmethod
def sum(self, a, b):
return a + b
@classmethod
def div(self, a, b):
return a / b
@classmethod
def retrun_None(self):
return None
# 单元测试类
class MyTest(unittest.TestCase):
# assertEqual()方法实例
def test_assertEqual(self):
# 断言两数之和的结果
try:
a, b = 1, 2
sum = 3
self.assertEqual(a + b, sum, '断言失败,%s + %s != %s' %(a, b, sum))
except AssertionError as e:
print (e)
# assertNotEqual()方法实例
def test_assertNotEqual(self):
# 断言两数之差的结果
try:
a, b = 5, 2
res = 1
self.assertNotEqual(a - b, res, '断言失败,%s - %s != %s' %(a, b, res))
except AssertionError as e:
print (e)
# assertTrue()方法实例
def test_assertTrue(self):
# 断言表达式的为真
try:
self.assertTrue(1 == 1, "表达式为假")
except AssertionError as e:
print (e)
# assertFalse()方法实例
def test_assertFalse(self):
# 断言表达式为假
try:
self.assertFalse(3 == 2, "表达式为真")
except AssertionError as e:
print (e)
# assertIs()方法实例
def test_assertIs(self):
# 断言两变量类型属于同一对象
try:
a = 12
b = a
self.assertIs(a, b, "%s与%s不属于同一对象" %(a, b))
except AssertionError as e:
print (e)
# test_assertIsNot()方法实例
def test_assertIsNot(self):
# 断言两变量类型不属于同一对象
try:
a = 12
b = "test"
self.assertIsNot(a, b, "%s与%s属于同一对象" %(a, b))
except AssertionError as e:
print (e)
# assertIsNone()方法实例
def test_assertIsNone(self):
# 断言表达式结果为None
try:
result = MyClass.retrun_None()
self.assertIsNone(result, "not is None")
except AssertionError as e:
print (e)
# assertIsNotNone()方法实例
def test_assertIsNotNone(self):
# 断言表达式结果不为None
try:
result = MyClass.sum(2, 5)
self.assertIsNotNone(result, "is None")
except AssertionError as e:
print (e)
# assertIn()方法实例
def test_assertIn(self):
# 断言对象A是否包含在对象B中
try:
strA = "this is a test"
strB = "is"
self.assertIn(strB, strA, "%s不包含在%s中" %(strB, strA))
except AssertionError as e:
print (e)
# assertNotIn()方法实例
def test_assertNotIn(self):
# 断言对象A不包含在对象B中
try:
strA = "this is a test"
strB = "Selenium"
self.assertNotIn(strB, strA, "%s包含在%s中" %(strB, strA))
except AssertionError as e:
print (e)
# assertIsInstance()方法实例
def test_assertIsInstance(self):
# 测试对象A的类型是否值指定的类型
try:
x = MyClass
y = object
self.assertIsInstance(x, y, "%s的类型不是%s" %(x, y))
except AssertionError as e:
print (e)
# assertNotIsInstance()方法实例
def test_assertNotIsInstance(self):
# 测试对象A的类型不是指定的类型
try:
a = 123
b = str
self.assertNotIsInstance(a, b, "%s的类型是%s" %(a, b))
except AssertionError as e:
print (e)
# assertRaises()方法实例
def test_assertRaises(self):
# 测试抛出的指定的异常类型
# assertRaises(exception)
with self.assertRaises(TypeError) as cm:
random.sample([1,2,3,4,5], "j")
# 打印详细的异常信息
#print "===", cm.exception
# assertRaises(exception, callable, *args, **kwds)
try:
self.assertRaises(ZeroDivisionError, MyClass.div, 3, 0)
except ZeroDivisionError as e:
print (e)
# assertRaisesRegexp()方法实例
def test_assertRaisesRegexp(self):
# 测试抛出的指定异常类型,并用正则表达式具体验证
# assertRaisesRegexp(exception, regexp)
with self.assertRaisesRegex(ValueError, 'literal') as ar:
int("xyz")
# 打印详细的异常信息
#print ar.exception
# 打印正则表达式
#print "re:",ar.expected_regexp
# assertRaisesRegexp(exception, regexp, callable, *args, **kwds)
try:
self.assertRaisesRegexp(ValueError, "invalid literal for.*XYZ'$", int, 'XYZ')
except AssertionError as e:
print (e)
if __name__ == '__main__':
# 执行单元测试
unittest.main()

1.8实例八:本地生成单元测试报告
# coding=utf-8
import unittest
import HTMLTestRunner
import math
class Calc(object):
def add(self, x, y, *d):
# 加法计算
result = x + y
for i in d:
result += i
return result
def sub(self, x, y, *d):
# 减法计算
result = x - y
for i in d:
result -= i
return result
class SuiteTestCalc(unittest.TestCase):
def setUp(self):
self.c = Calc()
@unittest.skip("skipping")
def test_Sub(self):
print ("sub")
self.assertEqual(self.c.sub(100, 34, 6), 61, u'求差结果错误!')
def testAdd(self):
print ("add")
self.assertEqual(self.c.add(1, 32, 56), 89, u'求和结果错误!')
class SuiteTestPow(unittest.TestCase):
def setUp(self):
self.seq = list(range(10))
# @unittest.skipIf()
def test_Pow(self):
print ("Pow")
self.assertEqual(pow(6, 3), 2161, u'求幂结果错误!')
def test_hasattr(self):
print ("hasattr")
# 检测math模块是否存在pow属性
self.assertTrue(hasattr(math, 'pow1'), u"检测的属性不存在!")
if __name__ == "__main__":
suite1 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestCalc)
suite2 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestPow)
suite = unittest.TestSuite([suite1, suite2])
#unittest.TextTestRunner(verbosity=2).run(suite)
filename = "test.html" # 定义个报告存放路径,支持相对路径。
# 以二进制方式打开文件,准备写
fp = open(filename, 'wb')
# 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
title = u'测试报告', description = u'测试报告内容')
# 运行测试集合
runner.run(suite)

1.9 实例九:批量执行某个目录下
#coding=utf-8
import unittest
if __name__ == '__main__' :
# 加载当前目录下所有有效的测试模块(以test开头的文件),“.”表示当前目录
testSuite = unittest.TestLoader().discover('.')
#.可以改为绝对路径
#print testSuite
unittest.TextTestRunner(verbosity = 2).run(testSuite)

1.10 实例十:结合webdriver
#encoding=utf-8
import unittest
from selenium import webdriver
import time
class GloryRoad(unittest.TestCase):
def setUp(self):
# 启动Firefox浏览器
self.driver = webdriver.Firefox(executable_path = "e:\\geckodriver")
def testSoGou(self):
# 访问搜狗首页
self.driver.get("http://sogou.com")
# 清空搜索输入框默认内容
self.driver.find_element_by_id("query").clear()
# 在搜索输入框中输入“光荣之路自动化测试”
self.driver.find_element_by_id("query").send_keys(u"WebDriver实战宝典")
# 单击“搜索”按钮
self.driver.find_element_by_id("stb").click()
# 等待3秒
time.sleep(3)
assert u"吴晓华" in self.driver.page_source, u"页面中不存在要寻找的关键字!".encode("gbk")
def testBing(self):
# 访问bing首页
self.driver.get("http://cn.bing.com")
# 清空搜索输入框默认内容
self.driver.find_element_by_id("sb_form_q").clear()
# 在搜索输入框中输入“光荣之路自动化测试”
self.driver.find_element_by_id("sb_form_q").send_keys(u"WebDriver实战宝典")
# 单击“搜索”按钮
self.driver.find_element_by_id("sb_form_go").click()
# 等待3秒
time.sleep(3)
assert u"吴晓华" in self.driver.page_source, u"页面中不存在要寻找的关键字!".encode("gbk")
def tearDown(self):
# 退出浏览器
self.driver.quit()
if __name__ == '__main__':
unittest.main()
1.11 代码覆盖率
1.11.1 环境安装
pip install coverage

1.11.2 实现代码覆盖率命令
方法一:
coverage run Calc.py
coverage report –m

方法二:
coverage html

1850



被折叠的 条评论
为什么被折叠?



