All Projects → rubocop → minitest-style-guide

rubocop / minitest-style-guide

Licence: other
Best practices for writing your tests

Projects that are alternatives of or similar to minitest-style-guide

Policial
Review pull requests for style guide violations
Stars: ✭ 36 (-14.29%)
Mutual labels:  rubocop, style-guide
Ruby Style Guide
📘 Russian Version: A community-driven Ruby coding style guide.
Stars: ✭ 358 (+752.38%)
Mutual labels:  rubocop, style-guide
Ruby Style Guide
A community-driven Ruby coding style guide
Stars: ✭ 15,836 (+37604.76%)
Mutual labels:  rubocop, style-guide
Ruby Style Guide
Shopify’s Ruby Style Guide
Stars: ✭ 127 (+202.38%)
Mutual labels:  rubocop, style-guide
smoothie
A deliciously scalable and adaptable stylesheet methodology 🍹
Stars: ✭ 27 (-35.71%)
Mutual labels:  style-guide
action-rubocop
Run rubocop with reviewdog 🐶
Stars: ✭ 83 (+97.62%)
Mutual labels:  rubocop
shopify python
Python development standards at Shopify
Stars: ✭ 60 (+42.86%)
Mutual labels:  style-guide
SFMC-Cookbook
How to survive as a developer for Salesforce Marketing Cloud
Stars: ✭ 70 (+66.67%)
Mutual labels:  style-guide
factory bot-preload
Preload factories (factory_bot) just like fixtures. It will be easy and, probably, faster!
Stars: ✭ 68 (+61.9%)
Mutual labels:  minitest
massa
Keep the quality, good practices and security of Rails projects.
Stars: ✭ 61 (+45.24%)
Mutual labels:  rubocop
intransient capybara
A set of improvements to Minitest/Capybara/Poltergeist/PhantomJS test stack that reduces the occurrence of transient failures.
Stars: ✭ 25 (-40.48%)
Mutual labels:  minitest
jetrockets-standard
Standard RuboCop configuration for JetRockets with cookies
Stars: ✭ 14 (-66.67%)
Mutual labels:  rubocop
ruby3-rails6-bootstrap-heroku
An opinionated starter application based on Ruby 3.0, Rails 6.1, Webpack 5, Yarn, and Bootstrap 5, deployable on Heroku
Stars: ✭ 21 (-50%)
Mutual labels:  rubocop
minitest-matchers vaccine
💉 Adds matcher support to minitest without all the other RSpec-style expectation "infections."
Stars: ✭ 33 (-21.43%)
Mutual labels:  minitest
standard-packages
List of packages that use `standard`
Stars: ✭ 32 (-23.81%)
Mutual labels:  style-guide
python
Python Style Guide
Stars: ✭ 49 (+16.67%)
Mutual labels:  style-guide
knapsack pro-ruby
Knapsack Pro gem splits tests across parallel CI nodes and makes sure that tests will run in optimal time on each node.
Stars: ✭ 101 (+140.48%)
Mutual labels:  minitest
front-end-resources
📚Resources for front-end developer
Stars: ✭ 32 (-23.81%)
Mutual labels:  style-guide
elixir inconsistencies
List of inconsistencies found throughout the Elixir programming language
Stars: ✭ 23 (-45.24%)
Mutual labels:  style-guide
betterminitest.com
Learn how to write better Minitest tests
Stars: ✭ 20 (-52.38%)
Mutual labels:  minitest

The Minitest Style Guide

Introduction

Role models are important.

— Officer Alex J. Murphy / RoboCop
Tip
You can find a beautiful version of this guide with much improved navigation at https://minitest.rubystyle.guide.

This Minitest style guide outlines the recommended best practices for real-world programmers to write code that can be maintained by other real-world programmers.

RuboCop, a static code analyzer (linter) and formatter, has a rubocop-minitest extension, provides a way to enforce the rules outlined in this guide.

You can generate a PDF copy of this guide using AsciiDoctor PDF, and an HTML copy with AsciiDoctor using the following commands:

# Generates README.pdf
asciidoctor-pdf -a allow-uri-read README.adoc

# Generates README.html
asciidoctor
Tip

Install the rouge gem to get nice syntax highlighting in the generated document.

gem install rouge

A Living Document

This guide is a work in progress - existing guidelines are constantly being improved, new guidelines are added, occasionally some guidelines would get removed.

Layout

This section discusses the idiomatic way to structure tests.

Note
This section is currently a stub. Contributions welcome!

Assertions

This section discusses idiomatic usage of the assertions provided by Minitest.

Assert Nil

Use assert_nil if expecting nil.

# bad
assert_equal(nil, actual)

# good
assert_nil(actual)

Refute Nil

Use refute_nil if not expecting nil.

# bad
assert(!actual.nil?)
refute(actual.nil?)

# good
refute_nil(actual)

Assert Equal Arguments Order

assert_equal should always have expected value as first argument because if the assertion fails the error message would say expected "rubocop-minitest" received "rubocop" not the other way around.

Note
If you’re used to working with RSpec then this in the opposite order.
# bad
assert_equal(actual, "rubocop-minitest")

# good
assert_equal("rubocop-minitest", actual)

Refute Equal

Use refute_equal if expected and actual should not be same.

# bad
assert("rubocop-minitest" != actual)
assert(!"rubocop-minitest" == (actual))

# good
refute_equal("rubocop-minitest", actual)

Assert Truthy

Use assert if expecting truthy value.

# bad
assert_equal(true, actual)

# good
assert(actual)

Refute false

Use refute if expecting false.

# bad
assert_equal(false, actual)

# bad
assert(!something)

# good
refute(actual)

Assert Includes

Use assert_includes to assert if the object is included in the collection.

# bad
assert(collection.include?(object))

# good
assert_includes(collection, object)

Refute Includes

Use refute_includes if the object is not included in the collection.

# bad
refute(collection.include?(object))
assert(!collection.include?(object))

# good
refute_includes(collection, object)

Assert In Delta

Use assert_in_delta if comparing floats. Assertion passes if the expected value is within the delta of actual value.

# bad
assert_equal(Math::PI, actual)

# good
assert_in_delta(Math::PI, actual, 0.01)

Refute In Delta

Use refute_in_delta if comparing floats. Assertion passes if the expected value is NOT within the delta of actual value.

# bad
refute_equal(Math::PI, actual)

# good
refute_in_delta(Math::PI, actual, 0.01)

Assert Empty

Use assert_empty if expecting object to be empty.

# bad
assert(object.empty?)

# good
assert_empty(object)

Refute Empty

Use refute_empty if expecting object to be not empty.

# bad
assert(!object.empty?)
refute(object.empty?)

# good
refute_empty(object)

Assert Operator

Use assert_operator if comparing expected and actual object using operator.

# bad
assert(expected < actual)

# good
assert_operator(expected, :<, actual)

Refute Operator

Use refute_operator if expecting expected object is not binary operator of the actual object. Assertion passes if the expected object is not binary operator(example: greater than) the actual object.

# bad
assert(!(expected > actual))
refute(expected > actual)

# good
refute_operator(expected, :>, actual)

Assert Output

Use assert_output to assert the methods output. Assertion passes if the expected output or error are matched or equal to the standard output/error. The expected value can be a regex, string or nil.

# bad
$stdout = StringIO.new
puts object.method
$stdout.rewind
assert_match expected, $stdout.read

# good
assert_output(expected) { puts object.method }

Assert Silent

Use assert_silent to assert that nothing was written to stdout and stderr.

# bad
assert_output('', '') { puts object.do_something }

# good
assert_silent { puts object.do_something }

Assert Path Exists

Use assert_path_exists if expecting path to exist.

# bad
assert(File.exist?(path))

# good
assert_path_exists(path)

Refute Path Exists

Use refute_path_exists if expecting path to not exist.

# bad
assert(!File.exist?(path))
refute(File.exist?(path))

# good
refute_path_exists(path)

Assert Match

Use assert_match if expecting matcher regex to match actual object.

# bad
assert(pattern.match?(object))

# good
assert_match(pattern, object)

Refute Match

Use refute_match if expecting matcher regex to not match actual object.

# bad
assert(!pattern.match?(object))
refute(pattern.match?(object))

# good
refute_match(pattern, object)

Assert Predicate

Use assert_predicate if expecting to test the predicate on the expected object and on applying predicate returns true. The benefit of using the assert_predicate over the assert or assert_equal is the user friendly error message when assertion fails.

# bad
assert expected.zero?     # => Expected false to be truthy
assert_equal 0, expected  # => Expected: 0 Actual: 2

# good
assert_predicate expected, :zero? # => Expected 2 to be zero?.

Refute Predicate

Use refute_predicate if expecting to test the predicate on the expected object and on applying predicate returns false.

# bad
assert(!expected.zero?)
refute(expected.zero?)

# good
refute_predicate expected, :zero?

Assert Responds To Method

Use assert_respond_to if expecting object to respond to a method.

# bad
assert(object.respond_to?(some_method))

# good
assert_respond_to(object, some_method)

Refute Responds To Method

Use refute_respond_to if expecting object to not respond to a method.

# bad
assert(!object.respond_to?(some_method))
refute(object.respond_to?(some_method))

# good
refute_respond_to(object, some_method)

Assert Instance Of

Prefer assert_instance_of(class, object) over assert(object.instance_of?(class)).

# bad
assert('rubocop-minitest'.instance_of?(String))
# good
assert_instance_of(String, 'rubocop-minitest')

Refute Instance Of

Prefer refute_instance_of(class, object) over refute(object.instance_of?(class)).

# bad
refute('rubocop-minitest'.instance_of?(String))
# good
refute_instance_of(String, 'rubocop-minitest')

Assert Kind Of

Prefer assert_kind_of(class, object) over assert(object.kind_of?(class)).

# bad
assert('rubocop-minitest'.kind_of?(String))
# good
assert_kind_of(String, 'rubocop-minitest')

Refute Kind Of

Prefer refute_kind_of(class, object) over refute(object.kind_of?(class)).

# bad
refute('rubocop-minitest'.kind_of?(String))
# good
refute_kind_of(String, 'rubocop-minitest')

Unspecified exception

Specify the exception being captured by assert_raises. This avoids false-positives when the raised exception is not the same users were expected.

# bad
assert_raises { do_something }

# good
assert_raises(FooException) { do_something }

Expectations

This section discusses idiomatic usage of the expectations provided by Minitest.

Note
This section is currently a stub. Contributions welcome!

Global Expectations

Use _() wrapper if using global expectations which are deprecated methods.

# bad
do_something.must_equal 2
{ raise_exception }.must_raise TypeError

# good
_(do_something).must_equal 2
value(do_something).must_equal 2
expect(do_something).must_equal 2
_ { raise_exception }.must_raise TypeError

Check the Minitest::Expectations doc for more information about its usage.

Hooks

If using a module containing setup or teardown methods, be sure to call super in the test class setup or teardown.

# bad

class TestMeme < Minitest::Test
  include MyHelper

  def setup
    do_something
  end

  def teardown
    clean_something
  end
end

# good

class TestMeme < Minitest::Test
  include MyHelper

  def setup
    super
    do_something
  end

  def teardown
    clean_something
    super
  end
end

File Naming

Use a consistent naming pattern of either a test_ prefix or a _test suffix for filenames of tests.

For a Rails app, follow the _test suffix convention, as used by the Rails generators.

Test Doubles

Minitest includes minitest/mock, a simple mock/stub system.

# example

service = Minitest::Mock.new
service.expect(:execute, true)

A common alternative is Mocha.

# example

service = mock
service.expects(:execute).returns(true)

Choose only one to use – avoid mixing both approaches within one project.

Contributing

The guide is still a work in progress - some guidelines are lacking examples, some guidelines don’t have examples that illustrate them clearly enough. Improving such guidelines is a great (and simple way) to help the Ruby community!

In due time these issues will (hopefully) be addressed - just keep them in mind for now.

Nothing written in this guide is set in stone. It’s our desire to work together with everyone interested in Ruby coding style, so that we could ultimately create a resource that will be beneficial to the entire Ruby community.

Feel free to open tickets or send pull requests with improvements. Thanks in advance for your help!

You can also support the project (and RuboCop) with financial contributions via Patreon.

How to Contribute?

It’s easy, just follow the contribution guidelines below:

Spread the Word

A community-driven style guide is of little use to a community that doesn’t know about its existence. Tweet about the guide, share it with your friends and colleagues. Every comment, suggestion or opinion we get makes the guide just a little bit better. And we want to have the best possible guide, don’t we?

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].