excel能翻译中文吗
614
2022-05-29
1.请求fixtures
在基本级别,测试函数通过将它们声明为参数来请求所需的fixtures。
当pytest运行测试时,会查看该测试函数签名中的参数,然后搜索与这些参数同名的fixtures。pytest找到后会运行这些fixtures,捕获它们返回的内容(如果有的话),并将这些对象作为参数传递给测试函数中。
1.1.例子
import pytest class Fruit: def __init__(self,name): self.name=name self.cubed=False def cube(self): self.cubed=True class FruitSalad: def __init__(self,*fruit_bowl): self.fruit=fruit_bowl self._cube_fruit() def _cube_fruit(self): for fruit in self.fruit: fruit.cube() # Arrange @pytest.fixture def fruit_bowl(): return [Fruit("apple"),Fruit("banana")] def test_fruit_salad(fruit_bowl): #Act fruit_salad=FruitSalad(*fruit_bowl) #Assert assert all(fruit.cubed for fruit in fruit_salad.fruit)
在这个例子中,test_fruit_salad请求fruit_bowl(即def test_fruit_salad(fruit_bowl):),当pytest看到时,会执行fruit_bowl的fixture函数,并将它返回的对象作为fruit_bowl参数传递给test_fruit_salad。
以下代码演示了如果我们手动完成操作时所发生的情况:
def fruit_bowl(): return [Fruit("apple"), Fruit("banana")] def test_fruit_salad(fruit_bowl): # Act fruit_salad = FruitSalad(*fruit_bowl) # Assert assert all(fruit.cubed for fruit in fruit_salad.fruit) # Arrange bowl = fruit_bowl() test_fruit_salad(fruit_bowl=bowl)
1.2.fixtures可以请求其他fixtures
pytest的最大优势之一就是极其灵活的fixture系统。它允许我们将复杂的测试需求归纳为更简单和有组织的功能,我们只需要让每个需求描述它们所依赖的东西。以下例子演示了fixtures如何调用其他fixtures。
# content of test_append.py import pytest # Arrange @pytest.fixture def first_entry(): return "a" # Arrange @pytest.fixture def order(first_entry): return [first_entry] # 相当于return ["a"] def test_string(order): # Act order.append("b") # Assert assert order==["a","b"]
请注意,这是和上面相似的示例。pytest中的fixtures请求fixtures就像测试一样。所有相同的请求规则都适用于用于测试的fixtures。下面是如果我们手动执行此示例的工作原理:
def first_entry(): return "a" def order(first_entry): return [first_entry] def test_string(order): # Act order.append("b") # Assert assert order == ["a", "b"] entry = first_entry() the_list = order(first_entry=entry) test_string(order=the_list)
1.3.fixtures可以复用
使pytest的fixture系统强大的原因之一是,它使我们能够定义一个可以一遍又一遍重复使用的通用设置步骤,就像使用普通功能一样。两个不同的测试可以请求相同的fixture,并让pytest从fixture中为每个测试提供自己的结果。
这对于确保测试不受彼此影响非常有用。我们可以使用此系统来确保每个测试都获得自己的数据,并从干净的状态开始,以便它能够提供一致,可重复的结果。
以下是一个如何派上用场的示例:
# contents of test_append1.py import pytest # Arrange @pytest.fixture def first_entry(): return "a" # Arrange @pytest.fixture def order(first_entry): return [first_entry] def test_string(order): # Act order.append("b") # Assert assert order==["a","b"] def test_int(order): # Act order.append(2) # Assert assert order==["a",2]
每个测试都为其提供了该列表对象的自己的副本,意味着order fixture将执行两次(对于first_entry fixture也一样)。如果我们手动执行此操作,如下所示:
def first_entry(): return "a" def order(first_entry): return [first_entry] def test_string(order): # Act order.append("b") # Assert assert order == ["a", "b"] def test_int(order): # Act order.append(2) # Assert assert order == ["a", 2] entry = first_entry() the_list = order(first_entry=entry) test_string(order=the_list) entry = first_entry() the_list = order(first_entry=entry) test_int(order=the_list)
1.4.一个测试/fixture可以在一个时刻请求多个fixture
测试和fixtures不仅限于一次请求一个fixture。可以随意请求。如下示例所示:
# contents of test_append2.py import pytest # Arrange @pytest.fixture def first_entry(): return "a" # Arrange @pytest.fixture def second_entry(): return 2 # Arrange @pytest.fixture def order(first_entry,second_entry): return [first_entry,second_entry] # Arrange @pytest.fixture def expected_list(): return ["a",2,3.0] def test_string(order,expected_list): # Act order.append(3.0) # Assert assert order==expected_list
1.5.每次测试可以多次请求fixture(缓存返回值)
在同一测试期间,也可以多次请求fixtures,pytest不会为该测试再次执行它们。意味着我们可以在依赖于它们的多个fixtures中请求fixtures(甚至在测试本身中再次请求fixtures),而无需多次执行执行该fixtures。
# contents of test_append3.py import pytest # Arrange @pytest.fixture def first_entry(): return "a" # Arrange @pytest.fixture def order(): return [] # Act @pytest.fixture def append_first(order,first_entry): return order.append(first_entry) def test_string_only(append_first,order,first_entry): # Assert assert order==[first_entry]
如果请求的fixture在测试期间每次请求都执行一次,则此测试将失败,以为append_first和test_string_only都将order视为空列表(即[]),但由于order的返回值在第一次调用后被缓存(以及执行它的任何副作用),测试和append_first都引用了同一个对象,测试看到了append_first对该对象的影响。
2.自动使用fixtures(你不必请求fixtures)
有时,你希望有一个(甚至几个)fixture,知道所有测试都将依赖于该fixture。"Autouse"fixtures是使所有测试自动请求它们的快捷方式。可以减少大量冗余请求。
可以通过将autouse=True传递给fixtures的装饰器。以下是一个简单的示例:
# content of test_append4.py import pytest @pytest.fixture def first_entry(): return "a" @pytest.fixture def order(first_entry): return [] @pytest.fixture(autouse=True) def append_first(order,first_entry): return order.append(first_entry) def test_string_only(order,first_entry): order.append(2) assert order==[first_entry,2]
在此示例中,append_first是自动使用fixture。由于是自动发生的,两个侧式都会受到影响,即使两个测试都没有请求它。但并不意味着不能请求它们,只是没有必要。
3.范围:跨类、模组、包或session共享fixtures
fixtures请求网络依赖于连接性,并且通常创建起来很费时。扩展前面的示例,我们可以在@pytest.fixture调用中添加一个scope="module"参数,以导致smtp_connection的fixtures功能,负责创建与预先存在的SMTP服务器的连接,每个测试模块仅调用一次(默认是每个测试函数调用一次)。因此,测试模块中的多个测试函数将各自接收相同的smtp_connection的fixtures实例,从而节省时间。范围的可能值是:函数、类、模块、包或会话。
下一个示例将fixtures函数放入单独的conftest.py文件中,以便目录中多个测试模块的测试可以访问fixtures函数:
# content of conftest.py import pytest import smtplib @pytest.fixture(scope="module") def smtp_connection(): return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
# content of test_module.py def test_ehlo(smtp_connection): response, msg = smtp_connection.ehlo() assert response == 250 assert b"smtp.gmail.com" in msg assert 0 # for demo purposes def test_noop(smtp_connection): response, msg = smtp_connection.noop() assert response == 250 assert 0 # for demo purposes
这里,test_ehlo需要smtp_connection的fixture值。pytest将发现并调用标记为smtp_connection的fixture函数的@pytest.fixture。
$ pytest test_module.py =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items test_module.py FF [100%] ================================= FAILURES ================================= ________________________________ test_ehlo _________________________________ smtp_connection =
你会看到两个assert 0失败,更重要的是可以看到完全相同的smtp_connection对象被传递到两个测试函数中,因为pytest的回溯中显示了传入的参数值。因此,使用smtp_connection的两个测试函数的运行速度与单个函数一样快,因为它们重用了相同的实例。
如果决定拥有一个会话范围的smtp_connection实例,可以简单声明:
@pytest.fixture(scope="session") def smtp_connection(): # the returned fixture value will be shared for # all tests requesting it ...
3.1.fixtures范围
fixtures在测试首次请求时创建,并根据其范围销毁:
function:默认作用域,fixture在测试结束时被销毁
class:fixture在类中最后一个测试的teardown过程中被销毁
module:fixture在模块中最后一个测试的teardown过程中被销毁
package:fixture在包中最后一个测试的teardown过程中被销毁
session:fixture在测试会话结束时被销毁
注意:pytest一次只缓存一个fixture实例,意味着当使用参数化fixture时,pytest可能会在给定范围内多次调用fixture。
3.2.动态范围(5.2版本出现)
某些情况下,你可能希望在不更改代码的情况下更改fixture的范围。为此,请将可调用对象传递给范围。可调用对象必须返回一个具有有效范围的字符串,并且只会执行一次(在fixture定义期间)。它将使用两个关键字参数调用(fixture_name作为字符串和配置对象的配置)。
这在处理需要时间设置的fixture时特别有用,例如生成docker容器。你可以使用命令行参数来控制不同环境的衍生容器的范围。请参见下面的示例。
def determine_scope(fixture_name, config): if config.getoption("--keep-containers", None): return "session" return "function" @pytest.fixture(scope=determine_scope) def docker_container(): yield spawn_container()
Python
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。