我正在编写一个简单的程序,将汇编语言指令转换为我们正在构建的处理器的各自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
块中,然后导致不同的期望(之前通过)失败。我有点困惑。想法?
P.S。我实际上并不想两次运行相同的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)>'
@micahbf和@felix,我有一个方法,它接受一个输入文件,每行都有一条指令,用于转换为二进制代码。我只是在一个输入文件上运行它,Li r2, 111001010001
重复约50次(我之前应该做的事:/),只有第一个输出是正确的 - 后续行添加1110010100010010
到最后...
001000001110010100010010
0010000011100101000100001110010100010010
00100000111001010001000011100101000100001110010100010010
etc..
所以...这不是rspec;)我将不得不深入挖掘我的代码以找出粘贴的位置。
对于那些希望知道的人(我愿意),在我的代码中,我找到了一个我必须返回对象的引用而不是值的位置。这导致原始对象被修改(我的头部受伤并且测试失败!):
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
答案 0 :(得分: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
您明确测试行为的地方。
答案 1 :(得分:0)
在测试之前拥有一个已知状态很重要。 因此,应该进行每次测试的设置和拆卸。 还有一个普遍的建议是“每次测试只有1个断言”。
基于此,我会继续将测试转移到自己的...结束块。你提到尝试这个但有一个问题,但没有显示问题。我会追求这条路。