Rspec 限制方法的重用
Rspec limit reuse of methods
Ruby 和 RSpec 的新手所以请保持温柔。
我来自 Python 世界,特别是 pytest。您可以在 pytest 中做的一件事是在您的测试和其他固定装置中使用固定装置。在一个超简单的示例中,假设我们有一个 create
灯具,以及一个需要 create
的 delete
灯具。如果我们有一个同时使用 create
和 delete
固定装置的测试,create
只会被调用一次(即使 delete
使用 create
,pytest 知道它是已经调用了测试用例。这是一些示例 python 代码:
# test_fixture_reuse.py
import pytest
@pytest.fixture
def create_something():
"""Create tester object"""
#return MyTester(request.param)
print ("created_something")
@pytest.fixture
def delete_something(create_something):
"""Create tester object"""
#return MyTester(request.param)
print ("delete_something")
class TestIt:
def test_only_create(self, create_something):
print ("in test_only_create")
assert 1
def test_create_and_delete(self, create_something, delete_something):
print ("in test_create_and_delete")
assert 1
def test_only_delete(self, delete_something):
print ("in test_only_delete")
assert 1
运行 pytest -v test_fixture_reuse -s
returns 这个输出,和预期的一样:
test_parameterized_fixture.py::TestIt::test_only_create created_something
in test_only_create
PASSED
test_parameterized_fixture.py::TestIt::test_create_and_delete created_something
delete_something
in test_create_and_delete
PASSED
test_parameterized_fixture.py::TestIt::test_only_delete created_something
delete_something
in test_only_delete
PASSED
根据我在 Ruby 中的尝试,没有与 fixture
等效的概念,这意味着每个测试都需要控制调用流。因此,如果我们正在测试删除,测试将需要调用 create
,然后调用 delete
,但 delete
不会显式依赖于 create
。 RSpec 中的灯具通常似乎映射到模型,因此大多数搜索结果都不相关。
我的问题是 - 我怎样才能在 RSpec 中执行类似于上述 python 代码的操作?还是因为 Python 的经验,这是我的观点过于局限的事情之一,并且在 RSpec 中有一种类似的做事方式我没有正确搜索?
在 RSpec 中我们使用 let
作为记忆辅助方法,像这样:
RSpec.describe("my tests") do
let(:created_record) { MyRecord.create }
# using tap here to return the deleted record from the block
let(:destroyed_record) { created_record.tap(&:destroy) }
it("can create record") { created_record }
it("can destroy record") { destroyed_record }
it("memoizes created_record if called twice") { created_record; destroyed_record }
end
let
调用不会 运行 直到您第一次在测试中引用它们,并在该测试用例中为后续调用使用缓存的结果。 “测试用例”是指 it
块。如果您希望这些方法在每个测试用例开始时自动执行(无需显式调用该方法),您可以改用 let!
。结果仍将被缓存以供后续调用。参见 https://relishapp.com/rspec/rspec-core/v/2-11/docs/helper-methods/let-and-let
subject
https://relishapp.com/rspec/rspec-core/v/3-10/docs/subject 也值得一读。
如果您想要一个普通的、未缓存的方法,您只需编写一个常规的 def .. end
。参见 https://relishapp.com/rspec/rspec-core/v/3-10/docs/helper-methods/arbitrary-helper-methods
另一件事,Rails 土地中的术语“fixture”有一些特定的含义,它通常意味着您从 YAML 文件或类似文件加载数据库状态(参见 https://guides.rubyonrails.org/testing.html#the-low-down-on-fixtures) ... this is in contrast to "factories" which are much easier to work with but also significantly slower (see https://github.com/thoughtbot/factory_bot 这是制造工厂最常用的库)。
Ruby 和 RSpec 的新手所以请保持温柔。
我来自 Python 世界,特别是 pytest。您可以在 pytest 中做的一件事是在您的测试和其他固定装置中使用固定装置。在一个超简单的示例中,假设我们有一个 create
灯具,以及一个需要 create
的 delete
灯具。如果我们有一个同时使用 create
和 delete
固定装置的测试,create
只会被调用一次(即使 delete
使用 create
,pytest 知道它是已经调用了测试用例。这是一些示例 python 代码:
# test_fixture_reuse.py
import pytest
@pytest.fixture
def create_something():
"""Create tester object"""
#return MyTester(request.param)
print ("created_something")
@pytest.fixture
def delete_something(create_something):
"""Create tester object"""
#return MyTester(request.param)
print ("delete_something")
class TestIt:
def test_only_create(self, create_something):
print ("in test_only_create")
assert 1
def test_create_and_delete(self, create_something, delete_something):
print ("in test_create_and_delete")
assert 1
def test_only_delete(self, delete_something):
print ("in test_only_delete")
assert 1
运行 pytest -v test_fixture_reuse -s
returns 这个输出,和预期的一样:
test_parameterized_fixture.py::TestIt::test_only_create created_something
in test_only_create
PASSED
test_parameterized_fixture.py::TestIt::test_create_and_delete created_something
delete_something
in test_create_and_delete
PASSED
test_parameterized_fixture.py::TestIt::test_only_delete created_something
delete_something
in test_only_delete
PASSED
根据我在 Ruby 中的尝试,没有与 fixture
等效的概念,这意味着每个测试都需要控制调用流。因此,如果我们正在测试删除,测试将需要调用 create
,然后调用 delete
,但 delete
不会显式依赖于 create
。 RSpec 中的灯具通常似乎映射到模型,因此大多数搜索结果都不相关。
我的问题是 - 我怎样才能在 RSpec 中执行类似于上述 python 代码的操作?还是因为 Python 的经验,这是我的观点过于局限的事情之一,并且在 RSpec 中有一种类似的做事方式我没有正确搜索?
在 RSpec 中我们使用 let
作为记忆辅助方法,像这样:
RSpec.describe("my tests") do
let(:created_record) { MyRecord.create }
# using tap here to return the deleted record from the block
let(:destroyed_record) { created_record.tap(&:destroy) }
it("can create record") { created_record }
it("can destroy record") { destroyed_record }
it("memoizes created_record if called twice") { created_record; destroyed_record }
end
let
调用不会 运行 直到您第一次在测试中引用它们,并在该测试用例中为后续调用使用缓存的结果。 “测试用例”是指 it
块。如果您希望这些方法在每个测试用例开始时自动执行(无需显式调用该方法),您可以改用 let!
。结果仍将被缓存以供后续调用。参见 https://relishapp.com/rspec/rspec-core/v/2-11/docs/helper-methods/let-and-let
subject
https://relishapp.com/rspec/rspec-core/v/3-10/docs/subject 也值得一读。
如果您想要一个普通的、未缓存的方法,您只需编写一个常规的 def .. end
。参见 https://relishapp.com/rspec/rspec-core/v/3-10/docs/helper-methods/arbitrary-helper-methods
另一件事,Rails 土地中的术语“fixture”有一些特定的含义,它通常意味着您从 YAML 文件或类似文件加载数据库状态(参见 https://guides.rubyonrails.org/testing.html#the-low-down-on-fixtures) ... this is in contrast to "factories" which are much easier to work with but also significantly slower (see https://github.com/thoughtbot/factory_bot 这是制造工厂最常用的库)。