-
Notifications
You must be signed in to change notification settings - Fork 1.9k
kotlinx-coroutines-test: why the name runTest
?
#3050
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
Comments
Hi!
I don't think this is an issue, as the package name There are exceptions, of course, like
Not really true, as both in Native and on the JVM, the tests are not run asynchronously.
This seems ok.
It is!
Not quite how I would phrase it. We're trying to make each word in a name count, as each one of them adds mental load. What misuse could we prevent by having a longer name? I don't see any: if someone tries to launch a suspending function without As a side note, we do want people to actually read the docs on @Test
fun testFoo() {
runTest {
// NO, WON'T WORK, DON'T WRITE CODE LIKE THIS
}
} will work incorrectly on the JS. What do you think? |
Mmh if this rationale was really followed, then
You have a point regarding I disagree for
That would be the difference between
We do use this function to run asynchronous stuff inside, in a synchronous or asynchronous way depending on the platform. Note that, in this respect,
My argument was mostly about readability rather than code correctness at writing time. I agree a different name wouldn't really prevent misuse, if we put aside the fact that any testing library of any topic could define a |
Why put the name clash aside?
You wouldn't know it just by looking at it in the code, where this particular receiver is usually implicit.
Do you have any particular library in mind, or are these concerns theoretical?
Ah, yes, you're right here. That said, if we could imagine
You may be right, but it's not obvious to me. I don't see an arbitrary library creating a function with this name, because… what would that function do? You provide an example of measuring execution time, but this is not a test-only thing to do, so why would Also,
// very simplified, but the essence is this:
fun runTest(block: suspend () -> Unit): (Unit | Promise<Unit>) It provides an entry point to test suspend-functions, a fundamental language concept. We could conceivably even make it the default behavior of tests. In fact, at some point, we wanted to (https://youtrack.jetbrains.com/issue/KT-22228), but ultimately decided against this. So, why would any testing library really define a |
First of all, thanks a lot for even having the discussion, by the way.
Because "I don't believe it was named runTest just to avoid the clash with the stdlib's run." - but maybe I was wrong here.
I agree it's not always obvious of course, but I find it more legitimate to assume the reader is aware of the receiver type rather than the package of the function. Awareness can come from explicit receiver specified, or in scope of the current function/method, while imports are likely to be star imports, especially in this case.
Only theoretical. Note that this is not a concern about actual name clash, it's about finding a name that could represent less things semantically (and being a possible choice for other totally unrelated testing libraries is a way to measure the semantic precision of the name).
Again it's more about naming precision than actual clash prevention. I don't expect a mocking library, or testcontainers, etc. to declare a global
Yet,
I mentioned performance testing, but it's true that maybe this example was not the best to illustrate my point after all, sorry.
This is a valid argument for a bigger legitimacy of this library over others, thanks. So indeed this kinda invalidates my previous statement about "all bets are off" for other libraries - it implies somehow that it runs the whole test, so it also limits the possible interpretations in a way. It doesn't prevent us from going one step further and also mention suspensions/asynchronism, though.
Yes, I remember the discussion about making it a language feature. That being said, I bet the language feature would have included some hint at asynchronous or suspending stuff (like a I wonder what exactly would be a drawback of naming it |
Sorry, I caught a cold and won't be responding for a while. I wouldn't even write this if I didn't think we wanted to reach a conclusion on this while we're still in the RC phase. @qwwdfsad, could you take this from here? I can sort of see both sides and will accept any outcome.
|
When considering name collisions, don't forget that there's also user code in addition to stdlib/kotlinx. For example, KaMPKit defines its own runTest function. While in that case, we'd probably replace it with this one anyway, I can easily imagine another project wrapping its own particular test setup code in a similar function that might conflict with the coroutines-test one. |
We've discussed it one more time and decided to keep things as they are.
It will eventually be well-known and advised to be used, it will be internalized by the developers who write code with coroutines and we want the name to be short and concise. It is in fact no different from One of the main benefits of having something like |
@qwwdfsad thanks for the consideration and for reporting back here.
That's fair enough.
I'm not sure I understand the point here.
On the contrary, Trying to avoid clashes with similar libraries that operate on the same concepts shouldn't really be a goal in my opinion, because sometimes a name for a concept is just very good, regardless of which library implements it. If In any case, thanks again for letting us know the final decision. I'm just nitpicking here, and I'm pretty ok with |
I'm back.
I'll respond directly to this point then. Semantic precision is not our goal, because it is not always viable. Instead, "Flow" (and "Flux") are just some vague names that only get their meanings from their wide use. There is zero semantic precision in them, and yet, they are fine, as everyone just accepted them as a separate abstraction. Likewise, A more semantically precise name would be
|
@dkhalanskyjb Welcome back :) Thanks a lot for taking the time to answer, these are all fair points. Semantic precision is a spectrum. I totally agree that it's pointless to try to be the most precise in a name. It's technically not possible, because the name is an abstraction of the implementation, so you have to leave out some details. It's all about balance, and finding what is worth leaving out and what is worth including in the name (naming is hard, as the saying goes).
From what I can see, it just seems we believe the sweet spot to be in a different place, and this is perfectly fine. Again, I'm splitting hair and I don't want you to waste more time in these discussions. Thanks again for this discussion! |
Yeah, in cases of methods that are going to be used all the time, practicality is more important to us than esthetics. I would wholly agree with your arguments if
Sure, thanks for sharing your doubts! You never know, sometimes such discussions lead to surprising insights, and in turn, to overturning decisions. |
I understand that
runBlockingTest
was no longer an appropriate name because it is not always likerunBlocking
anymore, due to the new JS backend support where we cannot block.But I find the
runTest
name a bit too vague for the uninitiated. I mean the difference between these 2 is unclear:Because both of those "run a test". I feel like the name of
runTest
should somehow convey the idea that it's about running coroutines / suspending functions / async stuff, as opposed to "regular tests".Were names like
runSuspendingTest
orrunAsyncTest
considered? Is it because it's expected to have many usages, and shorter is better?The text was updated successfully, but these errors were encountered: