【问题标题】:Identical rspec tests succeed and fail respectively相同的 rspec 测试分别成功和失败
【发布时间】:2013-12-02 13:21:52
【问题描述】:

我正在编写一个简单的程序,用于将汇编语言指令转换为我们正在构建的处理器各自的 24 位二进制指令。我正在用 Ruby (2.0.0) 编写程序并使用 Rspec (2.14.6) 对其进行测试。奇怪的是我可以运行两个相同的测试——一个失败,另一个成功。这是一个例子:

测试失败:

it "Returns 24-bit binary instruction for valid line of assembly code" do

  #...25 other instructions are tested before these...
  expect(Parser.build_instruction("Li r2, 0000111001010001")).to eq("001000001110010100010010")
  expect(Parser.build_instruction("Li r2, 0000111001010001")).to eq("001000001110010100010010")

end

通过测试:

it "Returns 24-bit binary instruction for valid line of assembly code" do

  #...25 other instructions are tested before these...
  expect(Parser.build_instruction("Li r2, 0000111001010001")).to eq("001000001110010100010010")
  #expect(Parser.build_instruction("Li r2, 0000111001010001")).to eq("001000001110010100010010")

end

我开始怀疑你是否可能在一个 it...do...end 块中进行太多测试(或者运行相同的 expect 两次是否有问题),但我尝试复制最后两个上面的一些测试,并且测试继续通过。我还尝试将一些测试拉到他们自己的it...do...end 块中,然后导致不同的期望(之前通过)失败。我有点困惑。想法?


附:我实际上不想运行相同的expect 两次,但它对以下两个测试做了奇怪的事情,所以我将第二个测试更改为与第一个匹配,但它仍然失败。另外,如果我注释掉第一个测试(这两个),第二个通过。换句话说,只有当我同时运行两个测试时它才会失败——而不是另一个。

it "Returns 24-bit binary instruction for valid line of assembly code" do

  #...25 other instructions are tested before these...
  expect(Parser.build_instruction("Li r2, 0000111001010001")).to eq("001000001110010100010010")
  expect(Parser.build_instruction("Li r2, 111001010001")).to eq("001000001110010100010010")

end

输出:

1) Parser Returns 24-bit binary instruction for valid line of assembly code
 Failure/Error: expect(Parser.build_instruction("Li r2, 111001010001")).to eq("001000001110010100010010")

   expected: "001000001110010100010010"
        got: "0010000011100101000100001110010100010010"

   (compared using ==)
 # ./spec/parser_spec.rb:65:in `block (2 levels) in <top (required)>'

编辑 1

@micahbf 和@felix,我有一个方法,它接受一个输入文件,每行都有一条指令,以便将其转换为二进制代码。我只是在一个输入文件上运行它,Li r2, 111001010001 重复了大约 50 次(我应该在之前完成 :/),并且只有第一个输出是正确的——后续行将 1110010100010010 附加到末尾,如...

001000001110010100010010
0010000011100101000100001110010100010010
00100000111001010001000011100101000100001110010100010010
etc..

所以...这不是 rspec ;) 我将不得不进一步深入研究我的代码以找出问题所在。


编辑 2

对于那些想知道(我想知道)的人,在我的代码中,我发现了一个地方,我必须返回对对象的引用而不是值。这导致原始对象被修改(我的头受伤并且测试失败!):

def self.get_reg_code reg
    @logger.debug { "Getting register code for [ #{reg.inspect} ]" }
    reg.upcase!
    if register? reg
      return CODES["#{reg}".to_sym] # <-- Returning object reference!
    else
      return reg
    end
end

我改成这样了:

def self.get_reg_code reg
    @logger.debug { "Getting register code for [ #{reg.inspect} ]" }
    reg.upcase!
    if register? reg
      reg_code = CODES["#{reg}".to_sym].clone # <-- Return a copy--not the referenced object!
      return reg_code
    else
      return reg
    end
end

【问题讨论】:

  • 能否提供::build_instruction的出处?似乎Parser 代码中的某些内容导致了这种情况发生。您是否测试过在 RSpec 之外运行这些方法(包括两次相同的方法)?
  • @micahbf:“您是否测试过在 RSpec 之外运行这些方法(包括两次相同的方法)”- 好建议。我在 rspec 之外运行过它——但不是多次。我更新了我的问题:)

标签: ruby rspec


【解决方案1】:

抱歉,看起来 rspec 是正确的而 Parser 是错误的。 :)

特别是在失败的情况下(“0010000011100101000100001110010100010010”),Parser 看起来好像有某种状态来存储指令。

为了检验这个假设,第三次运行代码(但第二次没有预期)。如果失败然后显示为“001000001110010100010000111001010001001000100001110010100010010”,则您为我的状态假设收集了一个论据。

另一种“测试”的方法是为每次调用 build_instructions 创建一个新的解析器实例。不是要真正规避这个问题,而是要调查它。

你可能还需要类似的东西

describe "#build_instruction"
  it "resets state" do
    expect(Parser.build_instruction("Li r2, 0000111001010001")).to eq("001000001110010100010010")
    expect(Parser.build_instruction("Li r2, 111001010001")).to     eq("001000001110010100010010")
  end
end

您在哪里明确测试行为。

【讨论】:

  • 确实,我同意。似乎状态正在坚持。对于处理器而言,这实际上可能是一件好事,因为最佳代码路径(处理器方面)可能取决于先前的指令。当然只是猜测:)
  • @Felix:“rspec 是对的,Parser 是错的”——我认为你是对的 :) 我更新了我的问题。
【解决方案2】:

在测试之前有一个已知的状态很重要。 出于这个原因,应该对每个测试进行设置和拆卸。 还有一个一般建议是“每个测试只有 1 个断言”。

基于此,我会追求将测试移入它自己的 it...end 块。你提到尝试这个但有问题但没有显示问题。我会走这条路。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2017-02-07
    • 1970-01-01
    相关资源
    最近更新 更多