https://kotlinlang.org logo
Title
s

Stylianos Gakis

06/16/2022, 7:47 AM
I’m wondering, what are the plans for apollo’s
runTest
function when coroutines have now their own
runTest
as well? And I am not talking just about the name being the same, which is possibly okay if people are aware that they are different things, but also about including coroutine’s
runTest
functionality. The powers it gives you like automatic skipping delays, access to
advanceUntilIdle
and such have been very helpful for us in our tests, to make them easier to reason about. See example. I am now at a point where I am using apollo’s runTest at some test but would also like to be able to use coroutine’s runTest, and I was thinking maybe apollo’s runTest can use coroutines runTest instead of runBlocking under the hood at some point? Or do you feel like this can’t/shouldn’t happen?
b

bod

06/16/2022, 7:56 AM
I believe Apollo's
runTest
exists because of the specifics of how coroutines / threading work on native, which has restrictions due to the current memory model. That means we should be able to revamp this when we switch to the new memory model - which we plan to do at some point in the future 🙂.
I must admit I'm not 100% certain of what this implies in details
m

mbonnin

06/16/2022, 8:15 AM
If you're only on the JVM, I think you can use the coroutines
runTest
?
s

Stylianos Gakis

06/16/2022, 8:15 AM
Aha! But doesn’t the official 1.6 coroutines
runTest
impl take care of said native intricacies? Since it’s like the way to run tests with coroutines in the latest version. Or does this have something with how apollo is handling threading?
m

mbonnin

06/16/2022, 8:16 AM
The later. Apollo requires the request coroutine to run on the main thread in Apple platforms
As such it needs a main thread in tests (main in the CFRunLoop sense)
👍 1
But unsure if we can do it now or still need to support the old memory model
1
s

Stylianos Gakis

06/16/2022, 8:21 AM
Right, that makes sense. And when not using apollo’s runTest and do the before() after() calls myself since they’re nothing special as I see in the impl. So for a “final” fix waiting for the new mm is the best bet then. I wonder since it will take quite some time for the community to switch over, and since this is a library and if the clients support the old mm, having apollo-kotlin have the new mm seems to make it non-compatible, it might take a while until you can confidently do that without breaking people right? Unless you say that version 3.x.x is for old mm, and from 3.x.x+1 it’s new mm, so if you want to bump you need the new mm. Or am I missing something?
b

bod

06/16/2022, 8:24 AM
that's exactly right
if a project is set on the current/old MM but uses a library that assumes the new MM, there will be crashes 🙂
m

mbonnin

06/16/2022, 8:26 AM
I think we could certainly drop the old mm soon-ish. Looks like there's more people waiting for the new mm than people rquiring the old one
b

bod

06/16/2022, 8:28 AM
yeah plus as @Stylianos Gakis said, people who can't switch immediately can always stay with the current version of Apollo in the meantime (not ideal if they need a bugfix or feature but...)
👍 1
s

Stylianos Gakis

06/16/2022, 8:32 AM
Right, that’s true, going to the new mm does indeed have benefits as well. Awesome I think all of this makes sense then. Dropping it as soon as you feel comfortable to do so makes sense. I did see that you fixed something in 2.x recently as well. I wonder if you’d need to keep somehow a way open to port such fixes to the version that’d still support the old mm or if it’d just get abandoned completely. Would it be weird with semantic versioning to pull something like this off? 😅 And to go back to the original question, with the new mm how would you expect the runTest api to look like? Maybe deprecating it in favor of just using the coroutines one?
m

mbonnin

06/16/2022, 8:37 AM
if you’d need to keep somehow a way open to port such fixes to the version that’d still support the old mm or if it’d just get abandoned completely
Depends the community feedback. 2.x is still widely used because it's used in some crazy huge codebases where migration takes time and also it's used by Java folks who don't want to pull the coroutines dependency so there is demand for maintainance release. I suspect demand will be much lower for old mm maintainance as the K/N user base is usually moving really fast . But if there is demand I guess we can still patch
🙌 1
Maybe deprecating it in favor of just using the coroutines one?
Yup, that ☝️
🤝 1
🙌 1
s

Stylianos Gakis

06/16/2022, 8:38 AM
Alright thanks for helping me understand all of this and thanks for the discussion! It’s all quite clear to me now.
🙏 2
m

mbonnin

06/16/2022, 8:39 AM
While we're on the
runTest
topic, any reason to use
advanceUntilIdle
instead of "just" waiting for
viewModel.viewState
to change?
I'm personnally always a bit wary of APIs like
advanceUntilIdle
because they introduce a behaviour that's specific to tests
s

Stylianos Gakis

06/16/2022, 8:43 AM
How would a test like the one I posted above look like with that approach? I still need to fast forward the clock by some time somehow to have the delays and such run and move over to the new state. And advanceUntilIdle does that. It’d be great if you could give me a better idea of what you mean.
m

mbonnin

06/16/2022, 8:50 AM
Something along these lines:
viewModel.submitCode("123456")
        val newState = withTimeout(2000) {
            viewModel.viewState.drop(1).first()
        }
        assertThat(newState.loadingCode).isEqualTo(true)
        assertThat(newState.loadingResend).isEqualTo(false)
As a nice side effect, you get more precise testing because you're guaranteed that no intermediate
viewState
is emitted