Skunk is a RubyCritic extension to calculate a SkunkScore for a file or project. The SkunkScore is a value that assesses the technical debt of a module.
The main goal of the SkunkScore is to serve as a compass in your next refactoring adventure. It will help you answer these questions:
- What can I do to pay off technical debt?
- What are the most complicated files with the least code coverage?
- What are good candidates for my next test-writing efforts?
- What are good candidates for my next refactoring efforts?
To assess the technical debt of a module, Skunk takes into account:
- Code Complexity
- Code Smells
- Code Coverage
Start by including skunk
in your Gemfile:
gem 'skunk'
Then run bundle
.
Or, install it yourself by running: $ gem install skunk
Use SimpleCov to generate a report of how many statements are covered by your test suite (code coverage). That's how skunk
knows what's the status of your test suite + code coverage.
Please refer to SimpleCov's Getting Started Guide to install it and generate the coverage report.
SimpleCov was successfully installed when it generated a JSON file under coverage/.resultset.json
in your application directory.
β οΈ Skunk runsrubycritic
, which loads code coverage data from yourcoverage/.resultset.json
file. Make sure to have this file for best SkunkScore results.
Note: after adding more tests to your application, run SimpleCov again to generate an updated Code Coverage. This way, skunk will generate a new SkunkScore.
Run skunk -h
to check out the help options:
Usage: skunk [options] [paths]
-b, --branch BRANCH Set branch to compare
-o, --out FILE Output report to file
-v, --version Show gem's version
-h, --help Show this message
The SkunkCore is a sorted list of smelly files. Skunk's report will be in the console. On the Ruby project you want to analyze, run:
skunk
The result is a list of smelly files and the SkunkScore of the project/files:
+-----------------------------------------------------+----------------+------------------+--------------+--------------+--------------+
| file | skunk_score | churn_times_cost | churn | cost | coverage |
+-----------------------------------------------------+----------------+------------------+--------------+--------------+--------------+
| samples/rubycritic/analysed_module.rb | 258.88 | 12.94 | 5 | 2.59 | 0.0 |
| lib/skunk/commands/compare.rb | 85.41 | 32.32 | 14 | 2.31 | 63.64 |
| lib/skunk/rubycritic/analysed_modules_collection.rb | 31.76 | 3.18 | 5 | 0.64 | 50.0 |
| lib/skunk/commands/status_reporter.rb | 11.33 | 68.0 | 18 | 3.78 | 97.5 |
| lib/skunk/command_factory.rb | 8.3 | 1.95 | 4 | 0.49 | 83.33 |
| lib/skunk/commands/status_sharer.rb | 8.17 | 10.9 | 4 | 2.72 | 97.67 |
| lib/skunk/cli/application.rb | 7.06 | 21.19 | 18 | 1.18 | 94.12 |
| lib/skunk/cli/options/argv.rb | 4.08 | 7.35 | 9 | 0.82 | 95.24 |
| lib/skunk/commands/compare_score.rb | 3.77 | 2.51 | 4 | 0.63 | 94.74 |
| lib/skunk/rubycritic/analysed_module.rb | 3.37 | 33.74 | 10 | 3.37 | 100.0 |
| lib/skunk/commands/version.rb | 2.64 | 0.7 | 8 | 0.09 | 70.0 |
| lib/skunk/commands/output.rb | 1.86 | 0.09 | 1 | 0.09 | 80.0 |
| lib/skunk/cli/options.rb | 0.68 | 5.44 | 8 | 0.68 | 100.0 |
| lib/skunk/commands/default.rb | 0.4 | 3.23 | 8 | 0.4 | 100.0 |
| lib/skunk/commands/shareable.rb | 0.2 | 0.4 | 2 | 0.2 | 100.0 |
| lib/skunk/commands/help.rb | 0.2 | 1.2 | 6 | 0.2 | 100.0 |
| lib/skunk/commands/base.rb | 0.1 | 0.49 | 5 | 0.1 | 100.0 |
| lib/skunk.rb | 0.0 | 0.0 | 6 | 0.0 | 100.0 |
| lib/skunk/version.rb | 0.0 | 0.0 | 12 | 0.0 | 0.0 |
+-----------------------------------------------------+----------------+------------------+--------------+--------------+--------------+
SkunkScore Total: 428.21
Modules Analysed: 19
SkunkScore Average: 22.54
Worst SkunkScore: 258.88 (samples/rubycritic/analysed_module.rb)
With the report, you can answer these refactoring questions with clarity.
In this example, the file samples/rubycritic/analysed_module.rb
has the Worst SkunkScore. It means this file has a high code complexity, with lower code coverage. To decrease its SkunkScore, start by adding tests to it. Then, simplify the code to decrease the code complexity.
Other great candidates are the files that have lower code coverage. By adding tests, their SkunkScore will decrease, and refactoring the code will be more achievable.
Skunk also gives you a SkunkScore Total value: it shows you the overall code quality of the project. As you decrease the SkunkScore of the files, the total score of the project will decrease.
To only run skunk on specific folders, pass a list of directories in the command line. For example, if you only want the report for the files under app
and lib
, run:
skunk app lib
When working on new features, run skunk against your feature branch to check if the changes are improving or decreasing the code quality of the project.
To generate the SkunkScore of your feature branch, run:
skunk -b <your-feature-branch-name>
Then, get a SkunkScore average comparison with main
by running:
$ skunk -b main
Switched to branch 'main'
....
Base branch (main) average skunk score: 290.53999999999996
Feature branch (feature/compare) average skunk score: 340.3005882352941
Score: 340.3
This should give you an idea if you're moving in the direction of maintaining the code quality or not. In this case, the feature branch is decreasing the code quality because it has a higher SkunkScore than the main branch.
If you want to share the results of your Skunk report with the Ruby community, run:
SHARE=true skunk app/
SkunkScore Total: 126.99
Modules Analysed: 17
SkunkScore Average: 7.47
Worst SkunkScore: 41.92 (lib/skunk/commands/status_sharer.rb)
Generated with Skunk v0.5.0
Shared at: https://skunk.fastruby.io/
Results will be posted by default to https://skunk.fastruby.io which is a free and open source Ruby on Rails application sponsored by OmbuLabs(source code).
If you prefer to post results to your server, set your own SHARE_URL
:
$ SHARE_URL=https://path.to.your.skunk-fyi-server.example.com skunk app/
SkunkScore Total: 126.99
Modules Analysed: 17
SkunkScore Average: 7.47
Worst SkunkScore: 41.92 (lib/skunk/commands/status_sharer.rb)
Generated with Skunk v0.5.0
Shared at: https://path.to.your.skunk-fyi-server.example.com
Have a fix for a problem you've been running into or an idea for a new feature you think would be useful? Want to see how you can support Skunk?
Take a look at the Contributing document for instructions to set up the repo on your machine, check the Help Wanted section, and create a good Pull Request.
skunk
is maintained and funded by FastRuby.io. The names and logos for FastRuby.io are trademarks of The Lean Software Boutique LLC.