minitest-verify 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d86d8652f970d9903ab8669a82deeb240cf98e921142b16478c0b1f3e63f1f74
4
- data.tar.gz: b412d10611d8e75e217287896e03fd86d9e34c704aed74c05fbd50526da1a5eb
3
+ metadata.gz: 2464bb648cf544989dd202a1306d3fc0e90739249eb5bc9e34887fe0ed47d0c7
4
+ data.tar.gz: 99d318563f2241dc9d3da3a7cb0a882096a2742198c51eeca2c9d819d14fc310
5
5
  SHA512:
6
- metadata.gz: a2734af789cb9c1019f5fe1fa18382dcab38f5773647ba4149ca10cb2d39eb57a03f840adb84ced9fa751b69517ea6dcd86a7dd1bfb67067cc0836318143aec7
7
- data.tar.gz: 8dc9ca7b532ddfce192c3ed5e7241967dd3f58be678aef9576e087bbf66159ded64de6aa1c37630ec88eebb19cdc0319e27c23fae5a5c43cf79b5bca4d5c0c36
6
+ metadata.gz: a5fe05ddf58dfd01f4aa7889420f34df579b7583bc692990faa896004508e2ae0bbc8e022af3c485cfc52cb5aeb02b32d9d1eaaf67f53db689542206c1382ef1
7
+ data.tar.gz: 2e80275d96ebf402943f33387a6caf99a99d400155c1d72d604d719355cd54427668e87a2f835d44a0e204477358bae9f734a4de9f682366c5e9082439e14342
data/README.md CHANGED
@@ -1,22 +1,22 @@
1
1
  # Minitest::Verify
2
2
 
3
- Avoid false-positive tests by verifying they fail when key setup is removed.
3
+ Avoid false negative tests by verifying they fail when key setup is removed.
4
4
 
5
- ## Installation
5
+ This is a quick proof-of-concept minitest plugin, but it mostly works fine!
6
6
 
7
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
7
+ ## Installation
8
8
 
9
9
  Install the gem and add to the application's Gemfile by executing:
10
10
 
11
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
11
+ $ bundle add minitest-verify
12
12
 
13
13
  If bundler is not being used to manage dependencies, install the gem by executing:
14
14
 
15
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
15
+ $ gem install minitest-verify
16
16
 
17
17
  ## Usage
18
18
 
19
- This is a false-positive test. It always passes because `post` and `comment` are completely unrelated: there's no reason `post.comments` would ever include `comment`.
19
+ This is a false negative test. It always passes because `post` and `comment` are completely unrelated: there's no reason `post.comments` would ever include `comment`.
20
20
 
21
21
  ```rb
22
22
  require "minitest/autorun"
@@ -57,18 +57,18 @@ Now run the test with the `--verify` argument:
57
57
  $ ruby post_test.rb --verify
58
58
  ```
59
59
 
60
- This will cause the test to run twice. First it runs _with_ the contents of the `verify_fails_without` block evaluated (normal run). Then it runs _without_ the contents of the `verify_fails_without` block evaluated (verification run). If the test still passes without having evaluated the code inside the block, it's a false positive and you'll see a verification failure in your test output:
60
+ This will cause the test to run twice. First it runs _with_ the contents of the `verify_fails_without` block evaluated (normal run). Then it runs _without_ the contents of the `verify_fails_without` block evaluated (verification run). If the test still passes without having evaluated the code inside the block, it's a false negative and you'll see a verification failure in your test output:
61
61
 
62
62
  ```
63
63
  # Running:
64
64
 
65
- V
65
+ F
66
66
 
67
67
  Finished in 0.000380s, 2631.5783 runs/s, 5263.1565 assertions/s.
68
68
 
69
- 1) Verification Failure:
69
+ 1) Failure:
70
70
  PostTest#test_comments_excludes_hidden_comments [post_test.rb:11]:
71
71
  Expected at least one assertion to fail.
72
72
 
73
- 1 runs, 2 assertions, 0 failures, 0 errors, 0 skips
73
+ 1 runs, 2 assertions, 1 failures, 0 errors, 0 skips
74
74
  ```
data/Rakefile CHANGED
@@ -1,4 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- task default: %i[]
3
+ require "minitest/test_task"
4
+
5
+ Minitest::TestTask.create
6
+
7
+ task default: :test
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Minitest
4
4
  module Verify
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.1"
6
6
  end
7
7
  end
@@ -6,45 +6,39 @@ module Minitest
6
6
  module Verify
7
7
  class VerificationFailedError < StandardError; end
8
8
 
9
- class VerificationFailure < Minitest::Assertion
10
- def result_label
11
- "Verification Failure"
12
- end
13
- end
14
-
15
- class VerificationError < Minitest::UnexpectedError
16
- def result_label
17
- "Verification Error"
18
- end
19
- end
20
-
21
9
  class << self
22
10
  attr_accessor :enabled
23
11
  end
24
12
 
25
13
  def verify_fails_without(&block)
26
14
  if @current_caller
27
- block.call unless caller[0] == @current_caller[0]
15
+ # If @current_caller is set, we are in the verification phase.
16
+ # Evaluate the block unless it is the one currently being verified.
17
+ block.call unless caller(1..1).first == @current_caller[0]
28
18
  else
19
+ # If @current_caller is not set, we're in the normal test phase.
20
+ # Collect the caller (there might be multiple per test) and evaluate the block.
29
21
  callers << caller
30
22
  block.call
31
23
  end
32
24
  end
33
25
 
34
26
  def run
35
- super
27
+ # If verification is disabled, run the test normally.
28
+ return super unless Verify.enabled
36
29
 
37
- return Result.from(self) unless Verify.enabled
30
+ super
38
31
 
39
- @normal_failures = failures.dup
40
- failures.clear
32
+ # If there are normal failures, don't run verification.
33
+ return Result.from(self) if failures.any?
41
34
 
42
35
  begin
43
- while @current_caller = callers.shift
36
+ # For each caller, run the test again and verify that it fails.
37
+ while (@current_caller = callers.shift)
44
38
  with_verification { super }
45
39
  end
46
40
  rescue VerificationFailedError
47
- callers.clear
41
+ # If verification fails, break out of the loop.
48
42
  end
49
43
 
50
44
  Result.from(self)
@@ -59,27 +53,24 @@ module Minitest
59
53
  def with_verification
60
54
  yield
61
55
 
62
- assertions = failures.select { |f| f.class == Minitest::Assertion }
63
- unexpected_errors = failures.select { |f| f.class == Minitest::UnexpectedError }
64
-
65
- failures.clear
66
- failures.concat(@normal_failures)
67
-
68
- if unexpected_errors.any?
69
- unexpected_errors.each do |unexpected_error|
70
- failures << VerificationError.new(unexpected_error.error)
71
- end
72
-
56
+ # Fail verification if there is an unexpected error.
57
+ # Encountering an unexpected error doesn't imply the test is not a false negative, it might just be broken.
58
+ if failures.any? { |f| f.is_a?(Minitest::UnexpectedError) }
73
59
  raise VerificationFailedError
74
60
  end
75
61
 
76
- if assertions.empty?
77
- exception = VerificationFailure.new("Expected at least one assertion to fail.")
78
- exception.set_backtrace(@current_caller)
79
- failures << exception
80
-
81
- raise VerificationFailedError
62
+ # Remove all assertion failures so the failing test passes.
63
+ # If at least one was removed, the test is not a false negative.
64
+ if failures.reject! { |f| f.is_a?(Minitest::Assertion) }
65
+ return
82
66
  end
67
+
68
+ # If there were no assertion failures, we probably have a false negative.
69
+ exception = Minitest::Assertion.new("Expected at least one assertion to fail.")
70
+ exception.set_backtrace(@current_caller)
71
+ failures << exception
72
+
73
+ raise VerificationFailedError
83
74
  end
84
75
  end
85
76
  end
@@ -2,12 +2,12 @@ require "minitest/verify"
2
2
 
3
3
  module Minitest
4
4
  def self.plugin_verify_options(opts, options)
5
- opts.on "--verify", "Verify tests sometimes fail." do
6
- options[:enabled] = true
5
+ opts.on "--verify", "Verify tests are not false negatives after running them." do
6
+ options[:verify] = true
7
7
  end
8
8
  end
9
9
 
10
10
  def self.plugin_verify_init(options)
11
- Verify.enabled = options.fetch(:enabled, false)
11
+ Verify.enabled = options.fetch(:verify, false)
12
12
  end
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minitest-verify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Marshall
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-30 00:00:00.000000000 Z
11
+ date: 2024-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -57,8 +57,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
57
  - !ruby/object:Gem::Version
58
58
  version: '0'
59
59
  requirements: []
60
- rubygems_version: 3.5.3
60
+ rubygems_version: 3.5.18
61
61
  signing_key:
62
62
  specification_version: 4
63
- summary: A minitest plugin to prevent false positive tests.
63
+ summary: A minitest plugin to prevent false negative tests.
64
64
  test_files: []