minitest-meaningful 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +76 -0
- data/Rakefile +4 -0
- data/lib/minitest/meaningful/version.rb +7 -0
- data/lib/minitest/meaningful.rb +91 -0
- data/lib/minitest/meaningful_plugin.rb +13 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0537b67234cc8e5b97f42ac7117068392946f88ca607b2b7ff6aa0fff95b7f1f
|
4
|
+
data.tar.gz: 49534eacac48a362598ca178ee5b91da40ab41da44f3ab132aecbdbfeb8d78c7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4248b5451112ca9ff2dd6e96d22404b8b0aa8b4cd23ebf11f6596e365587c1737210ec33680029c3c1b2520d87aa7002f2df71ec00c4f786ea55e0a1f143a4ba
|
7
|
+
data.tar.gz: b777b67082ea2a943b3c01d8fbb9b3760af8c2fdafe00cdec7ce209e0d7f8ab47e94c81c8cea663da0756b77d6f848937364ce9f7604ea63100ea70f8e8d06d8
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Minitest::Meaningful
|
2
|
+
|
3
|
+
This is a proof-of-concept Minitest plugin to help avoid writing completely meaningless tests. A meaningless test is one that always passes because of incorrect test setup. This plugin helps ensure tests aren't meaningless, by trying to make them fail.
|
4
|
+
|
5
|
+
For example, in a Rails app we might have a test that looks like this:
|
6
|
+
|
7
|
+
```rb
|
8
|
+
test "#visible_comments excludes hidden comments" do
|
9
|
+
post = create(:post)
|
10
|
+
comment = create(:comment, status: "hidden")
|
11
|
+
|
12
|
+
refute_includes post.visible_comments, comment
|
13
|
+
end
|
14
|
+
```
|
15
|
+
|
16
|
+
The `comment` record is completely unrelated to the `post` record. It doesn't matter what the `status` is, nor does it really matter what the `#visible_comments` implementation looks like, there's no reason this comment would ever be returned. It always passes, it's a false positive test.
|
17
|
+
|
18
|
+
This plugin adds an `important!` annotation to wrap the most important test setup variable. The test runner can then run the test both with and without evaluating that block. If the test passes when that `important!` block is not evaluated, then we know it is not meaningful.
|
19
|
+
|
20
|
+
```rb
|
21
|
+
test "#visible_comments excludes hidden comments" do
|
22
|
+
post = create(:post)
|
23
|
+
comment = create(:comment)
|
24
|
+
important! { comment.update!(status: "hidden") }
|
25
|
+
|
26
|
+
refute_includes post.visible_comments, comment
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
Install the gem and add to the application's Gemfile by executing:
|
33
|
+
|
34
|
+
$ bundle add minitest-meaningful
|
35
|
+
|
36
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
37
|
+
|
38
|
+
$ gem install minitest-meaningful
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
Include the `Minitest::Meaningful` module in your test:
|
43
|
+
|
44
|
+
```rb
|
45
|
+
class ExampleTest > Minitest::Test
|
46
|
+
include Minitest::Meaningful
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Annotate the most important test setup variable:
|
51
|
+
|
52
|
+
```rb
|
53
|
+
def test_visible_comments_excludes_hidden_comments
|
54
|
+
post = create(:post)
|
55
|
+
comment = create(:comment)
|
56
|
+
important! { comment.update!(status: "hidden") }
|
57
|
+
|
58
|
+
refute_includes post.visible_comments, comment
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
Assert the test should fail:
|
63
|
+
|
64
|
+
```rb
|
65
|
+
assert_meaningful :test_visible_comments_excludes_hidden_comments
|
66
|
+
```
|
67
|
+
|
68
|
+
Run the test with the `--meaningful` flag:
|
69
|
+
|
70
|
+
```sh
|
71
|
+
$ ruby example_test.rb --meaningful
|
72
|
+
```
|
73
|
+
|
74
|
+
## Contributing
|
75
|
+
|
76
|
+
This is definitely a hacky proof-of-concept. If you can think of a better way to integrate this into Minitest test suites, or a way to more robustly identify false-positive tests, please let me know! Also, I hate the name—please suggest something better!
|
data/Rakefile
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "meaningful/version"
|
4
|
+
|
5
|
+
module Minitest
|
6
|
+
module Meaningful
|
7
|
+
class << self
|
8
|
+
attr_accessor :enabled
|
9
|
+
end
|
10
|
+
|
11
|
+
MultipleAnnotationsError = Class.new(StandardError)
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def runnable_methods
|
15
|
+
if Meaningful.enabled
|
16
|
+
meaningful_methods.keys
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def meaningful_methods
|
23
|
+
@meaningful_methods ||= {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def assert_meaningful(*names)
|
27
|
+
names.each do |name|
|
28
|
+
meaningful_methods[name.to_s] = caller
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.included(base)
|
34
|
+
base.extend(ClassMethods)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def run
|
39
|
+
@should_fail = Meaningful.enabled
|
40
|
+
|
41
|
+
super
|
42
|
+
|
43
|
+
if @should_fail
|
44
|
+
if !@important_backtrace
|
45
|
+
exception = Minitest::Assertion.new("Expected test to have `important!` setup.")
|
46
|
+
exception.set_backtrace(self.class.meaningful_methods[name.to_s])
|
47
|
+
self.failures << exception
|
48
|
+
elsif !@did_fail
|
49
|
+
exception = Minitest::Assertion.new("Expected test to fail without `important!` setup.")
|
50
|
+
exception.set_backtrace(@important_backtrace)
|
51
|
+
self.failures << exception
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Result.from(self)
|
56
|
+
rescue MultipleAnnotationsError
|
57
|
+
exception = Minitest::Assertion.new("Test uses `important!` more than once.")
|
58
|
+
exception.set_backtrace(@important_backtrace)
|
59
|
+
self.failures << exception
|
60
|
+
|
61
|
+
Result.from(self)
|
62
|
+
end
|
63
|
+
|
64
|
+
def capture_exceptions
|
65
|
+
return super unless @should_fail
|
66
|
+
|
67
|
+
yield
|
68
|
+
rescue *Minitest::Test::PASSTHROUGH_EXCEPTIONS
|
69
|
+
raise
|
70
|
+
rescue Assertion => e
|
71
|
+
@did_fail = true
|
72
|
+
end
|
73
|
+
|
74
|
+
def important!
|
75
|
+
if @should_fail
|
76
|
+
if @important_backtrace
|
77
|
+
raise MultipleAnnotationsError
|
78
|
+
else
|
79
|
+
@important_backtrace = caller
|
80
|
+
end
|
81
|
+
else
|
82
|
+
unless self.class.meaningful_methods.keys.include?(name.to_s)
|
83
|
+
exception = Minitest::Assertion.new("Test uses `important!` without `assert_meaningful`.")
|
84
|
+
raise exception
|
85
|
+
end
|
86
|
+
|
87
|
+
yield
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "minitest/meaningful"
|
2
|
+
|
3
|
+
module Minitest
|
4
|
+
def self.plugin_meaningful_options(opts, options)
|
5
|
+
opts.on "--meaningful", "Expect tests not to pass with important test setup removed." do
|
6
|
+
options[:meaningful] = true
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.plugin_meaningful_init(options)
|
11
|
+
Meaningful.enabled = options.fetch(:meaningful, false)
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: minitest-meaningful
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Thomas Marshall
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-04-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5'
|
27
|
+
description:
|
28
|
+
email:
|
29
|
+
- thomas@thomasmarshall.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- README.md
|
35
|
+
- Rakefile
|
36
|
+
- lib/minitest/meaningful.rb
|
37
|
+
- lib/minitest/meaningful/version.rb
|
38
|
+
- lib/minitest/meaningful_plugin.rb
|
39
|
+
homepage: https://github.com/thomasmarshall/minitest-meaningful
|
40
|
+
licenses: []
|
41
|
+
metadata:
|
42
|
+
homepage_uri: https://github.com/thomasmarshall/minitest-meaningful
|
43
|
+
source_code_uri: https://github.com/thomasmarshall/minitest-meaningful
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 2.6.0
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubygems_version: 3.5.3
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: A minitest plugin to prevent false positive tests.
|
63
|
+
test_files: []
|