使用 Rspec 和 C 扩展进行单元测试
Unit testing with Rspec and C extensions
这些天似乎每个人都在谈论 TDD 和 BDD,所以我想我尝试一下小型家庭项目。
一个简短的背景 我正在用 C 扩展开发 class Device
,它与本机 C API 交互,用于控制电灯开关等远程设备。
为了让测试更独立于平台,我已经模拟了 C API 来表现得像原来的那样,但它没有控制硬件,而是设置了一个全局 ruby 状态变量(一个哈希包含所有设备).
这一切都很好并且按预期工作。我可以编译并 link 到这个库而不是真正的库。
现在我需要帮助的部分是如何按照某种最佳实践进行测试 我有以下规范来描述我的 Device
class
describe Device do
describe ".get" do
context "Specified id exists" do
it "Returns a instance of Device"
it "Device has same id as specified"
end
context "Specified id is undefined"
it "throws UndefinedDeviceException"
end
end
describe "#turn_on" do
context "Device supports turning on" do
# I set up the mock state to have a device that supports on..
# how do i get the Device instance here? is it ok to depend on
# Device.get method?
it "Returns true"
it "Set device state to on" # Check mocked state
end
end
.....
end
现在,据我所知,在每个上下文中,我为我的模拟库设置状态以反映我想要测试的内容,并调用该方法。
这适用于静态方法 Device.get(id)
因为这个 returns 一个新的 Device
我不确定如何测试实例方法。如果我想测试 turn_on 方法,我首先需要有一个 Device
的实例,这意味着我需要调用 Device.get
来实际获取设备?但如果是这样的话,我是不是又 "testing" class 方法得到了?我想我在这里真正要问的是,如果它依赖于外部库,那么在 Rspec 中获取对象实例是什么好的做法。
调用 Device.get
听起来很适合我 - 在这些测试中,您将测试返回的 Device 对象的某些方法,而不是 get 本身。
虽然测试应该是独立的,但您不可避免地会得到一些使用其他测试测试的方法的测试 - 例如,活动记录测试套件有大量 create
和 [=12 的测试=] 但这些方法也被许多其他测试使用。
这方面的棘手之处在于决定在什么级别进行模拟 - 您最终可以只测试您的模拟和 none(或很少)实际实施。
这些天似乎每个人都在谈论 TDD 和 BDD,所以我想我尝试一下小型家庭项目。
一个简短的背景 我正在用 C 扩展开发 class Device
,它与本机 C API 交互,用于控制电灯开关等远程设备。
为了让测试更独立于平台,我已经模拟了 C API 来表现得像原来的那样,但它没有控制硬件,而是设置了一个全局 ruby 状态变量(一个哈希包含所有设备).
这一切都很好并且按预期工作。我可以编译并 link 到这个库而不是真正的库。
现在我需要帮助的部分是如何按照某种最佳实践进行测试 我有以下规范来描述我的 Device
class
describe Device do
describe ".get" do
context "Specified id exists" do
it "Returns a instance of Device"
it "Device has same id as specified"
end
context "Specified id is undefined"
it "throws UndefinedDeviceException"
end
end
describe "#turn_on" do
context "Device supports turning on" do
# I set up the mock state to have a device that supports on..
# how do i get the Device instance here? is it ok to depend on
# Device.get method?
it "Returns true"
it "Set device state to on" # Check mocked state
end
end
.....
end
现在,据我所知,在每个上下文中,我为我的模拟库设置状态以反映我想要测试的内容,并调用该方法。
这适用于静态方法 Device.get(id)
因为这个 returns 一个新的 Device
我不确定如何测试实例方法。如果我想测试 turn_on 方法,我首先需要有一个 Device
的实例,这意味着我需要调用 Device.get
来实际获取设备?但如果是这样的话,我是不是又 "testing" class 方法得到了?我想我在这里真正要问的是,如果它依赖于外部库,那么在 Rspec 中获取对象实例是什么好的做法。
调用 Device.get
听起来很适合我 - 在这些测试中,您将测试返回的 Device 对象的某些方法,而不是 get 本身。
虽然测试应该是独立的,但您不可避免地会得到一些使用其他测试测试的方法的测试 - 例如,活动记录测试套件有大量 create
和 [=12 的测试=] 但这些方法也被许多其他测试使用。
这方面的棘手之处在于决定在什么级别进行模拟 - 您最终可以只测试您的模拟和 none(或很少)实际实施。