Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 使用RSpec测试Rails模型验证,而不测试AR本身 使用RSpec测试Rails模型验证,而不测试AR本身_Ruby On Rails_Ruby_Unit Testing_Testing_Rspec - Fatal编程技术网

Ruby on rails 使用RSpec测试Rails模型验证,而不测试AR本身 使用RSpec测试Rails模型验证,而不测试AR本身

Ruby on rails 使用RSpec测试Rails模型验证,而不测试AR本身 使用RSpec测试Rails模型验证,而不测试AR本身,ruby-on-rails,ruby,unit-testing,testing,rspec,Ruby On Rails,Ruby,Unit Testing,Testing,Rspec,作为设置,我们有型号用户: class User < ActiveRecord::Base validate :name, presence: true, uniqueness: { case_sensitive: false }, on: :create validate :password, presence: true, format: { with: /\A[a-zA-z]*\z/ } end 或 我的主要问题是哪种方法更好,为什么?你能给我建议不同的方法吗? 其他问题:

作为设置,我们有型号
用户

class User < ActiveRecord::Base
  validate :name, presence: true, uniqueness: { case_sensitive: false }, on: :create
  validate :password, presence: true, format: { with: /\A[a-zA-z]*\z/ }
end

我的主要问题是哪种方法更好,为什么?你能给我建议不同的方法吗? 其他问题:

  • 我应该测试多少?举个例子,我可以为正则表达式编写这么多的测试,但这将是维护的地狱
  • 在这个例子中,您认为完整的测试覆盖率是多少

应使用其中两种,因为:

it { expect(user).to validate_presence_of(:name).on(:create) } 
=>您希望在
create
上运行
validate\u presence\u
,这应该是模型的测试用例

it do
  user = User.create(name: '')
  expect(user.errors[:name]).to be_present
end
=>在使用输入创建用户时,您预期会产生副作用,因此这应该是控制器的测试用例

为什么不应删除其中的1个:

  • 删除第一个测试用例:如果改为使用数据库验证级别,会发生什么情况?您希望使用活动记录级别的验证

  • 删除第二个测试用例:控制器上发生的事情实际上创建了一个新的
    用户
    ,您如何期望错误返回


以下功能:

  • Rails能够验证模型上是否存在任意值
  • 错误
    被添加到属性的对象中,该属性在配置验证时丢失
在Rails本身的测试(特别是在中)中介绍

这就需要为覆盖应用程序业务逻辑的配置编写测试,例如验证特定
用户
类上是否存在特定的
名称
属性等。在我看来,来自

RSpec.describe User, type: :model do
  subject(:user) { build(:user) } # assuming you're using FactoryGirl

  describe 'validations' do
    specify 'for name' do
      expect(user).to validate_presence_of(:name).on(:create)
      # NOTE: saving here is needed to test uniqueness amongst users in
      # the database
      user.save
      expect(user).to validate_uniqueness_of(:name)
    end

    specify 'for password' do
      expect(user).to validate_presence_of(:password)
      expect(user).to allow_value('abcd').for(:password)
      expect(user).to_not allow_value('1234').for(:password)
    end
  end
end
我认为,除非您有特定的自定义错误消息用于您想要测试的错误(即您已经覆盖了默认的Rails错误),否则可以删除像
expect(user.errors[:name])这样的测试(即使您有自定义错误,我仍然认为它们的价值值得怀疑,因为如果您将应用程序国际化,这些消息将取决于语言环境,因此我会在特性规范的
页面上测试某种错误的显示)

我可以为正则表达式编写这么多的测试,但这将是维护的地狱

我认为在测试
格式的验证时,您无法真正绕过这一点,因此我建议您只编写一些具有代表性的测试用例,然后在发现任何可能遗漏的问题时添加/删除这些用例,例如:

# use a `let` or extract out into a test helper method
let(:valid_passwords) do
  ['abcd', 'ABCD', 'AbCd'] # etc etc
end

describe 'validations' do
  specify 'for password' do
    valid_passwords.each do |password|
      expect(user).to allow_value(password).for(:password)
    end
  end
end
在这个例子中,您认为完整的测试覆盖率是多少


我已经从报告中获得了100%的代码覆盖率,比如在编写如上所述的单元规范时。

仅供参考,
matcher的
validate\u presence\u不是RSpec内置的,它是由shoulda matchers gem添加的:第一个更紧凑,所以更好,它意味着第二个方法的功能,所以您建议第二个测试用例是c控制器单元测试?所以你更喜欢第一个模型单元测试?是的,这就是我在当前项目中的想法和使用,我们通常测试行为(调用什么)和测试副作用(发生什么)!
RSpec.describe User, type: :model do
  subject(:user) { build(:user) } # assuming you're using FactoryGirl

  describe 'validations' do
    specify 'for name' do
      expect(user).to validate_presence_of(:name).on(:create)
      # NOTE: saving here is needed to test uniqueness amongst users in
      # the database
      user.save
      expect(user).to validate_uniqueness_of(:name)
    end

    specify 'for password' do
      expect(user).to validate_presence_of(:password)
      expect(user).to allow_value('abcd').for(:password)
      expect(user).to_not allow_value('1234').for(:password)
    end
  end
end
# use a `let` or extract out into a test helper method
let(:valid_passwords) do
  ['abcd', 'ABCD', 'AbCd'] # etc etc
end

describe 'validations' do
  specify 'for password' do
    valid_passwords.each do |password|
      expect(user).to allow_value(password).for(:password)
    end
  end
end