您的位置:首页 > 移动开发 > Swift

ios swift 测试框架翻译之Quick例子和一ArrangeActAssert

2016-05-18 14:15 1416 查看

XCTest高效测试:Arrange, Act, 和 Assert

无论你是使用XCTest, Quick或者其他的一些测试框架,你都能通过下面简单的模式写出高效的单元测试:

1. Arrange

2. Act

3. Assert

使用 Arrange, Act, 和Assert

现在。我们来看一个名字叫做Banana的简单类:

// Banana/Banana.swift

/** A delicious banana. Tastes better if you peel it first. */
public class Banana {
private var isPeeled = false

/** Peels the banana. */
public func peel() {
isPeeled = true
}

/** You shouldn't eat a banana unless it's been peeled. */
public var isEdible: Bool {
return isPeeled
}
}


//Banana.h
@interface Banana : NSObject
@property (assign,nonatomic) BOOL isPeeled;
-(void)peel;
-(BOOL)isEdibal;
-(NSString*)offer:(Banana*)banana;
@end
//Banana.m
-(instancetype)init{
self = [super init];
if (self) {
_isPeeled = false;
}
return self;
}
-(void)peel{
_isPeeled = true;
}
-(BOOL)isEdibal{
return self.isPeeled;
}

-(NSString*)offer:(Banana*)banana{
if (banana.isEdibal) {
return @"Hey, want a banana?";
} else {
return @"Hey, want me to peel this banana for you?";
}
}


接下来验证Banana.peel()方法去假定做些什么:

// BananaTests/BananaTests.swift

class BananaTests: XCTestCase {
func testPeel() {
// Arrange: Create the banana we'll be peeling.
let banana = Banana()

// Act: Peel the banana.
banana.peel()

// Assert: Verify that the banana is now edible.
XCTAssertTrue(banana.isEdible)
}
}


//objectes-c .m文件
- (void)setUp {
[super setUp];
// Arrange: Create a banana and peel it.
self.banana = [[Banana alloc]init];
}
-(void)testPeel {
// Act: Create the string used to offer the banana.
[self.banana peel];
// Assert: Verify it's the right string.
XCTAssertEqual(message, @"Hey, want a banana?");
}


使用清晰的测试方法名:

我们必须确保testPeel()方法;如果Banana.peel() 方法不能停止工作;我们知道。

事实上这些是经常发生的当我们的应用代码改变的时候,这意味着:

1. 我们的测试突然停止,因此我们会去修改测试的代码
2. 我们所做的改变我们的应用(这里应该指的是测试代码)应该知道如何工作--也许应为我们新增了一个类的特征--因此我们去改变测试代码


如果测试开始停止,我门如何知道适应于那种情况导致的?也许使你惊讶这个的测试的名字是我们最好的指导。好的测试名字:

1. 清楚告诉测什么的。

2. 清楚告诉测试是通过还是失败

方法 testPeel()是清楚的名字吗?我们来使他更清晰:

// BananaTests.swift

//-func testPeel() {
+func testPeel_makesTheBananaEdible() {
// Arrange: Create the banana we'll be peeling.
let banana = Banana()

// Act: Peel the banana.
banana.peel()

// Assert: Verify that the banana is now edible.
XCTAssertTrue(banana.isEdible)
}


//objectes-c .m文件
- (void)testPeel_makesTheBananaEdible() {
[super setUp];
// Arrange: Create a banana and peel it.
self.banana = [[Banana alloc]init];
}
-(void)testPeel_makesTheBananaEdible() {
// Act: Create the string used to offer the banana.
[self.banana peel];
// Assert: Verify it's the right string.
XCTAssertEqual(message, @"Hey, want a banana?");
}


这个新方法名:

1. 清楚这个方法是测试什么:testPeel 表明他是Banana.peel() 的方法。
2. 清楚知道测试通过:通过方法的返回,makesTheBananaEdible表明香蕉是水果一类的。


条件测试

假设我们想要为人们提供香蕉,使用offer()函数:

// Banana/Offer.swift

/** Given a banana, returns a string that can be used to offer someone the banana. */
public func offer(banana: Banana) -> String {
if banana.isEdible {
return "Hey, want a banana?"
} else {
return "Hey, want me to peel this banana for you?"
}
}


我们的代码做了两件事:

1. 也许售卖的香蕉已经是剥好皮的…

2. …或者售卖的是没有剥皮的

让我对这两个事件进行测试:

// BananaTests/OfferTests.swift

class OfferTests: XCTestCase {
func testOffer_whenTheBananaIsPeeled_offersTheBanana() {
// Arrange: Create a banana and peel it.
let banana = Banana()
banana.peel()

// Act: Create the string used to offer the banana.
let message = offer(banana)

// Assert: Verify it's the right string.
XCTAssertEqual(message, "Hey, want a banana?")
}

func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() {
// Arrange: Create a banana.
let banana = Banana()

// Act: Create the string used to offer the banana.
let message = offer(banana)

// Assert: Verify it's the right string.
XCTAssertEqual(message, "Hey, want me to peel this banana for you?")
}
}


//oc
-(void)testOffer_whenTheBananaIsPeeled_offersTheBanana {
// Arrange: Create a banana and peel it.

[self.banana peel];
// Act: Create the string used to offer the banana.
NSString *message = [self.banana offer:(self.banana)];

// Assert: Verify it's the right string.
XCTAssertEqual(message, @"Hey, want a banana?");
}
-(void)testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana {
// Arrange: Create a banana and peel it.

// Act: Create the string used to offer the banana.
NSString *message = [self.banana offer:(self.banana)];

// Assert: Verify it's the right string.
XCTAssertEqual(message, @"Hey,want me to peel this banana for you?");
}


我们的测试名字明确的指示出在那种条件下的测试通过:在
whenTheBananaIsPeeled
条件下
offer
的应该是
offersTheBanana
, 和即使这个香蕉没有剥皮?我们还是要去做一些测试。

在我们的测试代码中每一个测试都有
`if
去声明。我们去写一些测试的时候这是一个很好模式:

它确保每种设定的情况都有测试。如果一种情况下测试没有工作;或者测试条件需要改变,我们能够快速的找到在代码中位置并查看它。

XCTestCase.setUp()更短的 “Arrange”步骤

我们的OfferTests和”Arrange”两个包含着相似的代码:两者都创建了一个香蕉。我们应该讲代码移动到一个单独的地方,为什呢?

就像这样,如果我们改变了Banana类的初始化,我们必须去改变每一个测试类的创建的banana;

我们的测试方法将非常的短–这是一件非常好的事情,如果(只有)使得测试类变得更容易阅读。

接下啦,让我们移动Banana 的初始化 到 XCTestCase.setUp() 方法,他在每一测试方法之前调用。

// OfferTests.swift

class OfferTests: XCTestCase {
+  var banana: Banana!
+
+  override func setUp() {
+    super.setUp()
+    banana = Banana()
+  }
+
func testOffer_whenTheBananaIsPeeled_offersTheBanana() {
-    // Arrange: Create a banana and peel it.
-    let banana = Banana()
+    // Arrange: Peel the banana.
banana.peel()

// Act: Create the string used to offer the banana.
let message = offer(banana)

// Assert: Verify it's the right string.
XCTAssertEqual(message, "Hey, want a banana?")
}

func testOffer_whenTheBananaIsntPeeled_offersToPeelTheBanana() {
-    // Arrange: Create a banana.
-    let banana = Banana()
-
// Act: Create the string used to offer the banana.
let message = offer(banana)

// Assert: Verify it's the right string.
XCTAssertEqual(message, "Hey, want me to peel this banana for you?")
}
}


共享 “Arrange”代码 贯穿到多个测试中

如果你发现你在多个测试类中使用了相似的”arrange” 步骤,你也许想去定义一个辅助函数在你的测试target中:

// BananaTests/BananaHelpers.swift

internal func createNewPeeledBanana() -> Banana {
let banana = Banana()
banana.peel()
return banana
}


你的帮助类中的函数:函数不能有子类,或者能保留任何的状态,子类和多状态可以保证你的测试类容易读。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: