使用Rspec进行突变测试

时间:2018-10-03 01:34:00

标签: ruby rspec mutation-testing

我正在尝试使用rspec对某些红宝石代码执行突变测试。我只是在学习红宝石,我真的不知道我是否做得对。我要测试的部分代码是:

class Cipher

 def initialize()
  @a_offset = 65 #'A'.unpack('C').first
  @z_offset = 90 #'Z'.unpack('C').first
 end

 def encode(key, plain_text)
  key_offset = key.upcase.unpack('C').first

  cipher_text = plain_text.upcase.split('').collect do |letter| 
   cipher_letter = (letter.unpack('C').first + key_offset - @a_offset)
   if cipher_letter > @z_offset
    cipher_letter -= ( @z_offset - @a_offset + 1 )
   end
   cipher_letter.chr
 end

 return cipher_text.join
end

到目前为止,我的测试套件如下所示:

require 'rspec'
require 'Cipher'

describe "#initialize" do 
   it "should have correct @a_offset" do
     encoder = Cipher.new()
     expect(encoder.instance_variable_get(:@a_offset)).to eq 65
   end 

   it "should have correct @z_offset" do
     encoder = Cipher.new()
     expect(encoder.instance_variable_get(:@z_offset)).to eq 90
   end
 end 

describe "#encode" do
   it "It should correctly encode Caesar with key = A"do
     encoder = Cipher.new()
     expect(encoder.encode('R', 'CAESAR')).to eq ("TRVJRI")
   end 
end

运行rspec时,我的3个测试通过了。但是,当我在此套件上使用突变测试时,我只会杀死3/343,这不是很好。

1 个答案:

答案 0 :(得分:0)

由于您的目标是开发一个足够突变的测试套件,因此,未经杀灭的突变体实质上可以为要测试的内容提供指导。理想情况下,您的问题应该为未由测试套件杀死的生成突变体提供一些示例,以便其他人可以评论如何编写可杀死它们的测试。

让我尝试通过一般建议和示例来最好地回答您的问题。 我不熟悉您使用的特定突变测试工具,但通常应遵循与以下类似的过程*:

  1. 选择一个不会被您的测试套件杀死的突变体,并确定它是否可以被杀死(在语义上,突变体可能与您的程序等效-如果可以,请将其从突变体池中丢弃)。

  2. p>
  3. 写一个杀死所选突变体的测试-也就是说,编写通过原始程序但对该突变体失败的测试。

    • 确定适当的输入来触发由突变体引入的错误行为。
    • 确定一个可以对程序的预期行为/输出进行断言的合适的测试oracle(即,可以通过原始程序但在突变体上失败的测试oracle)。

请记住,您的目标不是 写最小限度的测试来杀死所有突变体,而是编写对您的项目有意义并作为副产品杀死突变体的测试。再说一次,如果您可以提供测试套件不会杀死的突变体的一些具体例子,那么我和其他人可以更好地评论缺少哪些测试。

示例:假设您有一个引入以下错误的变量(即,在原始程序的if语句中更改了关系运算符): - if cipher_letter > @z_offset + if cipher_letter >= @z_offset 要杀死该突变体,需要进行一项检查边界条件的测试-即一种将至少一个字符编码为“ Z”的测试。您当前的测试套件没有这样的测试。

*此过程描述了传统的突变测试。最近的研究[1][2]建议(1)并非所有可杀死的突变体都应被杀死(某些突变体引发根本没有意义的测试),(2)等效突变体可能表明您的问题您可能想要修复而不是丢弃等效变体的程序(例如,不必要的冗余或歧义)。