Search code examples
ruby-on-railsrubytddminitest

How do I customise test generators in default Rails?


Edit: Originally this was a Rails 5.2 question but it still seems relevant with Rails 6 and 6.1

I am trying to customise which tests are generated by default in a vanilla Rails 5.2.x app. I don't seem to be able to configure the Minitest generators though. The following code in my config/application.rb causes a error minitest [not found] error when I try and generate a model.

config.generators do |generate|
  generate.test_framework :minitest, model: false
end

My Assumptions/Understanding

Clearly there's a gap in my understanding or one of my assumptions is wrong.

Steps to Reproduce

rails -v
    # Rails 5.2.1.1
rails new testing-test-frameworks
    # Bundle install outputs: 'Using minitest 5.11.3'
cd testing-test-frameworks
rails g model --help
    # Default [test framework]: test_unit [why???]

rails g model person
    # invoke    test_unit [why???]
    # create      test/models/person_test.rb
    # create      test/fixtures/people.yml

Strangely enough, the official Rails testing guide also has lots of references to invoke test_unit for both unit tests and system tests.

Other Things I Tried

  • I tried other settings in the config.generators block just to make sure it's working

  • Given that the test_unit generators seem to be non-negotiable I tried changing the generations through test_unit; config.generators.test_framework :test_unit, model: false

  • I tried to disable various other tests; fixture:false, integration: false, model: false, spec: false, system: false, view: false

  • I tried to confirm I don't have any other gems or settings that might be messing with things (several similar sounding problems related to an old version of FactoryBot/Girl)

  • I tried variations such as generate.test_framework :mini_test mentioned in other answers

Questions

  1. How do I control these generators?
  2. Where (on the Internet or on my filesystem) do I go to learn about the valid options that can be passed to the generators for each test framework?
  3. Why does the help system in my vanilla app say the default test generator is TestUnit when the official documentation says it's Minitest?

Solution

  • I'm attempting to partially answer some of my own questions (2+ years later) based on recent learnings (and based on Rails 6). If I'm wrong, hopefully Cunningham's Law holds true.

    1. :test_unit == :minitest (more or less)

    The first big point of confusion for me was that Minitest is indeed the default test framework under the hood but just about everything within Rails (still?) seems to refer to TestUnit/test_unit.

    Examples include:

    1. rails g model --help output (snippets below)
      -t, [--test-framework=NAME]                # Test framework to be invoked
                                                 # Default: test_unit
                                                            ^^^^^^^^^
      
      TestUnit options:
      ^^^^^^^^
      
    2. rails g scaffold Example output (snippets below):
        create    app/models/example.rb
        invoke    test_unit
                  ^^^^^^^^^
        create      test/models/example_test.rb
        invoke  scaffold_controller
        create    app/controllers/examples_controller.rb
        invoke    test_unit
                  ^^^^^^^^^
        create      test/controllers/examples_controller_test.rb
        create      app/helpers/examples_helper.rb
        invoke      test_unit
                    ^^^^^^^^^
      
    3. The way we generate tests:
      bin/rails generate test_unit:model article title:string body:text
                         ^^^^^^^^^
      

    2. Digging into Test Unit

    Sure enough, if we look in all.rb we see that "Test Unit" is being included via the test_unit Railtie. If (like me) you don't really know what a Railtie is, check out this blog post, I found it quite helpful.

    In terms of what options we can provide in our config/application.rb config.generators block, I think the only options we can pass with config.generators.test_framework :test_unit are fixture: true/false (and maybe specifying a fixture_replacement path(?), based on the apparent defaults in the test_unit railtie).

    3. What else can "TestUnit" generate?

    If you run rails g to get a list of available generators, only four TestUnit ones are mentioned in the output:

    TestUnit:
      test_unit:channel
      test_unit:generator
      test_unit:mailbox
      test_unit:plugin
    

    But the Rails Testing Guide mentions test_unit:model and test_unit:scaffold as well. And when I tried rails g test_unit:foo Rails suggested perhaps I meant rails g test_unit:job so that's three "undocumented" generators.

    From what I can tell, those three extras come from this generators folder, along with a few others. If so, I think the complete list is:

    • test_unit:channel *not in that folder, seems to be added by ActionCable
    • test_unit:controller
    • test_unit:generator
    • test_unit:helper
    • test_unit:integration
    • test_unit:job
    • test_unit:mailbox *not in that folder, seems to be added by ActionMailbox
    • test_unit:mailer
    • test_unit:model
    • test_unit:plugin
    • test_unit:scaffold
    • test_unit:system