如何使用Minitest测试工厂,但没有规范框架?

问题描述 投票:3回答:2

我发现了一篇关于Testing Factories First的博客文章(由BigBinary发布 - 恰好是Thoughtbot's RSpec original的Minitest / spec版本)。

你可以告诉我没有spec框架的等价物 - 只需要Minitest(Rails)吗?

The Thoughtbot approach (RSpec)

投机/ factories_spec.rb

FactoryGirl.factories.map(&:name).each do |factory_name|
  describe "The #{factory_name} factory" do
     it 'is valid' do
      build(factory_name).should be_valid
     end
  end
end

Rake文件

if defined?(RSpec)
  desc 'Run factory specs.'
  RSpec::Core::RakeTask.new(:factory_specs) do |t|
    t.pattern = './spec/factories_spec.rb'
  end
end

task spec: :factory_specs

The BigBinary approach (Minitest, spec)

投机/ factories_spec.rb

require File.expand_path(File.dirname(__FILE__) + '/spec_helper')

describe FactoryGirl do
  EXCEPTIONS = %w(base_address base_batch bad_shipping_address)
  FactoryGirl.factories.each do |factory|
    next if EXCEPTIONS.include?(factory.name.to_s)
    describe "The #{factory.name} factory" do

      it 'is valid' do
        instance = build(factory.name)
        instance.must_be :valid?
      end
    end
  end
end

LIB /任务/ factory.rake

desc 'Run factory specs.'
Rake::TestTask.new(:factory_specs) do |t|
  t.pattern = './spec/factories_spec.rb'
end

task test: :factory_specs

什么是Minitest等价物(没有spec)?

ruby-on-rails testing factory-bot minitest
2个回答
2
投票

我在下面介绍的方法与两个原始解决方案略有不同 - 从某种意义上说,我的方法只创建了一个测试,在这个测试中,我循环遍历工厂并对每个测试运行一个断言。我无法创建最接近原始解决方案的解决方案 - 这是(我相信)每个工厂的单独测试方法。如果有人能够展示这样的实现,那就太酷了。

测试/ aaa_factories_tests / factories_test.rb

require File.expand_path(File.dirname(__FILE__) + '/../test_helper.rb')

class FactoriesTest < Minitest::Unit::TestCase

  puts "\n*** Factories Test ***\n\n"

  EXCEPTIONS = %w(name_of_a_factory_to_skip another_one_to_skip)

  def test_factories

    FactoryGirl.factories.each do |factory|

      next if EXCEPTIONS.include?(factory.name.to_s)

      instance = FactoryGirl.build(factory.name)
      assert instance.valid?, "invalid factory: #{factory.name}, error messages: #{instance.errors.messages.inspect}"

      instance = factory = nil
    end         
  end   
end

感谢Minitest works out of the box的方式 - 在test/minitest-rails下添加任何目录将自动为它创建相关的rake任务。所以,假设您添加了一个test/api/目录,rake minitest:api将自动可用。 - 当我运行没有其他配置的bundle exec rake -T时,我看到了任务:

rake minitest:aaa_factories_tests    # Runs tests under test/aaa_factories_tests

我能够成功运行此任务:

-bash> bundle exec rake minitest:aaa_factories_tests

*** Factories Test ***

Run options: --seed 19208

# Running tests:

.

Finished tests in 0.312244s, 3.2026 tests/s, 9.6079 assertions/s.

1 tests, 3 assertions, 0 failures, 0 errors, 0 skips

尽管使用aaa预先填充目录是丑陋的,但我能够首先测试工厂:

bundle exec rake minitest:all

aaa prepend解决方案的原因是MiniTest does a Dir globMac OS X(以及其他Unix变体),结果按字母顺序排序(though the results differ across different platforms)。

同样,我在the default_tasks array前面加上aaa_factories_tests,让工厂首先在默认的Minitest任务中测试(即运行bundle exec rake minitest时)。

LIB /任务/ factories_first.rake

MiniTest::Rails::Testing.default_tasks.unshift('aaa_factories_tests') if Rails.env =~ /^(development|test)\z/

请注意,上述条件避免在不可用的环境中错误地引用Minitest(我已将minitest-rails限制在:test中的:developmentGemfile组)。没有这个if条件,推到Heroku(例如stagingproduction)将导致uninitialized constant MiniTest

当然我也可以直接运行工厂测试:

bundle exec ruby -I test test/aaa_factories_tests/factories_test.rb

0
投票

这是MiniTest的解决方案,没有规范框架:

测试/ factories_test.rb

require File.expand_path(File.dirname(__FILE__) + '/test_helper')

class FactoriesTest < ActiveSupport::TestCase
  EXCEPTIONS = %w(griddler_email)
  FactoryBot.factories.map(&:name).each do |factory_name|
    next if factory_name.to_s.in?(EXCEPTIONS)
    context "The  #{factory_name} factory" do
      should 'be valid' do
        factory = build(factory_name)
        assert_equal true, factory.valid?, factory.errors.full_messages
      end
    end
  end
end

LIB /任务/ factory.rake

namespace :test do
  desc 'Test factories'
  Rake::TestTask.new(:factories) do |t|
    t.pattern = './test/factories_test.rb'
  end
end

task minitest: 'test:factories'

如果您希望在其他测试之前运行工厂测试,最重要的是使用taks minitest而不是任务测试。

© www.soinside.com 2019 - 2024. All rights reserved.