测试代码,就是尽可能在用户发现bug之前提前找到并修复bug
更新包
python -m pip install --upgrade package_name
更新pip包
python -m pip install --upgrade pip
安装三方包
--user
参数指仅为当前用户安装,一般加不加都没多大影响
python -m pip install --user package_name
安装pytest包
python -m pip install --user pytest
测试代码
写好的代码(
add.py
)后,再新建一个前缀为test_
或 以_test
后缀的py文件(test_add.py
),然后导入原先的代码
待测试函数
# add.py
def add_num(x , y):
return x + y
编写测试代码
其中
assert
右边可以换成其他的运算符(只有结果是布尔值就没有问题)
# test_add.py
from add import add_num
def test_add_num():
result = add_num(11, 45)
assert result == 56
开始测试
后面这个这个
test_add.py
模块名字如果不加那就是测试当前目录下所有的以test_
前缀 或 以_test
后缀的py文件;如果加上就只测一个文件
python -m pytest test_add.py
测试完成
当你测试完成,你将看到一个进度值(100%)和一个
.
,这个点表示测试成功,反之表示测试失败。关于这个进度条,如果你使用的是python -m pytest
并且旁边还有一个测试文件,这个测试文件还有两个测试函数,那么第一个进度值一定是33%或者66%。
PS E:\Documents\code> python -m pytest
======================= test session starts =======================
platform win32 -- Python 3.13.1, pytest-8.4.0, pluggy-1.6.0
rootdir: E:\Documents\code
collected 3 items
test_add.py . [ 33%]
test_survey.py .. [100%]
======================== 3 passed in 0.06s ========================
待测试类
# survey.py
class AnonymousSurvey:
"""Collect anonymous answers to a survey question."""
def __init__(self, question):
"""Store a question, and prepare to store responses."""
self.question = question
self.responses = []
def show_question(self):
"""Show the survey question."""
print(self.question)
def store_response(self, new_response):
"""Store a single response to the survey."""
self.responses.append(new_response)
def show_results(self):
"""Show all the responses that have been given."""
print("Survey results:")
for response in self.responses:
print(f"- {response}")
运行代码
# language_survey.py
from survey import AnonymousSurvey
# Define a question, and make a survey.
question = "What language did you first learn to speak?"
language_survey = AnonymousSurvey(question)
# Show the question, and store responses to the question.
language_survey.show_question()
print("Enter 'q' at any time to quit.\n")
while True:
response = input("Language: ")
if response == 'q':
break
language_survey.store_response(response)
# Show the survey results.
print("\nThank you to everyone who participated in the survey!")
language_survey.show_results()
测试代码
可以测试单个方法,也可以通过模仿单个方法来测试多个方法,不过可能有些操作比较繁杂,因为很多代码都是很低效重复的,所以我们要用额外的手段来尽可能减少重复代码。
测试单个函数
# test_survey.py
from survey import AnonymousSurvey
def test_store_single_response():
"""Test that a single response is stored properly."""
question = "What language did you first learn to speak?"
language_survey = AnonymousSurvey(question)
language_survey.store_response('English')
assert 'English' in language_survey.responses
然后运行
python -m pytest test_survey.py
测试多个函数
# test_survey.py
from survey import AnonymousSurvey
def test_store_single_response():
"""Test that a single response is stored properly."""
question = "What language did you first learn to speak?"
language_survey = AnonymousSurvey(question)
language_survey.store_response('English')
assert 'English' in language_survey.responses
def test_store_three_responses():
"""Test that three individual responses are stored properly."""
question = "What language did you first learn to speak?"
language_survey = AnonymousSurvey(question)
responses = ['English', 'Spanish', 'Mandarin']
for response in responses:
language_survey.store_response(response)
for response in responses:
assert response in language_survey.responses
然后运行
python -m pytest test_survey.py
优化测试代码
首先我们要先学习一下装饰器
装饰器
我这定义了三个函数和使用了一下装饰器,首先我们先看上面的函数,假设我们运行这最上面的
out_func
函数并让它被赋值为a
,执行之后它会先打印外层1
,接着返回值in_func
函数给a
,所以现在a就相当于指向in_func
函数,所以a
后面接上个括号就能直接运行内层函数的代码。
而我们要说的装饰器就和这个原理非常像,其实下面的@out_func
以及跟在定义函数后面的,约等于a = out_func(test_func)
,所以再给a
后面接一个括号,就跟上面说的原理一模一样了。
# test.py
def out_func(func):
print('外层1')
def in_func():
print('内层1')
func()
print('内层2')
return in_func
@out_func
def test_func():
print('test_func')
test_func()
def test1_func(func):
func() # 等价于运行test_func()而这个等价于运行in_func()
test1_func(test_func)
测试代码
# test_survey.py
import pytest
from survey import AnonymousSurvey
@pytest.fixture
def language_survey():
"""A survey that will be available to all test functions."""
question = "What language did you first learn to speak?"
language_survey = AnonymousSurvey(question)
return language_survey
def test_store_single_response(language_survey):
"""Test that a single response is stored properly."""
language_survey.store_response('English')
assert 'English' in language_survey.responses
def test_store_three_responses(language_survey):
"""Test that three individual responses are stored properly."""
responses = ['English', 'Spanish', 'Mandarin']
for response in responses:
language_survey.store_response(response)
for response in responses:
assert response in language_survey.responses