我正在编写一个简单的程序,将汇编语言指令转换为它们各自的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发布于 2013-11-19 06:26:26
对不起,看起来rspec是对的,Parser是错的,。:)
特别是考虑到它的失败(“001000001110010100010000111001010010”),它看起来就像是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在那里显式地测试行为。
发布于 2013-11-19 14:16:51
在测试前有一个已知的状态是很重要的。因此,应该对每个测试进行设置和删除。还有一项一般性建议,即“每次测试只有一个断言”。
基于此,我将继续将测试移到它自己的it...end块中。你提到尝试,但有一个问题,但没有显示问题。我会走这条路。
https://stackoverflow.com/questions/20063942
复制相似问题