我正在尝试整个BDD方法,并想测试我正在编写的 Vanilla 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

我已经注释掉了the em-minitest-spec gem的功能,该功能应强制规范在EventMachine react 器中运行,如果包含它,我会遇到关于(我想)内联类(甚至是NoMethodError: undefined method 'include' for #<#<Class:0x3a1d480>:0x3b29e00>)的更为粗略的异常。

我正在测试的代码(即该Service中的connect方法)基于on this article,看起来像这样:
# 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

整个“异常处理”仅是尝试将异常冒泡到我可以捕获/处理的地方,无论有无beginraise位,都无济于事,运行该命令时仍然会得到相同的结果规范:
EventMachine::ConnectionError: unable to resolve server address,实际上实际上是我所期望的,但是Minitest不能在整个 react 堆概念中很好地发挥作用,并且基于Exception未能通过测试。

问题仍然存在:如何使用EventMachine的规范机制测试与Minitest相关的代码? Another question也一直在徘徊关于Cucumber,也未得到解答。

还是我应该专注于我的主要功能(例如消息传递并查看消息是否被发送/接收)而忘记边缘情况?任何见识都将真正有帮助!

当然,所有这些都可以归结为我上面编写的代码,也许这不是编写/测试这些方面的方式。可能!

关于我的环境的注释:ruby 1.9.3p194 (2012-04-20) [i386-mingw32](是,Win32:>),minitest 3.2.0eventmachine (1.0.0.rc.4 x86-mingw32)amqp (0.9.7)
提前致谢!

最佳答案

抱歉,如果此响应过于繁琐,但是如果您区分单元测试和验收测试,那么我认为您将更容易编写测试和库。

BDD与TDD

注意不要将BDD与TDD混淆。尽管两者都很有用,但是当您尝试在验收测试中测试每个边缘情况时,可能会导致问题。例如,BDD是关于测试您要通过服务完成的工作,与连接消息队列本身相比,它与消息队列的工作更多有关。我认为,当您尝试连接到不存在的消息队列时会发生什么,这更适合单元测试的领域。还值得指出的是,您的服务不应该负责测试消息队列本身,因为这是AMQP的责任。

BDD

虽然我不确定您的服务应该做什么,但是我可以想象您的BDD测试应该看起来像这样:

  • 启动服务(如果需要,可以在测试中的单独线程中执行此操作)
  • 写一些东西到队列
  • 等待您的服务响应
  • 检查服务结果

  • 换句话说,BDD(或接受测试或集成测试,不过您要考虑一下)可以将您的应用程序视为应该提供某些功能(或行为)的黑匣子。这些测试使您始终专注于最终目标,但更多地是为了确保一两个黄金用例,而不是确保应用程序的健壮性。为此,您需要分解为单元测试。

    时分双工

    在执行TDD时,请让测试在代码组织方面为您提供一些指导。测试创建新线程并在该线程中运行EM的方法很困难,但是对其中一个进行单元测试并不难。因此,请考虑将主线程代码放入一个单独的函数中,您可以对其进行单独的单元测试。然后,可以在对connect方法进行单元测试时将其 stub 。另外,您可以测试当AMQP引发错误时(代码的责任),而不是测试尝试连接到故障服务器(测试AMQP)时发生的情况。在这里,您的单元测试可以 stub AMQP.connect的响应以引发异常。

    10-08 03:11