【问题标题】:RSpec for validating generated object or testing functions?RSpec 用于验证生成的对象或测试功能?
【发布时间】:2013-11-18 23:23:34
【问题描述】:

以下是我编写的第一批 RSpec 测试之一,在实施之后,我有几个问题悬而未决。

测试使用不同的输入运行相同的方法calculate,并验证生成的对象。然而,个别的小方法,如day_off? 没有明确测试。

我应该为各个方法编写测试而不是验证生成的对象吗?还是仅验证输出就足够了?还是应该同时测试各个方法和输出?

我认为典型的答案是“取决于”,但取决于什么?

我真的希望这不会作为一个主观问题而结束,因为我认为实际上可能会有一个有用的答案。

完整代码见:https://gist.github.com/asmand/d1ccbcd01789353c01c3

这是要测试的类:

class WeeklyFlexCalculator

  attr_reader :params

  def initialize(params)
    @params = params
  end

  def calculate
    group_efforts(
      (params.start_date..params.end_date).map do |date|
        daily_effort(date)
      end.compact
    )
  end

  def group_efforts(result)
    weekly = result.group_by { |e| get_week_key(e[:date]) }
    weekly.map do |key,w|
      {
        year: get_year_from_week_key(key),
        week: get_week_from_week_key(key),
        weekTarget: get_target_sum(w),
        weekEffort: get_effort_sum(w),
        efforts: w
      }
    end.sort { |a, b| b.efforts[0].date <=> a.efforts[0].date }
  end

  def daily_effort(date)
      target = get_target(date)
      effort = get_effort(date)
      return if target == 0 && effort == 0
      {
        date: date,
        effort: effort,
        target: target,
        diff: effort - target
      }
  end

  def get_target_sum(efforts)
    efforts.inject(0){|sum,e| sum + e[:target]}
  end

  def get_effort_sum(efforts)
    efforts.inject(0){|sum,e| sum + e[:effort]}
  end

  def get_week_key(date)
    date.cwyear.to_s + "|" + date.cweek.to_s
  end

  def get_year_from_week_key(key)
    key.split('|')[0]
  end

  def get_week_from_week_key(key)
    key.split('|')[1]
  end

  def get_target(date)
    day_off?(date) ? 0 : params.user.hours_per_day
  end

  def get_effort(date)
    ts = get_timesheet(date)
    ts.nil? ? 0.0 : ts.TimeInHours
  end

  def day_off?(date)
    date.wday == 0 or date.wday == 6 or params.holidays.include? date.to_s
  end

  def get_timesheet(date)
    params.timesheets.select {|ts| ts.Date == date.to_s}.first
  end
end

这是测试:

require './WeeklyFlexCalculator'

describe WeeklyFlexCalculator, "during Christmas week" do

  subject(:calculation) { WeeklyFlexCalculator.new(params).calculate }

  let(:params) do
    messages = {
      :start_date => Date.new(2013,12,23),
      :end_date => Date.new(2013,12,29),
      :holidays => ["2013-12-24", "2013-12-25", "2013-12-26"],
      :timesheets => [],
      :user => user
    }
    double(:params,messages)
  end

  let(:user) do
    messages = {
      :hours_per_day => 7.5
    }
    double(:user, messages)
  end

  let(:timesheet) do
    messages = {
      :Date => Date.new(2013,12,23).to_s,
      :TimeInHours => 5.0
    }
    double(:timesheet, messages)
  end

  context "with no work performed" do
    it { should have(1).item }

    context "the week calculated" do
      subject(:workweek) {calculation[0]}

      its([:year]) { should eq "2013" }
      its([:week]) { should eq "52" }
      its([:weekTarget]) { should eq 15.0 }
      its([:weekEffort]) { should eq 0.0 }

      context "the work efforts" do
        subject(:efforts) {workweek[:efforts]}

        it { should have(2).items }

        context "the first work effort" do
          subject(:effort) {efforts[0]}

          its([:target]) {should eq 7.5}
          its([:diff]) {should eq -7.5}
          its([:effort]) {should eq 0.0}
        end
      end
    end
  end

  context "with work effort on normal day" do
    before do
      params.stub(:timesheets => [timesheet])
    end

    it { should have(1).item }

    context "the week calculated" do
      subject(:workweek) {calculation[0]}

      its([:year]) { should eq "2013" }
      its([:week]) { should eq "52" }
      its([:weekTarget]) { should eq 15.0 }
      its([:weekEffort]) { should eq 5.0 }

      context "the work efforts" do
        subject(:efforts) {workweek[:efforts]}

        it { should have(2).items }

        context "the first work effort" do
          subject(:effort) {efforts[0]}

          its ([:effort]) { should eq 5.0 }
          its ([:diff]) { should eq -2.5 }
        end
      end
    end
  end

  context "with work effort on a holiday" do
    before do
      timesheet.stub(:Date => Date.new(2013,12,24).to_s)
      params.stub(:timesheets => [timesheet])
    end

    it { should have(1).item }

    context "the week calculated" do
      subject(:workweek) {calculation[0]}

      its([:year]) { should eq "2013" }
      its([:week]) { should eq "52" }
      its([:weekTarget]) { should eq 15.0 }
      its([:weekEffort]) { should eq 5.0 }

      context "the work efforts" do
        subject(:efforts) {workweek[:efforts]}

        it { should have(3).items }

        context "the first work effort" do
          subject(:effort) {efforts[0]}

          its ([:effort]) { should eq 0.0 }
          its ([:diff]) { should eq -7.5 }
        end

        context "the second work effort" do
          subject(:effort) {efforts[1]}

          its ([:effort]) {should eq 5.0}
          its ([:diff]) { should eq 5.0}
        end
      end
    end
  end
end

【问题讨论】:

    标签: ruby rspec


    【解决方案1】:

    我会全部测试。对我来说,知道day_off? 在功能上是正确的,我感到很欣慰。如果我不测试那个方法,我总是会有点紧张,因为我对calculate 的测试可能只是因为day_off? 中的一些未知错误而“神奇地”工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-08
      • 2014-07-05
      相关资源
      最近更新 更多