<mbj>
But it is STILL accumulating state inside the Rspec singleton.
<mbj>
it should be an application specific constant
<mbj>
So you could do "spec algebra" with multiple expectation objects.
<mbj>
s/expectation/spec_root/
<mbj>
I did not followed rspec development very close, I just consumed rspec as is.
<mbj>
But I'll end up in doing my own framework. Maybe during summer vacation.
<mbj>
It is a good project to keep brain busy :D
<dkubb>
I would be fine if I could get describe after doing include SomeModule at the top
<dkubb>
automatically monkey patching is the thing that's actually bad
<mbj>
jo
<dkubb>
but yeah, I suspect there are tons of methods and constants in the RSpec namespace
<dkubb>
accumulating that complexity in a single namespace, in the name of a better interface, is still a mistake imho
<mbj>
So an application specific root would be better
<mbj>
MyAppsSpecs.describe
<mbj>
or include MyappsSpecs
<mbj>
describe
<mbj>
going to sleep
<mbj>
meet you tomorrow
<dkubb>
I just wish I could say something like: describe MyNamespace, '#read' .. and then describe MySubclass, '#read' do; inherits MyNamespace, '#read'
<dkubb>
and then I could have my own before and let blocks that I can override
<mbj>
snusnu: Thougt you are on a longer vacation and coming back in 2 days.
<mbj>
dkubb: hola, sorry for dropping out so fast yersterday.
<mbj>
dkubb: I have an interesting thought. We Adamantium{,::FLat} that makes objects immutable. But sometimes I need an object that is mutable. (Root of the object tree) This object sometimes gets passed into a freezer. So IMHO we need Adamantium::Mutable that noops #freeze and #frozen => true
<mbj>
dkubb: So I can greatly reduce memoize :freezer => :noop usage!
<Gibheer>
and what would you gain from lying? You would not like an API which is lying to you, right?
<Gibheer>
it will just cause pain :/
<mbj>
Gibheer: It wount, but use it wisely
<mbj>
Gibheer: I already use this for 1 in 1000 classes :D
<Gibheer>
why not just return false for frozen?
<mbj>
Gibheer: Because ice_nine will try to freeze it.
<mbj>
Gibheer: All time it sees that object :D
<Gibheer>
if it is intended like this, then it would be the correct way
<Gibheer>
or you create a flag which represents the purpose, like mutable?
<mbj>
Gibheer: I cannot argue deeply now, busy. later.
<mbj>
But I think it is correct, sometimes.
<Gibheer>
mbj: I see why you would need it, but lying about an objects features feels wrong to me.
<mbj>
Gibheer: #freeze, #frozen? is a protocoal
<mbj>
s/protocal/protocol/
<mbj>
I need a special protocol entity
<mbj>
For edge cases.
<mbj>
And we support these edge cases with :freezer => :noop already.
<mbj>
But all users need to know "dont freeze this object".
<mbj>
With Adamantium::Mutable you can remove all these special memoizers.
<mbj>
So I replace lots of crap with less crap. Okay for me :D
<mbj>
s/crap/imperfectness/
<dkubb>
mbj: I'm fine with this as a stop-gap, but we need a way to configure ice_nine without making special freezers. some kind of dsl that can do it quickly and easily
<mbj>
So just do Mutator::Registry.lookup(node) == Mutator::Node::Generic
<mbj>
And you are done.
<mbj>
Mhh, I should do this *now* :D
<mbj>
mom
<dkubb>
cool
<dkubb>
hehe
<dkubb>
I'd guess there's, what, 15-20 nodes? we could display the top 5 or something and then people who want to contribute could just pop one of those off and work on it in a PR
<dkubb>
what I would probably do is keep a list of 100% mutation covered gems, and tell people to run mutant with them and add a node for the #1 entry
<dkubb>
then maybe they'll knock it down from 100%.. gamify it
<dkubb>
if anyone knocked down one of my 100% covered gems in mutation coverage I would immediately fix it
<mbj>
dkubb: done
<mbj>
(waiting for local rake ci)
<mbj>
dkubb: This is so nice. I love this design.
<mbj>
nesting is:
<mbj>
Reporter(Runner(DomainObject))
<mbj>
So reporter can access runner (with details the runner accumulates)
<mbj>
And reporter can peek into DomainObject
<mbj>
Mutant::Subject in this case.
<dkubb>
oh nice!
<dkubb>
I'll use this report to priorities my time
<dkubb>
I'll start with the top nodes in axiom-types and then branch out
<dkubb>
I still have to get axiom to 100% coverage too
<dkubb>
maybe after I get mutable materialized relations
<mbj>
You can always use parser -e "your code" to see sexps.
<mbj>
dkubb: I'd personally reduce code that we put inside mutations
<mbj>
so instead of an lvar I'd emit: "Mutant::DONT_TOUCH_ME"
<mbj>
And DONT_TOUCH_ME would be an instance of the class you showed.
<dkubb>
I think that Class.new(BasicObject).new would be enough
<dkubb>
it wouldn't respond to anything
<dkubb>
hehe
<mbj>
I think this mutation would not be killable.
<dkubb>
yeah I would probably make a Mutant constant
<dkubb>
you don't think so?
<mbj>
What about a method like this:
<mbj>
def foo(bar)
<mbj>
if bar
<mbj>
baz(bar)
<mbj>
eend
<dkubb>
at some point I wonder if we should have a way of tagging mutations as experimental, and they only are run when the --experimental flag is provided
<mbj>
Yeah
<mbj>
This method will never call a method on bar
namelessjon has joined #rom-rb
<dkubb>
if no one reports any bugs on it for a while then we promote it
<dkubb>
hmm
<dkubb>
yeah, I guess it's in boolean context
<mbj>
Yeah, but that DONT_TOUCH_ME will not be the receiver of any method call.
<dkubb>
I wonder about those cases where the lvar can be nil
<mbj>
So that replacement will not trigger any behavior
<mbj>
nil is falsy
<mbj>
and branch is not taken all the times
<dkubb>
no, I don't mean in this case
<mbj>
specs should measure this.
<dkubb>
I just meant in the general case
<dkubb>
of replacing it with nil
<mbj>
If you have an lvar there should be a case where it is not nil!
<mbj>
So this mutation is valid, IMHO.
<dkubb>
yeah
<dkubb>
I guess if it always expects nil, then wth are you doing
<dkubb>
just don't pass in anything then
<mbj>
I think lvar, gvar and ivar can be handled with the same mutator.
<dkubb>
ahh interesting
<mbj>
just call handle multiple times or with multiple arguments
<mbj>
handle(:lvar, :ivar, :gvar)
<mbj>
later we could expand ivar and gvar to snoop for other ivars or gvars and use another one.
<dkubb>
ahh cool
<dkubb>
so once I get it working for one I can test the others easily
<mbj>
via "mutation runtime reflection" - I'm a buzzword generator :D
<dkubb>
heh
<mbj>
hey, I invented "dynamic in-memory vendoring" also (Zombie) :D
<dkubb>
I think it would be nice to have a stand-alone gem that does that
<mbj>
Yeah
<dkubb>
it's like sandboxing kinda
<mbj>
called zombifier
<mbj>
Mine is not perfect currently
<mbj>
if you do:
<mbj>
require 'foo'
<mbj>
class Bar
<mbj>
end
<mbj>
require 'baz'
<dkubb>
yeah, it doesn't have to be current to be a gem
<mbj>
it will vendor the contents of foo followed by bar and than Bar
<mbj>
I but it should do: 'foo', Bar, 'baz'
<mbj>
where it does (correciton) 'foo', 'baz', Bar
<mbj>
This does not cause any failure, currently.
<mbj>
But that zombifier is nothing more than a limited AST based ruby interpreter.
<mbj>
I could also expand it to hook Kernel.require
<mbj>
dkubb: Keep in mind we have statement deletion
<mbj>
So if you target zsuper you might think: "I could remove the super call altogether"
<mbj>
But this will already be done by parent mutator
<mbj>
dkubb: I thought longer about this, lvar => nil seems to be the only valid mutation
<mbj>
Other possiblities are not structural and should be done later.
<mbj>
Same for ivar, and gvar.
<dkubb>
yeah, I think the main thing is to get explicit mutators in place. we can continue to add stuff over time
<dkubb>
but it would be nice to be doing *something* to those nodes
<dkubb>
even the most basic mutation
<mbj>
dkubb: Yeah
<dkubb>
more mutations will come with familiarity
<mbj>
dkubb: You want add this for yourself?
zekefast has joined #rom-rb
<dkubb>
the lvar mutator?
<dkubb>
yeah I was going to add it today. it'll give me a chance to get familiar with adding new mutators
<dkubb>
then I can be more help later on with more complex stuff
<mbj>
dkubb: Yeah
<mbj>
dkubb: It is 4 loc
<dkubb>
if two of us can dig around and add stuff that's better
<dkubb>
heh
<mbj>
def dispatch; emit_nil; end
<dkubb>
once we get the basic ones in then we can start brainstorming about more mutators and/or stealing from other mutation test frameworks
<dkubb>
I see this as getting the low hanging fruit
<mbj>
dkubb: My research shows mutant has many many many more mutations than other test frameworks.
<dkubb>
yeah
<dkubb>
but there may be a few they've identified that we can steal
<mbj>
The only ones mutant is missing are boolean and relational operator expressions mutation
<dkubb>
it won't take much time to confirm
<mbj>
== to =>
<mbj>
!= to ==
<mbj>
etc.
<dkubb>
I would love to do that expansion one
machuga|away is now known as machuga
<mbj>
expansion?
<dkubb>
a >= b to a > b || a == b .. then mutating each of those
<mbj>
dkubb: I think this will have unkillable operators.
<mbj>
ohh, I see
<dkubb>
or I guess you could get that from simply doing a >= b to a > b and a == b
<mbj>
thought you where talking about op assign!
<dkubb>
nope
<dkubb>
I don't even think expansion is needed
<mbj>
yeah, the one you showed makes sense
<dkubb>
in order to test >= out you do need to handle both cases
<dkubb>
both > and ==
<mbj>
BTW you dont need to expand and reenter mutator
<mbj>
detecting >= and friends is easy
<mbj>
Just add detect this case and run a Send::Binary::GTE mutator.
<dkubb>
in the past I've actually manually expanded those statements, then mutation covered them, then compacted them
<mbj>
I so this for the various send edge cases already: