Introduction to Practice

Welcome to your first lesson in this course dedicated to practicing Test-Driven Development (TDD) using Kotlin and JUnit. Test-Driven Development is an effective approach that emphasizes writing tests before coding. This methodology helps you design your application with testing as a core element, ensuring each component behaves as expected. In this lesson, you'll learn the fundamentals of TDD along with the Red-Green-Refactor cycle, understanding their roles in creating robust and maintainable code.

This course involves hands-on practice, where you'll receive requirements through tests incrementally. Your task is to implement code that makes each test pass, mirroring a real-world TDD environment. Consider this course guide as your pair programmer, providing you with test-driven prompts to enhance your skills as you advance.

Understanding the Red-Green-Refactor Cycle

As a reminder, the Red-Green-Refactor cycle is central to TDD, guiding your development process:

  • Red: Start by writing a failing test to define the next step.
  • Green: Implement just enough code to pass the test, focusing on functionality.
  • Refactor: Optimize the code for clarity and efficiency without changing its behavior.
Requirements for `calculateDiscount` Function

Below, you’ll find the detailed requirements and corresponding test cases for the calculateDiscount function.

Each requirement focuses on a specific behavior the function must fulfill, guiding you through the TDD process step by step.

1. Correct Discount Application
  • Description: The function must correctly apply a percentage-based discount to an original price.
  • Test Case:
    Kotlin
    1import kotlin.test.Test 2import kotlin.test.assertEquals 3 4class DiscountCalculatorTest { 5 6 @Test 7 fun testCalculateDiscountAppliesCorrectDiscount() { 8 // Arrange 9 val discountCalculator = DiscountCalculator() 10 val originalPrice = 100.0 11 val discountPercentage = 20.0 12 val expectedDiscountedPrice = 80.0 13 14 // Act 15 val result = discountCalculator.calculateDiscount(originalPrice, discountPercentage) 16 17 // Assert 18 assertEquals(expectedDiscountedPrice, result, 0.01) 19 } 20}
    The test ensures that the function applies the discount correctly and tolerates minor floating-point deviations.
2. Zero Discount Handling
  • Description: The function should return the original price when the discount percentage is 0.
  • Test Case:
    Kotlin
    1import kotlin.test.Test 2import kotlin.test.assertEquals 3 4class DiscountCalculatorTest { 5 6 @Test 7 fun testCalculateDiscountReturnsOriginalPriceWhenDiscountIsZero() { 8 // Arrange 9 val discountCalculator = DiscountCalculator() 10 val originalPrice = 50.0 11 val discountPercentage = 0.0 12 13 // Act 14 val result = discountCalculator.calculateDiscount(originalPrice, discountPercentage) 15 16 // Assert 17 assertEquals(originalPrice, result, 0.01) 18 } 19}
    This test checks that with a 0% discount, the function should correctly maintain the original price.
3. Decimal Discount Precision
  • Description: The function must accurately handle decimal percentages in discount calculations and round the result to two decimal places.
  • Test Case:
    Kotlin
    1import kotlin.test.Test 2import kotlin.test.assertEquals 3 4class DiscountCalculatorTest { 5 6 @Test 7 fun testCalculateDiscountHandlesDecimalDiscountsCorrectly() { 8 // Arrange 9 val discountCalculator = DiscountCalculator() 10 val originalPrice = 100.0 11 val discountPercentage = 33.333 12 val expectedDiscountedPrice = 66.67 13 14 // Act 15 val result = discountCalculator.calculateDiscount(originalPrice, discountPercentage) 16 17 // Assert 18 assertEquals(expectedDiscountedPrice, result, 0.01) 19 } 20}
    It tests the function's ability to handle decimal discounts and verify rounding to two decimal points for accuracy.
4. Negative Price Handling
  • Description: The function should not accept negative prices and must throw an error if encountered.
  • Test Case:
    Kotlin
    1import kotlin.test.Test 2import kotlin.test.assertFailsWith 3 4class DiscountCalculatorTest { 5 6 @Test 7 fun testCalculateDiscountShouldThrowErrorForNegativePrices() { 8 // Arrange 9 val discountCalculator = DiscountCalculator() 10 val originalPrice = -50.0 11 val discountPercentage = 10.0 12 13 // Act & Assert 14 assertFailsWith<IllegalArgumentException> { 15 discountCalculator.calculateDiscount(originalPrice, discountPercentage) 16 } 17 } 18}
    This test is crucial for validating that the function rejects invalid negative price inputs by raising an exception.
5. Discount Percentage Greater Than 100%
  • Description: The function should not accept discount percentages greater than 100% and must throw an error in such cases.
  • Test Case:
    Kotlin
    1import kotlin.test.Test 2import kotlin.test.assertFailsWith 3 4class DiscountCalculatorTest { 5 6 @Test 7 fun testCalculateDiscountThrowsErrorForDiscountsGreaterThan100Percent() { 8 // Arrange 9 val discountCalculator = DiscountCalculator() 10 val originalPrice = 100.0 11 val discountPercentage = 110.0 12 13 // Act & Assert 14 assertFailsWith<IllegalArgumentException> { 15 discountCalculator.calculateDiscount(originalPrice, discountPercentage) 16 } 17 } 18}
    It examines the method’s behavior when provided with excessive discount percentages that logically exceed the threshold.
Summary and Preparation for Practice

Looking ahead to the practice exercises, you will have the opportunity to ensure all tests pass while practicing the Red-Green-Refactor cycle using Kotlin and JUnit. Your implementation may differ from the provided solutions, and that's perfectly acceptable. Each practice session will begin from a solution foundation, allowing you to compare your approach with the guided solution and develop your features to ensure test success.

As you undertake these exercises, remember to engage in the Red-Green-Refactor cycle. Each test I provide serves as the "Red" phase, marking the next step to achieve. Your task is to transition through the "Green" phase by making the tests pass and then enter the "Refactor" phase to enhance your code's clarity and maintainability while confirming that all tests remain successful.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal