Skip to content

Add LoginViewModelTest#1

Open
Tyler-Lopez wants to merge 1 commit intoMaria1-eng:mainfrom
Tyler-Lopez:lopez/add-instrumentation-tests
Open

Add LoginViewModelTest#1
Tyler-Lopez wants to merge 1 commit intoMaria1-eng:mainfrom
Tyler-Lopez:lopez/add-instrumentation-tests

Conversation

@Tyler-Lopez
Copy link
Copy Markdown

This commit adds unit testing for LoginViewModel.

This commit also moves the coroutine from the View to the ViewModel, but using viewModelScope in place of rememberCoroutineScope.

Screen.Recording.2025-11-03.at.8.03.42.PM.mov

This commit adds unit testing for LoginViewModel.

This commit also moves the coroutine from the View to the ViewModel, but using `viewModelScope` in place of `rememberCoroutineScope`.
Comment on lines -82 to -85
coroutine.launch {
viewModel.pressButton()

}
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

rememberCoroutineScope totally works, but in this case, it is a bit more normal to use viewModelScope.launch in the ViewModel instead of doing the coroutine in the view.


}

@VisibleForTesting fun isValidEmail(email: String): Boolean = Patterns.EMAIL_ADDRESS.matcher(email).matches()
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@VisibleForTesting is cool (to me 🤓). Basically, this function should be private. But if it was private, you couldn't test it in LoginViewModelTest. So @VisibleForTesting lets you use it in your test, but if you try to use this function anywhere else you will have problems compiling the app.

}

@VisibleForTesting fun isValidEmail(email: String): Boolean = Patterns.EMAIL_ADDRESS.matcher(email).matches()
@VisibleForTesting fun isValidPassword(password: String): Boolean = password.length > 6
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Suggestion: you could make "6" here a constant, and then it would make unit testing whether isValidPassword is working easier 🤔

Copy link
Copy Markdown
Owner

@Maria1-eng Maria1-eng left a comment

Choose a reason for hiding this comment

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

Regarding the tests, why should I use that runner? Is it especially useful for this case? I’ve read that it’s very fast. I'd like to know more about that

@Tyler-Lopez
Copy link
Copy Markdown
Author

That is a very good question 👏

I had to use it because the tests were not working without it. The reason they weren't working is that, in order to determine if an e-mail was valid or not, you wrote this Patterns.EMAIL_ADDRESS.matcher(email).matches(). I didn't know until the tests failed, but that requires Roboelectric.

Cannot invoke "java.util.regex.Pattern.matcher(java.lang.CharSequence)" because "android.util.Patterns.EMAIL_ADDRESS" is null java.lang.NullPointerException: Cannot invoke "java.util.regex.Pattern.matcher(java.lang.CharSequence)" because "android.util.Patterns.EMAIL_ADDRESS" is null at...

Basically, my understanding is that you need to use Roboelectric if you use code that uses things that are really specific to "Android" and not just "Kotlin" or "Java".

If you didn't use Roboelectric, then, from what I know, you would have to run these tests on an emulator, and that is what it means by being "very fast" - because it would be really slow to boot up an emulator every time you wanted to run tests.

https://developer.android.com/training/testing/local-tests/robolectric

I think you are on your way to knowing a lot more about this than I do 😆

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.

2 participants