【问题标题】:Passing Index Loop Vars To Objects in Ruby with TDD使用 TDD 将索引循环变量传递给 Ruby 中的对象
【发布时间】:2018-02-15 06:09:59
【问题描述】:

我正在尝试在 TDD 和 Ruby 中完成一组非常简单的测试。

我遇到的问题是试图将一系列值从测试传递给正在测试的对象。

代码的目的是通过 for 循环迭代地向对象发送一系列“猜测”值来猜测正确的“秘密数字”,这些值的范围在 1 到 10 之间。

测试应确认以下内容...

  1. 当 'guess' 值小于 5(5 是为 'secret number 设置的固定值)时,对象应返回符号 ':less'。

  2. 当 'guess' 值等于 5 时,对象应返回符号 ':found_secret_number'。

  3. 当 'guess' 值大于 5 时,对象应返回一个符号 ':greater'。

我发现虽然循环确实循环并生成所需的值,但循环仅将生成的最终循环值分配给每个测试(该值为 10)。我猜这个测试会在循环中创建所有测试,然后分配最后为 lop 变量设置的任何值(如果您快速查看代码,它可能更有意义......)。

该测试使用分配给对象的静态变量,因此从功能的角度来看,该类很好,但我不希望 100% 的行覆盖率(例如“猜测”值为 3、5 和 7),但是想要 100% 的值覆盖率(例如 1、2、3、4、5、6、7、8、9 和 10)。

我已经玩过并修改了代码,但找不到分配我正在寻找的值范围 (1..10) 的方法,而不必为值覆盖率编写 10 个静态案例,所以有没有人建议如何在不使用十个静态案例的情况下做到这一点?:)

顺便说一句,我仍在学习,所以如果你能尽可能简单地回答任何问题,那将有所帮助;)同样,我解释问题有助于你理解它,任何关于我如何解释问题的反馈更好的将不胜感激;相信大家都知道,通讯非常重要,我也在努力改进这一点。

谢谢!:)

require 'rspec'

class Game

  def initialize(secret_number)
    @secret_number = secret_number
  end

  def guess(number)
    if (number < @secret_number)
      :lower
    elsif
      (number > @secret_number)
      puts ("number is: " + number.to_s)

      :greater
    elsif (number == @secret_number)
      :found_secret_number
    end
  end
end

# 'describe' is a method, that is passed a 'Game' class,
# it's not normally written like this but I've just shown it this
# way, in this case, to affirm its just plain old Ruby.
describe(Game) do
  subject { Game.new(5) }
  describe '#guess' do
    for i in 1..10
      if (i < 5)
        puts ("i is less than 5, it is: " + i.to_s)
        context 'when guessing a number that is lower than the secret number ' do
          it 'returns the symbol :lower' do
            expect(subject.guess(val)).to eq(:lower)
          end
        end

      elsif (i == 5)
        puts ("i is equal to 5, it is: " + i.to_s)
        context 'when guessing a number that is the SAME as the secret number ' do
          it 'returns the symbol :found_secret_number' do
            expect(subject.guess(val)).to eq(:found_secret_number)
          end
        end

      elsif (i > 5)
        puts ("i is greater than 5, it is: " + i.to_s)
        context 'when guessing a number that is higher than the secret number ' do
          it 'returns the symbol :greater' do
            expect(subject.guess(val)).to eq(:greater)
            end
         end
      end
    end
  end
end

【问题讨论】:

  • Ruby 很少(如果有的话)使用实际的for 循环。这里通常使用(1..10).each do |i|10.times do |i|,具体取决于您希望如何抵消。

标签: ruby loops rspec tdd test-coverage


【解决方案1】:

基本上所有花哨的测试方法,如describecontextit 都只是定义测试方法的方式。 Rspec 然后在实际运行测试时调用这些测试方法。因此,在这样的循环中调用它们并没有真正意义,因为您正在动态定义测试(在您的情况下绝对不需要它时)。相反,您应该摆脱循环,并在这些测试用例中定义您的所有期望。例如:

describe(Game) do
  subject { Game.new(5) }
  describe '#guess' do
    context 'when guessing a number that is lower than the secret number ' do
      it 'returns the symbol :lower' do
        (1..4).each { |val| expect(subject.guess(val)).to eq(:lower) }
      end
    end

    context 'when guessing a number that is the SAME as the secret number ' do
      it 'returns the symbol :found_secret_number' do
        expect(subject.guess(5)).to eq(:found_secret_number)
      end
    end

    context 'when guessing a number that is higher than the secret number ' do
      it 'returns the symbol :greater' do
        (6..10).each { |val| expect(subject.guess(val)).to eq(:greater) }
     end
    end
  end
end

然后当我使用 rspec 运行该文件时,我得到了

...

Finished in 0.02421 seconds (files took 0.26321 seconds to load)
3 examples, 0 failures

【讨论】:

  • 我刚刚在另一篇文章中完成了输入。
  • 是的,我不确定该回复哪个。但另一个问题似乎没有足够的上下文。
  • 嗨@Max,很好的解决方案,谢谢你的帮助,你说的很有道理。关于另一个问题,我只是把它提出来,因为我没有对这个问题做出任何回应,并想如果我以更通用的方式提出这个问题,它可能会引起更多的兴趣,确实意味着很痛苦;)再次感谢: )
  • 点击那个绿色复选标记就是我需要的全部感谢。 ;)
猜你喜欢
  • 2017-06-20
  • 2016-05-23
  • 1970-01-01
  • 2015-12-10
  • 2013-01-27
  • 2017-04-01
  • 2013-06-19
  • 2023-04-07
  • 1970-01-01
相关资源
最近更新 更多