没有单元测试,何谈重构?

发表于:2016-11-17 11:03

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:溪石    来源:51Testing软件测试网采编

  最近科技公司流年不利,那边与整个硅谷唱反调的川普逆袭上台了,这边特斯拉被评为美国最不可靠汽车品牌,据报道是因为特斯拉为Model X增加了过于复杂的功能(高科技多也怪我咯),如前门采用电动开启方式,中排座椅实现了电动移动,所有这些功能整合在一个平台上,导致可靠性下滑。通俗解释下就是电动门有个小bug,电动座椅又有个小bug,一堆小bug最终导致的大bug,人命关天了,本篇就来谈谈软件开发中避免小bug的技术单元测试
  本文将介绍以下内容:
  1、iOS开发中添加单元测试的方法。
  2、如何写单元测试用例及用例组。
  3、介绍单元测试的一些基础概念。
  本篇作为重构的例子(想了解重构是什么,另参见他们总在说重构,不过是重写 ),假设了一个视频网站的电影点播系统,每次点击播放就会收取费用,按电影种类不同,时段不同,则收费不同,最终计算出顾客的总消费,并计算积分。这个例子的类关系比较清晰易懂,用OC语言实现,iOS开发的童鞋看起来会比较亲切,心急的童鞋可以跳过源码部分,先看后面添加单元测试的部分准备测试工具,需要了解细节时再回头看源码。
  系统包含一个电影类,顾客类,及点播类,类关系如下图所示:
  
类关系图.png
  电影类
//
//  Movie.h
//  RefactorDemo
//
//  Created by xishi on 16/10/29.
//  Copyright ? 2016年 xs. All rights 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 ? 2016年 xs. All rights 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
  点播类:
  点播类定义了点播行为,关心点播了什么电影,及点播的时段,这些都影响最终收取的费用。
//
//  Demand.h
//  RefactorDemo
//
//  Created by xishi on 16/10/29.
//  Copyright ? 2016年 xs. All rights 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, assign) int timePeriod;
- (id)initWithMovie:(Movie *)movie
timePeriod:(TimePeriodEnum)timePeriod;
@end
//
//  Demand.m
//  RefactorDemo
//
//  Created by xishi on 16/10/29.
//  Copyright ? 2016年 xs. All rights 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.h
//  RefactorDemo
//
//  Created by xishi on 16/10/29.
//  Copyright ? 2016年 xs. All rights 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 ? 2016年 xs. All rights 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:@"%@的点播清单\\\\n", _name];
for (Demand *aDemand in _demands) {
double thisAmount = 0;
// 根据不同电影定价:
switch (aDemand.movie.priceCode) {
case MovieEnumRegular:
thisAmount += 2; // 普通电影2元一次
break;
case MovieEnumNewRelease:
thisAmount += 3; // 新电影3元一次
break;
case MovieEnumChildrens:
thisAmount += 1.5; // 儿童电影1.5元一次
}
// 根据不同时段定价:
if (aDemand.timePeriod == TimePeriodEnumWorkDaytime)
thisAmount *= 1.0; // 工作日全价
else
if (aDemand.timePeriod == TimePeriodEnumWeekend) {
thisAmount *= 0.5; // 周末半价
}
else
if (aDemand.timePeriod == TimePeriodEnumWorkNight){
thisAmount *= 1.5; // 下班1.5倍
}
frequentDemandPotnts++;
// 周末点播新片积分翻倍:
if ((aDemand.movie.priceCode == MovieEnumNewRelease) &&
aDemand.timePeriod == TimePeriodEnumWeekend) {
frequentDemandPotnts++;
}
[result appendFormat:@"\\\\t%@\\\\t%@ 元\\\\n", aDemand.movie.title, @(thisAmount)];
totalAmount += thisAmount;
}
[result appendFormat:@"费用总计 %@ 元\\\\n", @(totalAmount).stringValue];
[result appendFormat:@"获得积分 %@", @(frequentDemandPotnts).stringValue];
return result;
}
@end
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号