Introduce a Style Guide
When a failed mutation comes across, I need to decide if I should change the code or the test.
Sometimes the decision is easy. The code can be tightened, or the test can be tweaked/ enhanced.
But other times I first need to understand more.
A style guide states the reasoning behind mutations. It educates developers so they can make better decisions, and possibly know what kind of tests will easily close the test gap.
Seems this could be implemented in a few ways:
- add a url to mutation definition pointing to other people's style guides or stack overflow articles.
- add description to the mutation definition (like rubydoc)
- mutant generates urls into a mutant wiki, and people would put in descriptions where necessary
- A single or set of markdown files possibly on github pages
- A pros style that teaches the philosophy of using the least powerful constructs.
- Seems like a lot of work, and potentially something that could become stale very easily.
- Would be nice if it were easy to add to the documentation in the same PR that contains the mutation addition.
- Would be nice for others to be able to contribute reasoning when they have a problem, research the answer, and want to give back to this community.
Any thoughts on the best way to put something like this together?
I think starting a guide is a good idea. How about calling this a "Mutation Guide" instead of a style guide since mutations shouldn't only have a style component to them?
I'll have to fiddle with whether this can work, but this project already has pretty good yard docs. We could use the Custom YARD Tag feature to add a @mutation #[] -> #fetch tag or something that we can then really easily extract and dump into a guide
I'd be willing to put some work into this effort. I've discussed similar ideas with @backus offline a few times. It would certainly be helpful to the newcomer (though I know that's not what @mbj is interested in optimizing for, which is fine) and, I think, generally educational.
Cool so it is pretty easy to attach a custom yard doc and then extract that information:
diff --git c/lib/mutant/mutator/node/send.rb i/lib/mutant/mutator/node/send.rb
index 5d04719..4f4698d 100644
--- c/lib/mutant/mutator/node/send.rb
+++ i/lib/mutant/mutator/node/send.rb
@@ -11,6 +11,78 @@ module Mutant
children :receiver, :selector
+ # @mutation #reverse_map -> #map
+ # explanation #1
+ #
+ # @mutation #kind_of -> #instance_of?
+ # explanation #2
+ #
+ # @mutation #is_a -> #instance_of?
+ # explanation #3
+ #
+ # @mutation #reverse_each -> #each
+ # explanation #4
+ #
+ # @mutation #reverse_merge -> #merge
+ # explanation #5
+ #
+ # @mutation #map -> #each
+ # explanation #6
+ #
+ # @mutation #flat_map -> #map
+ # explanation #7
+ #
+ # @mutation #sample -> #first
+ # explanation #8
+ #
+ # @mutation #pop -> #last
+ # explanation #9
+ #
+ # @mutation #shift -> #first
+ # explanation #10
+ #
+ # @mutation #first -> #last
+ # explanation #11
+ #
+ # @mutation #last -> #first
+ # explanation #12
+ #
+ # @mutation #send -> #public_send
+ # explanation #13
+ #
+ # @mutation #__send__ -> #public_send
+ # explanation #14
+ #
+ # @mutation #method -> #public_method
+ # explanation #15
+ #
+ # @mutation #gsub -> #sub
+ # explanation #16
+ #
+ # @mutation #eql -> #equal?
+ # explanation #17
+ #
+ # @mutation #to_s -> #to_str
+ # explanation #18
+ #
+ # @mutation #to_i -> #to_int
+ # explanation #19
+ #
+ # @mutation #to_a -> #to_ary
+ # explanation #20
+ #
+ # @mutation #to_h -> #to_hash
+ # explanation #21
+ #
+ # @mutation #at -> #fetch
+ # explanation #22
+ #
+ # @mutation #fetch -> #key?
+ # explanation #23
+ #
+ # @mutation #values_at -> #fetch_values
+ # explanation #24
+ #
SELECTOR_REPLACEMENTS = IceNine.deep_freeze(
reverse_map: %i[map each],
kind_of?: %i[instance_of?],
$ yard --title-tag mutation --no-cache
YARD::Registry
.all
.flat_map(&:tags)
.select { |tag| tag.tag_name == 'mutation' }
.each { |tag| puts "#{tag.name}: #{tag.text}" }
# >> #reverse_map -> #map: explanation #1
# >> #kind_of -> #instance_of?: explanation #2
# >> #is_a -> #instance_of?: explanation #3
# >> #reverse_each -> #each: explanation #4
# >> #reverse_merge -> #merge: explanation #5
# >> #map -> #each: explanation #6
# >> #flat_map -> #map: explanation #7
# >> #sample -> #first: explanation #8
# >> #pop -> #last: explanation #9
# >> #shift -> #first: explanation #10
# >> #first -> #last: explanation #11
# >> #last -> #first: explanation #12
# >> #send -> #public_send: explanation #13
# >> #__send__ -> #public_send: explanation #14
# >> #method -> #public_method: explanation #15
# >> #gsub -> #sub: explanation #16
# >> #eql -> #equal?: explanation #17
# >> #to_s -> #to_str: explanation #18
# >> #to_i -> #to_int: explanation #19
# >> #to_a -> #to_ary: explanation #20
# >> #to_h -> #to_hash: explanation #21
# >> #at -> #fetch: explanation #22
# >> #fetch -> #key?: explanation #23
# >> #values_at -> #fetch_values: explanation #24
@backus I outlined a strategy to attach more metadata to mutations in channel multiple times, and we already have similar issues, like https://github.com/mbj/mutant/issues/395.
I'm willing to refactor mutants internals alongside the ideas I outlined in channel.