Unit Tests

Unit Tests

“The Testing Pyramid,” unit tests verify how isolated parts of your application work. Before checking how things work together, you need to make sure the units of your application behave as expected.

you will Learn what unit tests are and what are the best places to use them.

? Write unit tests using the test-driven development (TDD) pattern to learn these concepts in the context of TDD.

When to use unit tests

Unit tests are the fastest and easiest tests to write. They also are the quickest to run. When you want to ensure that a class or method is working as intended in isolation — this means with no other dependent classes — you write unit tests.

Before writing any feature code, you should first write a unit test for one of the classes that will compose your feature. Afterwards, you write the class that will pass the test. After repeating this procedure, you’ll have a completed, testable feature

Creating unit tests

assertEquals verifies that the previous execution modified the game.currentScore property to be equal to one. It’s important to understand that the first parameter is the expected value, and the second parameter is the actual value
create the Game class

Running the test

Notice how the expected value is one and the actual value is zero. If we had reversed the order of our expected and actual values in our assertion, this would show up incorrectly

the test will be failed.

Making the test pass


Now run the test again and see that it passes.

test is pass

Creating more tests

The game will show a highest score. So, you should add a test that checks that when the current score is above the highest score, it increments the highest score:

@Test
fun whenIncrementingScore_aboveHighScore_shouldAlsoIncrementHighScore() {
 val game = Game()
 game.incrementScore()
 Assert.assertEquals(1, game.highestScore)
}        

Again if you try to compile it’ll fail because the highestScore property is missing. So, add the following property to the Game class:

var highestScore = 0
 private set        

Now the test will compile, so run it and watch it fail.

To make it pass, open the Game class and modify the incrementScore() method as follows:

Run the test and you’ll see that it passes

However, you should also test that, when the highest score is greater than the current score, incrementing the current score won’t also increment the highest score, so add the following test:

Here, the intention is to create a Game with a highscore of 10. The test won’t compile because you need to modify the constructor to allow a parameter. Because you need to start with a highest score greater than the default, which is 0, you need to alter the constructor like this:

Now, run all the tests and see that the last one doesn’t pass. You can use the green arrow button on the left-side of the class definition.

The last one doesn’t pass because you’re incrementing both the current score and highest score regardless of their values. Fix that by replacing the incrementScore() function with the following:

Build and run the last test to see the satisfying green checkmark.

Now I will add questions to make trivia game:

so you’ll now create unit tests that model a question with two possible answers. The question also has an “answered” option to model what the user has answered to the question

@Test
 fun whenCreatingQuestion_shouldNotHaveAnsweredOption() {
 val question = Question("CORRECT", "INCORRECT")
 Assert.assertNull(question.answeredOption)
 }        

Here, you used assertNull to check if question.answeredOption is null. If you try to run this test it won’t compile because the Question class doesn’t exist.

Create the Question class:

class Question(val correctOption: String,
 val incorrectOption: String) {
 var answeredOption: String? = null
 private set
}        

Run the test again and watch that it now passes.

Now, you can add another test:

 @Test
 fun whenAnswering_shouldHaveAnsweredOption() {
 val question = Question("CORRECT", "INCORRECT")
 question.answer("INCORRECT")
 Assert.assertEquals("INCORRECT", question.answeredOption)
 }        

This test will check that, when you add the user’s answer to a question, the user’s answer is saved in the answeredOption property. You’ll get a compilation error since you haven’t written the answer() method yet.

Add the following to the Question class to make it compile:

fun answer(option: String) { // No implementation yet }        

Now run the test and you’ll see that it doesn’t pass.

fun answer(option: String) {
 answeredOption = option
 }        

Because you’ll need to know if the question was answered correctly, imagine that the answer() method now returns a Boolean. The result would be true when the user answered correctly. Now, add this test.

 @Test
 fun whenAnswering_withCorrectOption_shouldReturnTrue() {
 val question = Question("CORRECT", "INCORRECT")
 val result = question.answer("CORRECT")
 Assert.assertTrue(result)
 }        

Notice, here, that you’re using assertTrue. It checks for a Boolean result. Running this test will get you a compilation error since the answer() method doesn’t return a Boolean. Update the Question class so that the answer() method returns a Boolean.For now, always return false

fun answer(option: String): Boolean {
 answeredOption = option
 return false
 }        

Run it and watch it fail.

Fix it temporarily by always returning true:

 fun answer(option: String): Boolean {
 answeredOption = option
 return true
 }        

Run it and watch it pass.

Add the following test:

 @Test fun whenAnswering_withIncorrectOption_shouldReturnFalse() {
 val question = Question("CORRECT", "INCORRECT") 
val result = question.answer("INCORRECT") 
Assert.assertFalse(result) 
}        

Run it and see that it fails.

Now that we have tests for when the answer is correct and when the answer is not correct, we can fix the code:

 fun answer(option: String): Boolean {
 answeredOption = option
 return correctOption == answeredOption
 }        

Run all the Question tests and verify they all pass correctly.


Finally, you should ensure that the answer() method only allows valid options. Add this test

@Test(expected = IllegalArgumentException::class)
 fun whenAnswering_withInvalidOption_shouldThrowException() {
 val question = Question("CORRECT", "INCORRECT")
 question.answer("INVALID")
 }
Notice, here, that the @Test annotation allows to expect an exception. If that exception occurs, the test will pass. This will save you from writing try/catch. If you run the test now, it will fail because the answer() method doesn’t throw the exception.        

To fix this, modify the Question class as follows:

Run the test and watch that it now passes.

Refactoring the unit tests:

*)QuestionClass

*)QuestionClassUnitTests



Mohamed Osama

Senior Android Developer at Awqaf

11 个月

?????????? ?? ?????

Mohamed Nabil

Software Engineer| Junior Android Developer Kotlin & Java | Freelance Professional Open for Opportunities

11 个月

???? ??? ???? ????? ???? ??

Omar Refaat

Service Engineer

11 个月

Good job ??

Mahdi Abd El-Mageed

Mobile Developer ( Native Android & Flutter )

11 个月

???? ???? ????? ????? ??

Mohamed Magdy

Front End Developer React& Next JS | Bubble.io Developer

11 个月

????? ???? ??? ????? ??

要查看或添加评论,请登录

社区洞察

其他会员也浏览了