【问题标题】:Configure rspec to show 'E' error when running an erroneous test配置 rspec 以在运行错误测试时显示“E”错误
【发布时间】:2013-12-16 12:29:03
【问题描述】:

TL;DR:当 rspec 遇到错误时,如何停止中止所有规范?

在运行 rails 的内置测试套件时,我得到类似于以下的输出:

...F..F.EE...E

Finished in 0.64396 seconds
14 examples, 2 failures, 3 errors 

. 代表通过测试,F 代表失败测试,​​E 代表错误测试。一个失败的测试意味着你的 Rails 应用程序的代码失败了,一个错误的测试意味着你的实际测试的代码失败了。错误的测试永远不会是好的。

不过,我喜欢的是,当程序遇到 E 时,它会继续执行所有其他测试。

我正在使用 rpsec,虽然我喜欢它,但我有点讨厌它遇到错误规范时如何完全放弃幽灵,并退出所有规范,如下所示:

12:39:37 - INFO - Running: spec
/usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/validations.rb:57:in `save!': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)
    from /usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/attribute_methods/dirty.rb:41:in `save!'
    from /usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/transactions.rb:275:in `block in save!'
    from /usr/local/rvm/rubies/ruby-1.9.3-p392/lib/ruby/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'

虽然我确实喜欢错误报告,但我真的希望它在遇到错误规范时继续运行所有规范。而不是上面的输出,我真的想要以下内容:

12:40:01 - INFO - Running: spec
...F..F..E

Failures:

  1) User A new user can be created email should == "awesomedog@hotmail.co.uk"
     Failure/Error: its(:email) { should == "awesomedog@hotmail.co.uk" }
       expected: "awesomedog@hotmail.co.uk"
            got: "awesomedozg@hotmail.co.uk" (using ==)
     # ./spec/model/user_spec.rb:11:in `block (3 levels) in <top (required)>'

  2) User A new user can be created should not be valid
     Failure/Error: it { should_not be_valid }
       expected valid? to return false, got true
     # ./spec/model/user_spec.rb:20:in `block (3 levels) in <top (required)>'

Errors:

  1) `save!': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)

Finished in 0.64396 seconds
10 examples, 2 failures, 1 error

Failed examples:

rspec ./spec/model/user_spec.rb:11 # User A new user can be created email should == "awesomedog@hotmail.co.uk"
rspec ./spec/model/user_spec.rb:20 # User A new user can be created should not be valid

我在我的规范中使用 factory-girl 和 factory,并在每个规范之间使用数据库清理器来清理我的数据库。我正在使用 rspec-guard 在任何项目文件(tmplogdb 中的文件除外)被保存的情况下运行所有​​规范。因为如果 rpsec 命中,它会不断消失一个错误,我收到了这个错误:

How can I clean my database between erroneous rspec specs?

基本上,database-cleaner 被配置为在规范开始和规范结束时清理我的数据库。因为 rspec 在遇到错误时会在规范中间退出,所以 database-cleaner 不会检测到规范已经完成,因此永远不会清理我的数据库。这意味着我必须使用我的数据库 shell 手动清空它。

我还希望查看我所有其他规格的状态,即使其中一个是错误的! Rspec 在这方面真的很傻我想!

这是我的工厂和规格:

spec/model/user_spec.rb:

require 'spec_helper'

describe User do
    context "Valid user" do
        user = FactoryGirl.create(:user_with_all_valid)

        subject { user }
        its(:first_name) { should == "Jimmy" }
        its(:last_name) { should == "Thehat" }
        its(:profile_name) { should == "Jimbohatboy893" }
        its(:email) { should == "awesomedog@hotmail.co.uk" }
        its(:password) { should == "thisisasupersecretpassword12234234" }
        its(:password_confirmation) { should == "thisisasupersecretpassword12234234" }
    end
end

spec/factories.rb:

FactoryGirl.define do

    factory :user_with_all_valid, class: User do
        first_name "Jimmy"
        last_name "Thehat"
        profile_name "Jimbohatboy893"   
        email "awesomedog@hotmail.co.uk"
        password "thisisasupersecretpassword12234234"
        password_confirmation "thisisasupersecretpassword12234234"
    end
end

【问题讨论】:

  • 您究竟是如何运行规范的?你在做 rspec spec 还是 rake specrake spec 如果您不使用它可能会有所帮助。
  • 好点,更新问题
  • 您使用的是stub! 还是before :all?这些会因情况而异。
  • 仍然不清楚您是如何运行测试的 - 通过警卫?我会在处理这个问题时禁用它。像 guard 和 spork 这样的工具偶尔会引起问题,以及为什么许多人停止使用它们。
  • 对不起,更具体地说,我正在使用 rspec-guard。所以是的,所有的规范/测试都是由 rspec-guard 在文件保存时自动启动的。

标签: ruby-on-rails rspec


【解决方案1】:

你的问题是这一行:

context "Valid user" do
  user = FactoryGirl.create(:user_with_all_valid)  # Right here!
  ...

测试设置应始终在before 块中完成;变量定义在let 块中完成。在您的测试定义中执行此操作将导致 rspec 失败,如所述。通常,您应该只在context 块中包含 rspec 指令(之前、之后、让、主题、它、其等)。如果您正在运行测试设置、应用程序代码等,您将面临此类问题。你想要的是:

context "Valid user" do
  let(:user) { FactoryGirl.create(:user_with_all_valid) }

或:

context "Valid user" do
  before { @user = FactoryGirl.create(:user_with_all_valid) }

然后套件将按预期运行整个事情,并报告未能正确执行其定义设置(用户定义)的测试失败,而不是轰炸整个套件。

【讨论】:

    【解决方案2】:

    使用详细的序列:https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#sequences

    可以使用序列生成特定格式的唯一值(例如,电子邮件地址)。序列是通过在定义块中调用序列来定义的,序列中的值是通过调用FactoryGirl.generate来生成的:

    # Defines a new sequence
    FactoryGirl.define do
      sequence :email do |n|
        "person#{n}@example.com"
      end
    end
    
    FactoryGirl.generate :email
    # => "person1@example.com"
    
    FactoryGirl.generate :email
    # => "person2@example.com"
    ...
    

    只需让您的规范检查电子邮件地址的一部分是否正确,例如@something.com 或使用正则表达式进行比较,例如match(/person.*@something\.com/)

    【讨论】:

      【解决方案3】:

      由于模型验证,您每次都需要有一个唯一的电子邮件。
      顺便说一句,其他 7 或 8 个正在通过(点)。

      尝试添加:

      new_user_time = Time.new
      

      保存当前时间。 然后将其传递给创建用户工厂。 然后用它来检查用户的电子邮件是否正确。

      【讨论】:

      • 虽然这可能会修复失败的测试,但它并不能解决问题。
      • 是的,我更愿意回答问题的详细信息而不是标题,但很好。
      猜你喜欢
      • 2021-01-16
      • 1970-01-01
      • 2016-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多