New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce matcher interface #468
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
--- | ||
threshold: 18 | ||
total_score: 1248 | ||
total_score: 1232 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,15 @@ | ||
module Mutant | ||
# Abstract matcher to find subjects to mutate | ||
class Matcher | ||
include Adamantium::Flat, Enumerable, AbstractType | ||
include Adamantium::Flat, AbstractType | ||
|
||
# Default matcher build implementation | ||
# Call matcher | ||
# | ||
# @param [Env] env | ||
# @param [Object] input | ||
# | ||
# @return [undefined] | ||
# | ||
# @api private | ||
def self.build(*arguments) | ||
new(*arguments) | ||
end | ||
|
||
# Enumerate subjects | ||
# | ||
# @return [self] | ||
# if block given | ||
# | ||
# @return [Enumerable<Subject>] | ||
# otherwise | ||
# | ||
# @api private | ||
abstract_method :each | ||
abstract_method :call | ||
|
||
end # Matcher | ||
end # Mutant |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious. Why did you add
Kernel
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short: To be able to spec the global side effect this code should trigger.
Long:
When specifying requires, its IMO okay to rely on the fact
Kernel#require
will do the right thing when called. So its IMO fine to place message expectations to "specify" certain requires happen.I could actually have setup a real file require it and observe a constant was added, but that would defeat the idea of a unit spec. A unit spec under execution should not mutate global state. (OT: Thats a nice way to try defining unit spec vs integration spec!)
Now when setting up message expectations (that are temporal monkey patches effectively) we need an object to target this monkey patches on.
2 thoughts arise from that:
Bootstrap.call
that returnsEnv
. No instance ofBootstrap
is visible to the API client. The whole intention is to cause side effects and produce a "stable" environment object. Tests should only use the API of the class and do not "fuck around" with their implementation details. As I do not have access on an instance ofBootstrap
via the API I do not have an object to set the message expectation up against.Bootstrap
setting up a message expectation on the object under test would be a very bad idea. Here I actually have to blame ruby because very important APIs with global side effects such asKernel#require
are available as private methods everywhere. I'd prefer it ifrequire 'foo'
would only work toplevel, or at class level, but not at instance level per default. This would reduce lots of confusion.In summary: By changing the code to another construct, causing the same side effect. Its now more testable, as I can setup the message expectation on Kernel that is globally available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another maybe more useful instance of the same pattern is available here: https://github.com/mbj/mutant/blob/master/bin/mutant#L13-L29
This is the call side for mutants self-zombification. It explicitly passes kernel into the zombifier API, for testing the zombifier I could implement a "fake Kernel" (that also does some message expectations, but not via rspec) to specify the behavior of Zombification.
Here is the test support class: https://github.com/mbj/mutant/blob/master/spec/support/ruby_vm.rb
This example is an instance of the same idea: When multiple APIs that produce the same effect exist (
#require
vsKernel.require
) use the one that is easier to unit test.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very interesting!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I think next refactorings will pass in Kernel, $stderr, $stdout and other global friends explicitly into the mutant namespace. I had great success with that on the
Mutant::Zombifier
sub-project. So it'll help everywhere.Each time I have to place a message expectation via rspec on a global constant something in my hart dies.