Ruby 基于机器(反应器)的规范测试代码
我正在尝试整个Ruby 基于机器(反应器)的规范测试代码,ruby,testing,amqp,eventmachine,minitest,Ruby,Testing,Amqp,Eventmachine,Minitest,我正在尝试整个BDD方法,并想测试我正在编写的基于AMQP的普通Ruby应用程序。在选择了Minitest作为测试框架,以平衡其功能和表达能力,而不是其他恰当命名的植物框架之后,我开始编写本规范: # File ./test/specs/services/my_service_spec.rb # Requirements for test running and configuration require "minitest/autorun" require "./test/specs/spe
BDD
方法,并想测试我正在编写的基于AMQP
的普通Ruby
应用程序。在选择了Minitest
作为测试框架,以平衡其功能和表达能力,而不是其他恰当命名的植物框架之后,我开始编写本规范:
# File ./test/specs/services/my_service_spec.rb
# Requirements for test running and configuration
require "minitest/autorun"
require "./test/specs/spec_helper"
# External requires
# Minitest Specs for EventMachine
require "em/minitest/spec"
# Internal requirements
require "./services/distribution/my_service"
# Spec start
describe "MyService", "A Gateway to an AMQP Server" do
# Connectivity
it "cannot connect to an unreachable AMQP Server" do
# This line breaks execution, commented out
# include EM::MiniTest::Spec
# ...
# (abridged) Alter the configuration by specifying
# an invalid host such as "l0c@alho$t" or such
# ...
# Try to connect and expect to fail with an Exception
MyApp::MyService.connect.must_raise EventMachine::ConnectionError
end
end
我已经注释掉了包含的功能,它应该强制规范在EventMachine
反应器中运行,如果我包含它,我会遇到一个关于(我想)内联类的更粗略的异常:NoMethodError:undefined方法“include”for#
我正在测试的代码,即该服务中的connect
方法是基于以下代码的:
# Main namespace
module MyApp
# Gateway to an AMQP Server
class MyService
# External requires
require "eventmachine"
require "amqp"
# Main entry method, connects to the AMQP Server
def self.connect
# Add debugging, spawn a thread
Thread.abort_on_exception = true
begin
@em_thread = Thread.new {
begin
EM.run do
@connection = AMQP.connect(@settings["amqp-server"])
AMQP.channel = AMQP::Channel.new(@connection)
end
rescue
raise
end
}
# Fire up the thread
@em_thread.join
rescue Exception
raise
end
end # method connect
end
end # class MyService
整个“异常处理”只是试图将异常冒泡到一个我可以捕获/处理它的地方,但不管是否使用开始
和提升
位,我在运行规范时仍然得到相同的结果:
EventMachine::ConnectionError:无法解析服务器地址
,这实际上是我所期望的,但是Minitest
不能很好地处理整个反应堆概念,并且由于该异常
而导致测试失败
接下来的问题是:如何使用Minitest
的规范机制来测试EventMachine
相关的代码?关于黄瓜的问题也一直悬而未决,也没有回答
或者我应该专注于我的主要功能(例如,发送消息并查看消息是否被发送/接收),而忽略边缘案例?任何洞察都会有真正的帮助
当然,这可以归结为我上面写的代码,也许这不是编写/测试这些方面的方式。可能是
关于我的环境的说明:ruby 1.9.3p194(2012-04-20)[i386-mingw32]
(是的,Win32:>),minitest 3.2.0
,eventmachine(1.0.0.rc.4 x86-mingw32)
,amqp(0.9.7)
提前谢谢 如果这个回答太迂腐,那么很抱歉,但是我认为如果您区分单元测试和验收测试,那么编写测试和库会容易得多
BDD与TDD
注意不要将BDD与TDD混淆。虽然两者都非常有用,但在验收测试中尝试测试每个边缘情况时可能会导致问题。例如,BDD是关于测试您试图用您的服务完成什么,这与您对消息队列所做的事情比连接到队列本身更相关。在我看来,当您尝试连接到一个不存在的消息队列时发生的事情更符合单元测试的范畴。还值得指出的是,您的服务不应该负责测试消息队列本身,因为这是AMQP的责任
BDD
虽然我不确定您的服务到底应该做什么,但我认为您的BDD测试应该如下所示:
在进行TDD时,让测试在代码组织方面为您提供一些指导。测试一个创建新线程并在该线程内运行EM的方法是困难的,但单独对其中任何一个进行单元测试并不困难。因此,考虑将主线程代码放在单独的函数中,可以单独进行单元测试。然后,您可以在单元测试
connect
方法时删除该方法。此外,您可以测试AMQP抛出错误时发生的情况(这是您的代码负责处理的),而不是测试尝试连接到坏服务器时发生的情况(测试AMQP)。在这里,您的单元测试可以剔除AMQP.connect的响应以抛出异常。感谢您的见解,这确实让事情变得更加全面,你看穿了我的问题,并在这个过程中启发了我:)最终证明有效的方法是在规范中用一个开始--解救块包装对连接的调用,其中必须引发断言。然而,测试非常慢(重试、超时等),我可能会完全放弃它,主要是考虑到Ben在下面的答案中的洞察力。