The first glimpse of test-driven development

Source: Internet
Author: User

What is test-driven development

Test-driven development refers to the development of test code before writing implementation code. JUnit's author Kent Beck said: "The key reason for writing test-driven code is to eliminate fear and uncertainty in development, because the fear of writing code allows you to be careful with your temptation to avoid communication, make you shy of getting feedback, make you restless, and TDD is the elimination of fear, An important means of making Java developers more confident and more receptive to communication. The benefits of TDD may not be immediately present, but you will find at some point that these benefits include:

    1. Clearer code-write only the code you need
    2. A better design
    3. Greater flexibility-encourages programmers to interface-oriented programming
    4. Faster feedback-don't know if the bug exists until the system is online

TDD can be used at multiple test levels, as shown in the following table:

Test level Description
Unit Test Code in the test class
Integration Testing Test the interaction between classes
System Testing Testing the system in operation
System Integration Testing Systems in a test run include third-party components
Example of test-driven development

Now we need a piece of code to calculate the ticket revenue for a movie theater, the current business rules are very simple, including:

    • Price per ticket (unit price) ¥30
    • Revenue = Number of tickets SOLD * unit price
    • Maximum occupancy of 100 people in the screening Hall

There is also a hypothesis: at present, because there is no professional equipment or system to count the number of tickets sold, in the calculation of ticket revenue, ticket sales amount is manually entered by the user.
The basic steps of TDD are: red-green-refactoring.

    1. Red-write a test that can't be passed
    2. Green-Write the implementation code and let the test pass as soon as possible
    3. Refactoring-Refactor the code and let the test pass again

Next we follow the above steps to complete the function of ticket revenue calculation.

 PackageCom.lovo;ImportJava.math.BigDecimal;ImportOrg.junit.Assert;ImportOrg.junit.Before;ImportOrg.junit.Test; Public  class ticketrevenuetest {    PrivateTicketrevenue ticketrevenue;PrivateBigDecimal expectedrevenue;@Before     Public void setUp() {ticketrevenue=NewTicketrevenue (); }@Test     Public void oneticketsoldisthirtyinrevenue() {expectedrevenue =NewBigDecimal ("a"); Assert.assertequals (Expectedrevenue, Ticketrevenue.estimatetotalrevenue (1)); }}

The above test code not only cannot pass the test, even compiles cannot pass, because the Ticketrevenue class does not exist yet. Next we can take advantage of the IDE's Code repair functionality (both Eclipse and IntelliJ) to create the Ticketrevenue class and the Estimatetotalrevenue method for calculating ticket revenue in that class.

package com.lovo;import java.math.BigDecimal;publicclass TicketRevenue {    publicestimateTotalRevenue(int i) {        return BigDecimal.ZERO;    }}

The

can now run your unit test cases, but because we haven't implemented the real business logic, this test is not possible, as shown in.

However, so far we have completed the "red" step. Next we modify the Estimatetotalrevenue method of the Ticketrevenue class to let the test pass.

package com.lovo;import java.math.BigDecimal;publicclass TicketRevenue {    publicestimateTotalRevenue(int numberOfTicketsSold) {        BigDecimal totalRevenue = BigDecimal.ZERO;        if1) {            new BigDecimal(30);        }        return totalRevenue;    }}

Run the unit test again, as shown in the results.

Here, the second step of "green" is done.
Next we start refactoring the code for the Ticketrevenue class.

package  Com.lovo; import  java.math.BigDecimal; public  class  ticketrevenue  {  private  final  static  int     Ticket_price = 30 ; public  BigDecimal estimatetotalrevenue  (int         Numberofticketssold) {BigDecimal totalrevenue = null ;        Totalrevenue = new  BigDecimal (Ticket_price * numberofticketssold);    return  totalrevenue; }}

The reconstructed code can calculate the corresponding revenue based on the number of tickets sold, and it has taken a big step forward compared to the previous hard code, but it is clear that it does not take into account the case where the input is less than 0 or greater than 100. So we need more test examples to simulate the possible inputs in the actual working environment, and we have made the following improvements to the test code that we just tested.

 PackageCom.lovo;ImportJava.math.BigDecimal;ImportOrg.junit.Assert;ImportOrg.junit.Before;ImportOrg.junit.Test; Public  class ticketrevenuetest {    PrivateTicketrevenue ticketrevenue;PrivateBigDecimal expectedrevenue;@Before     Public void setUp() {ticketrevenue =NewTicketrevenue (); }@Test(expected = Illegalargumentexception.class) Public void Failiflessthanzeroticketsaresold() {Ticketrevenue.estimatetotalrevenue (-1); }@Test     Public void zerosalesequalszerorevenue() {assert.assertequals (Bigdecimal.zero, Ticketrevenue.estimatetotalrevenue (0)); }@Test     Public void oneticketsoldisthirtyinrevenue() {expectedrevenue =NewBigDecimal ("a"); Assert.assertequals (Expectedrevenue, Ticketrevenue.estimatetotalrevenue (1)); }@Test     Public void tenticketssoldisthreehundredinrevenue() {expectedrevenue =NewBigDecimal ("+"); Assert.assertequals (Expectedrevenue, Ticketrevenue.estimatetotalrevenue (Ten)); }@Test(expected = Illegalargumentexception.class) Public void Failifmorethanonehundredticketsaresold() {Ticketrevenue.estimatetotalrevenue (101); }}

Running the test again will result in a test that has two invalid inputs in 5 tests (a test with a sales quantity of-1 and 101), for the simple reason that no invalid input code has been processed in our code. Next, we'll continue to refactor our code.

 PackageCom.lovo;ImportJava.math.BigDecimal; Public  class ticketrevenue {    Private Final Static intTicket_price = -; PublicBigDecimalestimatetotalrevenue(intNumberofticketssold)throwsillegalargumentexception {BigDecimal totalrevenue =NULL;if(Numberofticketssold <0) {Throw NewIllegalArgumentException ("Ticket sales quantity must be greater than or equal to 0"); }Else if(Numberofticketssold > -) {Throw NewIllegalArgumentException ("The number of tickets sold must be less than or equal to); }Else{totalrevenue =NewBigDecimal (Ticket_price * numberofticketssold); }returnTotalrevenue; }}

Run the test code again and check to see if your bar is green (JUnit's famous quote is "Keep your Bar Green"). Of course, for people with code cleanliness, the above code is still slightly bloated, it's OK, another refactoring it.

 PackageCom.lovo;ImportJava.math.BigDecimal; Public  class ticketrevenue {    Private Final Static intTicket_price = -; PublicBigDecimalestimatetotalrevenue(intNumberofticketssold)throwsillegalargumentexception {if(Numberofticketssold <0|| Numberofticketssold > -) {Throw NewIllegalArgumentException ("The number of tickets sold must be between 0 and 100"); }return  NewBigDecimal (Ticket_price * numberofticketssold); }}

Once you've finished modifying your code, never forget to do it again, and still need to keep your bar green.
If we use the object-oriented programming paradigm, then the refactoring of the code should follow the object-oriented design principles. The great god Robert Matin these principles into solid principles.

Principles English Description
Single duty principle (S) Single Responsibility Principle Each object only does what it's supposed to do.
Opening and closing principle (O) Open-closed Principle Accept extensions but do not accept modifications
Richter replacement principle (L) Liskov Substitution Principle You can replace a parent type with a subtype
Interface isolation principle (I) Interface Segregation Principle The interface should be small and dedicated
Dependency reversal principle (D) Dependency inversion Principle Relies on interfaces and does not rely on implementations

Description: The above example is from the well-grounded Java Developer (Chinese name "Java Programmer's Way of practicing"), which covers a lot of practical techniques in Java development and the new language features of Java. Interested can read this book, I believe you will get a lot of harvest.

The first glimpse of test-driven development

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.