python中测试代码

目录

一、测试函数

二、测试类


一、测试函数

要测试的代码

def get_formatted_name(first,last):
	full_name = f"{first} {last}"
	return full_name.title()

编写一个使用该函数的程序,来核实函数get_formatted_name。

from name_function import get_formatted_name
print("Enter 'q' at any time to quit.")
while True:
	first = input("\nPlease give me a first name: ")
	if first == 'q':
		break
	last = input("Please give me a last name: ")
	if last == 'q':
		break
	formatted_name = get_formatted_name(first,last)
	print(f"\tNearly formatted name: {formatted_name}.")
Please give me a first name: janis
Please give me a last name: joplin
        Nearly formatted name: Janis Joplin.

Please give me a first name: q

 说明合并得到的姓名无误,若还要添加中间名,可修改get_formatted_name后都进行测试:运行后一个程序names.py,但python提供了一种自动测试函数输出的高效方式。python标准库中的模块unittest提供了代码测试工具。

1.单元测试和测试用例

单元测试:用于核实函数的某个方面没有问题

测试用例:是一组单元测试,核实函数在各种情形下的行为都符合要求

全覆盖测试用例:包含一整套单元测试。通常只要对代码的重要行为编写测试即可。

2.可通过的测试

import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
	"""测试name_function.py"""
	def test_first_last_name(self):
		"""能够正确的处理Janis Joplin这样的姓名吗"""
		formatted_name = get_formatted_name('janis','joplin')
		self.assertEqual(formatted_name,'Janis Joplin')
if __name__=='__main__':
	unittest.main()

为函数编写测试用例,a先导入模块unittest和要测试的函数

b创建一个继承unittest.TestCase,类名随意,尽量与测试的函数相关并包含Test字样,类必须继承unittest.TestCase类,python才知道如何运行编写的测试。

c.编写一系列方法对函数行为的不同方面进行测试。def test_first_last_name(self):方法名必须以test_打头,这样它才会在运行文件时自动运行,方法名清楚的指出了测试的是哪个行为。

self.assertEqual(formatted_name,'Janis Joplin') 使用了unittest最有用的功能:断言方法,将formatted_name的值与字符串'Janis Joplin'比较

特殊变量__name__是在程序执行时设置的,如果这个文件作为主程序执行,变量__name__将设置为'__main__'

调用unittest.main( )来运行测试用例,如果文件被测试框架导入,变量__name__的值将不是__main__,就不会调用unittest.main( )

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

第一行的句点表示有一个测试通过了,最后的OK 表明测试用例中的所有单元测试都通过了。

3.未通过的测试

要测试的代码

def get_formatted_name(first,niddle,last):
	full_name = f"{first} {middle} {last}"
	return full_name.title()
E
======================================================================
ERROR: test_first_last_name (__main__.NamesTestCase)
能够正确的处理Janis Joplin这样的姓名吗
----------------------------------------------------------------------
Traceback (most recent call last):
  File "F:\python_work\chapter_11\test_name_function.py", line 7, in test_first_last_name
    formatted_name = get_formatted_name('janis','joplin')
TypeError: get_formatted_name() missing 1 required positional argument: 'last'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

E表示测试用例中有一个单元测试导致了错误;提示哪个测试未通过;Traceback指出问题 

4.测试未通过时怎么办

修复导致测试不能通过的代码。上例修改:让中间名变成可选的

可在函数定义中将形参middle移到形参列表末尾,并将其默认值指定为一个空字符串;再添加一个if测试,以便根据是否提供中间名相应的创建姓名。

def get_formatted_name(first,last,middle=''):
	if middle:
		full_name = f"{first} {middle} {last}"
	else:
		full_name = f"{first} {last}"
	return full_name.title()

5.添加新测试

import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
	"""测试name_function.py"""
	def test_first_last_name(self):
		"""能够正确的处理Janis Joplin这样的姓名吗"""
		formatted_name = get_formatted_name('janis','joplin')
		self.assertEqual(formatted_name,'Janis Joplin')

	def test_first_middle_last(self):
		"""能够正确的处理像Wolfgang Amadeus Mozart这样的姓名吗"""
		formatted_name = get_formatted_name('wolfgang','mozart','amadeus')
		self.assertEqual(formatted_name,'Wolfgang Amadeus Mozart')
		
if __name__=='__main__':
	unittest.main()

方法名必须以test_打头,这样它才会在我们运行test_name_function.py时自动运行。可以在TestCase类中使用很长的方法名,且必须是描述性的,这样你才能看懂测试未通过时的输出。这些方法由Python自动调用,你根本不用编写调用它们的代码。

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

二、测试类

1.各种断言方法

python在unittest.TestCase中提供了很多断言方法,6个常用的断言方法:

方法用途
assertEqual(a,b)核实a == b
assertNotEqual(a,b)核实a != b
assertTrue(x)核实x为True
assertFalse(x)核实x为False
assertIn(item,list)核实item在list中
assertNotIn(item,list)核实item不在list中

2.一个要测试的类

编写一个要测试的类 (survey.py)

class AnonymousSurvey:
	"""收集匿名调查问卷的答案"""
	def __init__(self,question):
		"""存储一个问题,并为存储答案做准备"""
		self.question = question
		self.responses = []
	def show_question(self):
		"""显示调查问卷"""
		print(self.question)
	def store_response(self,new_response):
		"""存储单份调查问卷的答案"""
		self.responses.append(new_response)
	def show_results(self):
		"""显示收集到的所有答案"""
		print("Survey results: ")
		for response in self.responses:
			print(f"-{response}")

编写一个使用程序证明类能正确工作(language_survey.py)

from survey import AnonymousSurvey

#定义一个问题并创建调查
question = "What language did you first learn to speak?"
my_survey = AnonymousSurvey(question)
#显示问题并存储答案
my_survey.show_question()
print("Enter 'q' at any time to quit.\n")
while True:
	response = input("Language: ")
	if response == 'q':
		break
	my_survey.store_response(response)
#显示调查结果
print("\nThank you to everyone who participate in the survey!")
my_survey.show_results()
What language did you first learn to speak?
Enter 'q' at any time to quit.

Language: English
Language: Spanish
Language: English
Language: Mandarin
Language: q

Thank you to everyone who participate in the survey!
Survey results:
-English
-Spanish
-English
-Mandarin

3.测试AnonymousSurvey类

import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
	"""针对AnonymousSurvey类的测试"""
	def test_store_single_response(self):
		"""测试单个答案会被妥善存储"""
		question = "What language did you first learn to speak? "
		my_survey = AnonymousSurvey(question)   #创建一个实例
		my_survey.store_response('English')
		self.assertIn('English',my_survey.responses)

if __name__ == '__main__':
	unittest.main()
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

这只能收集一个答案的调查,用途不大,当用户提供三个答案时,也会被妥善保存。

class AnonymousSurvey:
	"""收集匿名调查问卷的答案"""
	def __init__(self,question):
		"""存储一个问题,并为存储答案做准备"""
		self.question = question
		self.responses = []
	def show_question(self):
		"""显示调查问卷"""
		print(self.question)
	def store_response(self,new_response):
		"""存储单份调查问卷的答案"""
		self.responses.append(new_response)
	def show_results(self):
		"""显示收集到的所有答案"""
		print("Survey results: ")
		for response in self.responses:
			print(f"-{response}")
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

 4.方法setUp( )

如果在TestCase类中包含了方法setUp(),Python将先运行它,再运行各个以test_打头的方法。

使用setUp()来创建一个调查对象和一组答案,供方法test_store_single_response()和test_store_three_responses()使用。

import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase):
	"""针对AnonymousSurvey类的测试"""
	def setUp(self):
		"""创建一个调查对象和一组答案,供使用的测试方法使用"""
		question = "What language did you first learn to speak?"
		self.my_survey = AnonymousSurvey(question)               #创建一个调查对象
		self.responses = ['English','Spanish','Mandarin']        #创建一个答案列表

	def test_store_single_response(self):
		"""测试单个答案会被妥善存储"""
		self.my_survey.store_response(self.responses[0])
		self.assertIn(self.responses[0],self.my_survey.responses)

	def test_store_three_responses(self):
		"""测试三个答案会妥善保存"""
		for response in self.responses:
			self.my_survey.store_response(response)
		for response in self.responses:
			self.assertIn(response,self.my_survey.responses)

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

方法setUp()做了两件事情:创建一个调查对象,以及创建一个答案列表,存储这两样东西的变量名包含前缀self,因此可在类的任何地方使用 。这让两个测试方法都更简单,因为它们都不用创建调查对象和答案了。

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

测试自己编写的类时,方法setUp()让测试方法编写起来更容易:可在setUp()方法中创建一系列实例并设置其属性,再在测试方法中直接使用这些实例。相比于在每个测试方法中都创建实例并设置其属性,这要容易得多。

运行测试用例时,每完成一个单元测试,Python都打印一个字符:测试通过时打印一个句点,测试引发错误时打印一个E,而测试导致断言失败时则打印一个F。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值