Rails: How to test code in the lib/ directory?

Ruby on-RailsUnit Testing

Ruby on-Rails Problem Overview


I have a model which gets its data from a parser object. I'm thinking that the parser class should live in the lib/ directory (although I could be persuaded that it should live soewhere else). The question is: Where should my unit tests for the parser class be? And how do I ensure that they are run each time I run rake test?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

In the Rails application I'm working on, I decided to just place the tests in the test\unit directory. I will also nest them by module/directory as well, for example:

lib/a.rb   => test/unit/a_test.rb
lib/b/c.rb => test/unit/b/c_test.rb

For me, this was the path of last resistance, as these tests ran without having to make any other changes.

Solution 2 - Ruby on-Rails

Here's one way:

Create lib/tasks/test_lib_dir.rake with the following

namespace :test do
  
  desc "Test lib source"
  Rake::TestTask.new(:lib) do |t|    
    t.libs << "test"
    t.pattern = 'test/lib/**/*_test.rb'
    t.verbose = true    
  end
  
end

Mimic the structure of your lib dir under the test dir, replacing lib code with corresponding tests.

Run rake test:lib to run your lib tests.

If you want all tests to run when you invoke rake test, you could add the following to your new rake file.

lib_task = Rake::Task["test:lib"]
test_task = Rake::Task[:test]
test_task.enhance { lib_task.invoke }

Solution 3 - Ruby on-Rails

I was looking to do the same thing but with rspec & autospec and it took a little digging to figure out just where they were getting the list of directories / file patterns that dictated which test files to run. Ultimately I found this in lib/tasks/rspec.rake:86

  [:models, :controllers, :views, :helpers, :lib, :integration].each do |sub|
    desc "Run the code examples in spec/#{sub}"
    Spec::Rake::SpecTask.new(sub => spec_prereq) do |t|
      t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
      t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
    end
  end

I had placed my tests in a new spec/libs directory when the rpsec.rake file was configured to look in spec/lib. Simply renaming libs -> lib did the trick!

Solution 4 - Ruby on-Rails

An easy and clean way is just to create a directory under test/unit/lib. Then create test as test/unit/lib/foo_test.rb corresponding to lib/foo.rb. No new rake tasks required, and you can nest more directories if needed to match the lib directory structure.

Solution 5 - Ruby on-Rails

As of Rails 4.0:

rake test:all         # Run all tests in any subdir of `test` without resetting the DB
rake test:all:db      # Same as above and resets the DB

As of Rails 4.1, redefine test:run to include additional tasks when running rake or rake test:

# lib/tasks/test.rake

namespace :test do
  Rake::Task["run"].clear
  task run: ["test:units", "test:functionals", "test:generators", "test:integration", "test:tasks"]

  ["tasks"].each do |name|
    Rails::TestTask.new(name => "test:prepare") do |t|
      t.pattern = "test/#{name}/**/*_test.rb"
    end
  end
end

This has the added bonus of defining rake test:tasks in the given example.

As of Rails 4.2, test:run includes all subdirs of test including them when running rake test, and thus rake.

Solution 6 - Ruby on-Rails

To not define additional rake tasks to run tests from the custom defined folders you may also run them with the command rake test:all. Tests folders structure for the lib folder or any other custom folder is up to you. But I prefer to duplicate them in classes: lib is matched to test/lib, app/form_objects to test/form_objects.

Solution 7 - Ruby on-Rails

Use:

[spring] rake test:all

to run all tests, including the directories you created (like [root]/test/lib/).

Omit [spring] if tou aren't using it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKaptajnKoldView Question on Stackoverflow
Solution 1 - Ruby on-RailsMatt HaleyView Answer on Stackoverflow
Solution 2 - Ruby on-RailsPaul CareyView Answer on Stackoverflow
Solution 3 - Ruby on-Railsae35unitView Answer on Stackoverflow
Solution 4 - Ruby on-RailsjpgeekView Answer on Stackoverflow
Solution 5 - Ruby on-Railsuser59278View Answer on Stackoverflow
Solution 6 - Ruby on-Railska8725View Answer on Stackoverflow
Solution 7 - Ruby on-Railsuser4106029View Answer on Stackoverflow