There is no unit test, how to reconstruct

The recent technology companies and the entire Silicon Valley an unlucky year, there be Trump counter attack power, Tesla side was named America’s most reliable brand of car, reportedly because of the increased function is too complex for Model X (Tesla high-tech multi strange me), such as the use of electric door opening, middle seat electric implements mobile, all of these functions are integrated in a platform, leading to decline in reliability. Popular explanation is the electric door there is a small bug, the electric chair and a small bug, a small bug resulted in bug, human life, this is to avoid the small bug technology about software development: unit test.

This article will introduce the following:

  1. Method of adding unit testing in iOS development.
  2. How to write unit test cases and use case groups.
  3. Introduce some basic concepts of unit testing.

This article as the reconstruction examples (want to know what they see is the reconstruction of the other, always said the reconstruction, however, the assumption is to rewrite) a movie on demand system of video website, each click play will charge, according to the different kinds of movies, different time, different charging, finally calculate the total consumption of customers. And integral calculation. This example of the class relationship is clear and easy to understand, with the OC language, iOS development of children’s shoes will look more cordial, impatient shoes can skip the source of the first part for testing tools add unit testing, need to know the details back to see the source code.

The system includes a movie class, a customer class, and an on-demand class. The class relationship is shown below:

There is no unit test, how to reconstruct
class diagram.Png

Film class

/ / / / Movie.h / / RefactorDemo / / Created / / by Xishi on 16/10/29. Copyright xs. All rights of 2016 / / reserved. / / typedef NS_ENUM (NSUInteger, MovieEnum) {MovieEnumChildrens = 2, MovieEnumRegular = 0, MovieEnumNewRelease = 1}; @class Movie; @interface Movie NSObject @property (nonatomic, copy) NSString *title @property (nonatomic int priceCode);; - (ID) initWithTitle: (NSString *) Title priceCode: (int) priceCode; @end
/ / / / Movie.m / / RefactorDemo / / Created / / by Xishi on 16/10/29. Copyright xs. All rights of 2016 / / reserved. / / #import Movie.h @implementation Movie (ID) initWithTitle: (NSString *) Title priceCode: (int priceCode) {self = [super init]; if (self) {_title = title; _priceCode = priceCode;} return self @end;}

On demand category:
on-demand class defines the behavior of on-demand, concerned about what movies on demand, and the demand of the time, which affect the final charge.

/ / / / Demand.h / / RefactorDemo / / Created / / by Xishi on 16/10/29. Copyright xs. All rights of 2016 / / reserved. / / #import < Foundation/Foundation.h> typedef; NS_ENUM (NSUInteger, TimePeriodEnum) {TimePeriodEnumWorkDaytime = 1, TimePeriodEnumWorkNight = 2, TimePeriodEnumWeekend = 3}; @class Movie; @interface Demand NSObject @property (nonatomic Movie *movie @property (nonatomic); int timePeriod, assign); - (ID) initWithMovie: (Movie *) movie timePeriod: (TimePeriodEnum) timePeriod; @end
/ / / / Demand.m / / RefactorDemo / / Created / / by Xishi on 16/10/29. Copyright xs. All rights of 2016 / / reserved. / / #import "Demand.h" #import "Movie.h" @implementation Demand (ID) initWithMovie: (Movie *) movie timePeriod: (TimePeriodEnum timePeriod) {self = [super init]; if (self) {_movie = movie; _timePeriod = timePeriod return self @end;}};

Customer class

/ / / / Customer.h / / RefactorDemo / / Created / / by Xishi on 16/10/29. Copyright xs. All rights of 2016 / / reserved. / / #import < Foundation/Foundation.h> @class; Demand @interface; Customer: NSObject - (ID) initCustomerWithName: (NSString * name); - (void) addDemand: (Demand * demand); - (NSString * statement); @end
/ / / / Customer.m / / RefactorDemo / / Created / / by Xishi on 16/10/29. Copyright xs. All rights of 2016 / / reserved. / / #import "Customer.h" #import "Demand.h" #import "Movie.h" @interface (Customer) {NSString *_name; NSMutableArray * _demands; @end @implementation Customer} - (ID) initCustomerWithName: (NSString * name) {self = [super init]; if (self) {_name = name;} return self;} - (void) addDemand: (Demand * demand) {if (! _demands) {_demands = "NSMutableArray alloc] init] [_demands addObject:demand];};} - (NSString * statement) {double totalAmount = 0; int frequentDemandPotnts = 0; NSMutableString = *result [NSMutableString stringWithFormat:@ on the list of"% @ / ///n, _name]; for (Demand *aDemand in _demands) {double thisAmount = 0; / / according to different film Pricing: switch (aDemand.movie.priceCode) {case MovieEnumRegular: thisAmount = 2; / / ordinary film 2 yuan for a break; case MovieEnumNewRelease: thisAmount = 3; / / new film 3 yuan for a break; case MovieEnumChildrens: thisAmount = 1.5; / / children's film 1.5 yuan a} / / according to different period Pricing: if (aDemand.timePeriod = = TimePeriodEnumWorkDaytime) thisAmount = 1; / / day full price else if (aDemand.timePeriod = = TimePeriodEnumWeekend) { ThisAmount = 0.5; / / else (aDemand.timePeriod if weekend half price} = = TimePeriodEnumWorkNight) {thisAmount = 1.5; / / work 1.5 times} frequentDemandPotnts++; / / weekend on demand: if (double integral film (aDemand.movie.priceCode = = MovieEnumNewRelease) & & aDemand.timePeriod = = TimePeriodEnumWeekend) {frequentDemandPotnts++}; [result appendFormat:@ "////t%@////t%@ ////n, aDemand.movie.title, @ yuan" (thisAmount)]; totalAmount = thisAmount;} [result appendFormat:@ "total cost of $% @ ////n, @ (totalAmount).StringValue]; [result appendFormat:@" score (frequentDem @% @ ". AndPotnts).StringValue]; return result;} @end

Prepare test tools


Here is the choice of XCTest, which is built in the Xcode8 test framework, the use of very simple, the following two conditions for the project to add test:

1 add unit tests for new projects:

There is no unit test, how to reconstruct
new add unit test

2 add unit tests for existing projects

The steps in Xcode8 are different from those of previous generations:

There is no unit test, how to reconstruct
add Target
There is no unit test, how to reconstruct
keyword test quickly find Unit Testing bundle
The engineering structure of There is no unit test, how to reconstruct
after adding good unit test

Add first test


The first test is very important, it determines the direction and direction of our test, where the need to test what is the guiding principle, starting from the results, so the first look at the basic demand on demand:

Work on the demand for an ordinary film, 2 yuan fee, a product.

According to the above requirements, we add the test method in RefactorDemoTests.m:

- (void) testStatement_Regular Movie [[Movie alloc] initWithTitle:@ {*matrixMovie1 = "matrix 1" priceCode:MovieEnumRegular]; Demand *aDemand1 = [[Demand alloc] initWithMovie:matrixMovie1 timePeriod:TimePeriodEnumWorkDaytime]; / / customer to rent a Customer: *aCustomer = [[Customer alloc] initCustomerWithName:@ "]; [aCustomer addDemand:aDemand1]; Brooks" XCTAssertTrue "([@ Xishi on-demand list ////n" @ "////t matrix 1////t2 ////n" @ "total cost of 2 yuan ////n" @ "score 1" isEqualToString:[aCustomer statement]] "on demand, @ test An ordinary film "";}

This test case, the customer demand for a “stone” old “hacker empire 1”, because it is working, so according to the original charge, and accumulated 1 points, see details statement source code in the Cutomer method ().
shortcut keys U, run the test, test error:

There is no unit test, how to reconstruct
first run test error

Careful examination revealed that statment () implementation, price and the unit does not have a space, consider it was a space relatively clear, so after the modification, again press the shortcut key U running test, test:

There is no unit test, how to reconstruct
test passed

in the unit test, the green representation of the test, the red test failed, has become the industry standard, XCTest follows this rule.

Test case group


In the first example, we know that the test case always starts with test, as the Convention, who at the beginning of the test method, the XCTest framework will be run automatically, we add to the weekend on demand preference test:

- (void) testStatement_Weekend Movie [[Movie alloc] initWithTitle:@ {*matrixMovie2 = "the Matrix Reloaded 2-" priceCode:MovieEnumRegular]; Demand *aDemand2 = [[Demand alloc] initWithMovie:matrixMovie2 timePeriod:TimePeriodEnumWeekend]; Customer *aCustomer = [[Customer alloc] initCustomerWithName:@ "]; [aCustomer addDemand:aDemand2]; Brooks" XCTAssertTrue "([@ Xishi on-demand list ////n" @ "////t Matrix Reloaded 2- ////t1 $////n" @ "total cost of 1 yuan ////n" @ "won 1 points" isEqualToString:[aCustomer statement]], "a general test on @ Movies, weekends half price ";}

This test case in addition to the movie name is not the same, but the demand time from the working day to the weekend, in order to determine whether the correct calculation rules.
at this time, we have two test cases, in order to speed up the test and open test of fifth Xcode on the left navigation panel, can be specified separately a case running, pay attention to the change of marker map icon:

There is no unit test, how to reconstruct
runs a test case alone

So, we can consider the statement will need to return all in all test cases (is not listed here, the children can be realized, the problem can be proposed in the comments, though I would not answer), can ensure that the algorithm satisfies all requirements report.

The difference between unit testing and functional testing


The function test is to ensure the entire package to work properly, it is oriented to the target customers, security software functions meet the quality requirements of customers, of course, this kind of work should be submitted by professional testing departments like looking for bug to deal with, they will use and development of different tools, and don’t care about the details of the implementation (this the reason is that you and the test personnel always disagreeable conversation).
unit testing is concerned with the details of the implementation, it is the target of a class, a method that is our developers to verify that the code has abnormal tools that may not always look for the treatment of the boundary therefore write unit test.

Test cycle

From the simple use case above, we can clearly see the following general steps:

  1. Prepare test data.
  2. Call target API
  3. Verify output and behavior
There is no unit test, how to reconstruct
test cycle

Summary

In this paper, a movie on demand system example, demonstrates the following:

  1. Add unit test framework in iOS development XCTest.
  2. Using test method to organize the unit test cases and use case groups, can be unified operation, can also be run separately.
  3. This paper introduces some basic concepts of unit testing, understand the goal of unit testing, and test cycle.

These are the basis and prerequisite for further reconstruction of future space is limited, imitation object unit testing technology has not been mentioned, welcomed the attention of Xi Shi, and listen to the next time decomposition.