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
Split TestAnnotations into transforms and markers #27
Conversation
…on carrying a transform
…tation carrying a transform
…otation carrying a transform
OK, so now I've had a day to step back from this, I see that NodeTransform<*> isn't safe, because I can build a transform that replaces a node with one that expects Int
and use that to build a TransformingAnnotation. So that begs the question, what type can we pass to TransformingAnnotation that makes it impossible to assume the fixture type? |
The only thing that it doesn't have is the ability to call NodeBuilder<*>.addTransform( ) with it. |
Maybe have a look at the heterogeneous map example from effective java: http://www.informit.com/articles/article.aspx?p=2861454&seqNum=8 In your case it would mean, remove |
Thanks Rob, can I ask for some clarification?
You are correct that the F is the fixture type which is supplied by a container to its child nodes. So we need to make sure that a context cannot build the wrong fixture type, nor have a child that is expecting a different type than its context supplies. This applies not only to I believe (based on my (demonstrably flawed) knowledge and intuition and failure to find counter- examples) that the current code will not let you supply a transform that can make any assumptions about the fixture type, other than it is a subtype of
Can you find a place where you can actually get a ClassCastException with the current code without writing an UNCHECKED_CAST to force it through?
Do you mean for the (what I'm now calling) markers or for transforms?
I'm having trouble grokking I'm trying to achieve a balance of safety and convenience here, hampered by my own lack of intuition in variance. Something is going right, because so far I haven't had to change the public interface through all these changes, but there are limitations on what is a non-breaking change. My gut feel is that the approach of only allowing |
Just by reading your additional commits I guess you have already found a case where one can sneak in wrong types.
With heterogeneous
Maybe I get to you by another analogy: think in terms of |
I think that this branch is in a better place than master and has (probably) no effective breaking changes, so I'm going to merge it in. I'm still interested in any places where the annotations can apply an unsafe transform. |
This aims to solve the fundamental problems that I ran into because I was combining annotations with transforms.
I wanted to have
TestAnnotation<in F>
to allowTestAnnotation<Any?>
(for exampleSKIP
) to be combined withTestAnnotation<MyFixture>
, but because aTestAnnotation
carried a transformI ended up with the ability to add a transform that could send the wrong fixture type in to a test - https://github.com/dmcg/minutest/blob/master/core/src/test/kotlin/dev/minutest/experimental/AnnotationTortureTests.kt#L76
What I've done is to separate transforms from markers, and have the ability to add either to a
NodeBuilder
https://github.com/dmcg/minutest/compare/annotations-split?expand=1#diff-158654f07c4f987b79c4f9694e9571e8L14TestAnnotation
now doesn't have any generic parameter, and can either add itself to the [NodeBuilder] as a marker, or a transform, or both.It can't though know anything about the fixture type. That doesn't stop it implementing SKIP - because SKIP ignores the fixture.
JUnit Rules support and fixture sequence flattening are simplified because they can directly add a transform to do their thing, rather than creating an annotation to add a transform. Note that inside a
context
block transforms have access to the fixture type, it's only TestAnnotations that don't.So far so good?
There is one place that I can't make the typesystem work for this.
TransformingAnnotation
- https://github.com/dmcg/minutest/compare/annotations-split?expand=1#diff-a074010cc4b7550504b6d6291daefc88R15I think that
TransformingAnnotation
is safe, because it takes aNodeTransform<*>
, which can't assume anything about the fixture type. So I think that it should be safe to add that transform to aNodeBuilder<*>
- but the compiler thinks different. I've shoehorned it in with a castIs this actually safe?
No, that isn't a rhetorical question, it's the reason that this is a PR rather than just smashed in to master.