Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@fokot
Copy link
Contributor

@fokot fokot commented Dec 27, 2020

Fixing issue #4518

I was trying to do it without so many instanceOf but couldn't find a way.

If we have the same parameter types on the methods in SpecBuilder as in Spec will have type safety in subsequent calls on the SpecBuilder. Is it enough?

Should I add also proving of environments? And do we want to have typesafety there (that all tests have environment which is supertype of the suite's environment)?

@fokot
Copy link
Contributor Author

fokot commented Jan 1, 2021

I removed type parameters from the suite and test methods itself and SpecBuilder. Before it was:

private[test] final class SpecBuilder[R, E, T](_spec: Spec[R, E, T]) {...}

var allSuites: Chunk[SpecBuilder[_, _, _]] = Chunk.empty
var tests: Chunk[SpecBuilder[_, _, _]]     = Chunk.empty

Because it needed me to do casting and existential types. And even if someone would like to provide some R he would need to do casting himself, so no typesafety.

To have test methods with R and E maybe I can add phantom type if it is convertible to the same type as is in allSuites and tests but it would probably require some additional method, which would be there only if criteria is met e.g.

  suite("first") {

    test("simple") {
      assert(1)(equalTo(1))
    }.addTest
}

If you know of any better approach let me know.

Another safe option would be to have add type params to MutableRunnableSpec[R, E] extends RunnableSpec[R, E] and then have also DefaultMutableRunnableSpec extends MutableRunnableSpec[TestEnvironment, Any]. This would require all test methods in MutableRunnableSpec to have common R and E. If you think it is useful I can add it.

Copy link
Contributor

@adamgfraser adamgfraser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. As you say, the biggest issue is providing the environment. Since suite, test, and testM now perform the side effect of adding to the spec we need whatever we are adding to have the right environment type at the time we add it, which means it is difficult for us to implement operators that provide the environment.

def label: String
}

case class SuiteBuilder(label: String) extends SpecBuilder {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final or at least sealed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made them just sealed. It is fine to have them inside MutableRunnableSpec not to pollute zio.test package and I can also use type parameters from MutableRunnableSpec and do not need to add them to *Builder classes. If I make them final, I get this compilation error The outer reference in this type test cannot be checked at run time.

* }
* }}}
*/
class MutableRunnableSpec[R <: Has[_]](layer: ZLayer[TestEnvironment, Throwable, R])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is some overlap here with what Balasz is doing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will speak with him. Maybe renaming would be good to call this
DefaultMutableRunnableSpec -> MutableRunnableSpec
DefaultMutableRunnableSpec -> CustomMutableRunnableSpec
to have it consistent. What do you think? @jdegoes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe so.

}

final override def spec: ZSpec[Environment, Failure] = {
testRunning = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not quite correct. When spec is called, the effect is constructed, but it may not be run then (or ever). What you could do is attach a @@ before annotation to the spec which sets testRunning = true inside there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right 👍 The effect is not run but is already constructed. For me it is enough so I just renamed the variable to specBuilt. After that point no test method should be called to prevent test in test errors. I can not test it with stact because assertion to test is call by name final def test(label: String)(assertion: => TestResult): TestBuilder.

Copy link
Member

@jdegoes jdegoes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am good to merge if @adamgfraser is good. Thanks for your work on this!

Copy link
Contributor

@adamgfraser adamgfraser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@adamgfraser adamgfraser merged commit a35838f into zio:master Jan 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants