markdown guide
 

We use rspec-jumpstart for our clients who need test coverage help before beginning a Rails upgrade.

GitHub logo tjchambers / rspec-jumpstart

RSpec 3 code generator toward existing Ruby code.

rspec-jumpstart

RSpec 3 code generator toward existing Ruby code. This gem will help you working on existing legacy code which has no tests.

Build Status Maintainability

Installation

rubygems.org/gems/rspec-jumpstart

gem install rspec-jumpstart

Usage

rspec-jumpstart ./app
rspec-jumpstart ./lib
rspec-jumpstart ./lib/yourapp/util.rb

Options

$ rspec-jumpstart -h
Usage: rspec-jumpstart [options]
    -f                               Create if absent or append to the existing spec
        --force
    -n                               Dry run mode (shows generated code to console)
        --dry-run
    -r                               Run in Rails mode
        --rails
    -o VAL                           Output directory (default: ./spec)
        --output-dir VAL
    -D VAL                           Delta template path (e.g. ./rails_controller_delta.erb)
        --delta-template VAL
    -F VAL                           Full template path (e.g. ./rails_controller_full.erb)
        --full-template VAL
    -v                               Print version
        --version

Output example

Unfortunately, lib/foo/bar_baz.rb has no test. That's too bad...

module Foo
  class BarBaz
    def self.xxx(a, b = "aaa")
    end
    def yyy
    end
    private

    def zzz(a)
    end

  end
end

OK, run rspec-jumpstart now!

$ rspec-jumpstart lib/foo/bar_baz.rb
./spec/foo/bar_baz_spec.rb created.

spec/foo/bar_baz_spec.rb will be created…

 

wow, that's what I was looking for πŸ‘. Will give it a try!

Maybe there's something to generate factory_bot factories from existing models?

 

I think request specs are a good place to make quick progress covering a lot of behavior. Simpler to write than higher or lower level specs.

If you have some tooling budget, CodeClimate is a nice way to keep track of test coverage and get a scoreboard to watch early on in the process.

 

Thanks, 'requests' mean controller tests, right?
Very good point, - time spent/complexity somewhere in the middle of integration and unit tests

 

I would recommend adding a tool like CoverBand github.com/danmayer/coverband. This will allow you to know the most critical areas to cover by tests.

 

great gem, thanks for sharing πŸ˜€. I was thinking only about SimpleCov gem, so far

 

Easiest is to identify parts which are free of side effects and use small number of dependencies to execute and cover them with tests.

 
 

When you wrote code for tests you need to know what output is produced from given input. So if you can identify parts of code that work without dependencies (for example without calling the database and checking the results), you can easily test them. The more dependencies your code has (for example on external microservices) the more you have to mock. And if you mock too much, you will end up with code that has pretty high coverage but still the program will be full of bugs.

You have existing codebase, you you should start from parts which are easiest to understand, totally not partially. Controllers are pretty bad choice because they span lots of logic spread across multiple modules. In the other hand, smaller models should be simpler, because they don't depend on other modules (for example only on the database which you should mock).

Look, my project is a frontend over some kind of analytical database, I have no control of the data I'm processing. My application has coverage of about 90% with single API call. That single tests shows that my application can connect to the database, fetch the data, process it, and present, yet we still have tons of problems, for example the title is missing here and there. The thing is, the title comes from external data and I can't do anything about it. If I had a test that will check that for given keyword all articles have tiles - this test will be meaningless.
What I can do - is to do opposite approach. Mock the data and test my applications logic (assume that the title is provided, and put error handling when it's not). Check that connection can be retried when timeout happens. Unfortunately this requires lots of mocking.
Most of the tests in my application focus on checking if the user input is producing correct database queries. The query building logic is done by few classes, all of them have no dependencies. I made them that way, so that is easy to test them. I choose to do that under influence of "functional paradigm" (something different than object oriented programming).

 

The best place to start is with the next bugs you encounter. Making tests for those bugs will stop them from coming back in the future.

Then, any new feature you program should have its tests too. If you have a very strict budget, test the regular case and an edge case. You'll at least know the feature works.

After this, of you have time and money to do so, you can write tests for the older code that hasn't encountered bugs yet.

That's the way I brought unit/integration tests at my job, even if we didn't have budgets specifically for tests. This has led to fewer dumb or recurring bugs on our most recent sites.

Good luck!

Classic DEV Post from Jun 1

What the heck is a Developer Advocate?

Ark Shraier profile image
thinks that he's desingineer enjoying Ruby on Rails πŸ˜‰