ios swift 测试框架翻译之Quick例子和一组例子的有序测试

Quick使用一种特殊的语法去明确这个例子一组例子

使用XCTest进行高效的测试:有序,行为和断言时,我们知道一个好的测试方法名是非常重要的–当这个测试是一个失败的开始的时候,这个测试用一个最好的方式让我们决定要修改应用的代码或者更新代码。
Quick 例子(examples) 和组例子( example groups)提供两种目的 :

* 他们鼓励你去写测试的描述
* 在你的测试"安排"步骤时他们极大地简化测试代码

使用的例子

例子,定义一个它的函数,去了解断言如何在测试用例中使用的。
在XCTest中这些测试方法是相似的。

接收两个参数:这个例子的名字和一个闭包函数。在下面的例子中详细说明Sea.Dolphin 类的行为,一个海豚应该是聪明的和友好的:

// Swift

import Quick
import Nimble
import Sea

class DolphinSpec: QuickSpec {
  override func spec() {
    it("is friendly") {
      expect(Dolphin().isFriendly).to(beTruthy())
    }

    it("is smart") {
      expect(Dolphin().isSmart).to(beTruthy())
    }
  }
}
// Objective-C

@import Quick;
@import Nimble;

QuickSpecBegin(DolphinSpec)

it(@"is friendly", ^{
  expect(@([[Dolphin new] isFriendly])).to(beTruthy());
});

it(@"is smart", ^{
  expect(@([[Dolphin new] isSmart])).to(beTruthy());
});

QuickSpecEnd

使用描述去是你的测试用例更加整洁。描述可以是任何长度和使用任何字符,包括英语之外的其他字符,或者表情 符号:✌️

使用describe and context分组测试的例子

分组测试的例子是逻辑组的例子,例子能共享代代码setupteardown

使用describe描述类和类的方法

这个Dolphin类的click 方法指定了一种特殊的行为–换句话说;去测试方法的工作–使用describe 可以将它的的几个方法放在一个组里进行测试,讲相似的测试分组放在一起将使得测试代码更容易阅读

// Swift

import Quick
import Nimble

class DolphinSpec: QuickSpec {
  override func spec() {
    describe("a dolphin") {
      describe("its click") {
        it("is loud") {
          let click = Dolphin().click()
          expect(click.isLoud).to(beTruthy())
        }

        it("has a high frequency") {
          let click = Dolphin().click()
          expect(click.hasHighFrequency).to(beTruthy())
        }
      }
    }
  }
}

// Objective-C

@import Quick;
@import Nimble;

QuickSpecBegin(DolphinSpec)

describe(@"a dolphin", ^{
  describe(@"its click", ^{
    it(@"is loud", ^{
      Click *click = [[Dolphin new] click];
      expect(@(click.isLoud)).to(beTruthy());
    });

    it(@"has a high frequency", ^{
      Click *click = [[Dolphin new] click];
      expect(@(click.hasHighFrequency)).to(beTruthy());
    });
  });
});
QuickSpecEnd

当着两个部分运行在Xcode,它们将会有以下的描述信息在这个describe和他的函数中:
1. DolphinSpec.a_dolphin_its_click_is_loud
2. DolphinSpec.a_dolphin_its_click_has_a_high_frequency

当再一次进行测试的时候;我们可以明确的知道这个测试用例是用来测试什么的;

模仿 Setup/Teardown 代码 使用 beforeEachafterEach

分组的例子不仅只是使得代码更加清晰,在一个组测试中也可以使用setupteardowm;
在下面的例子中,使用beforeEach函数去创建dolphin的一个新的实例和在每个测它的clivk 方法之前;这样可以确保每一次的测试类都保持最新状态:

// Swift

import Quick
import Nimble

class DolphinSpec: QuickSpec {
  override func spec() {
    describe("a dolphin") {
      var dolphin: Dolphin!
      beforeEach {
        dolphin = Dolphin()
      }

      describe("its click") {
        var click: Click!
        beforeEach {
          click = dolphin.click()
        }

        it("is loud") {
          expect(click.isLoud).to(beTruthy())
        }

        it("has a high frequency") {
          expect(click.hasHighFrequency).to(beTruthy())
        }
      }
    }
  }
}

// Objective-C

@import Quick;
@import Nimble;

QuickSpecBegin(DolphinSpec)

describe(@"a dolphin", ^{
  __block Dolphin *dolphin = nil;
  beforeEach(^{
      dolphin = [Dolphin new];
  });

  describe(@"its click", ^{
    __block Click *click = nil;
    beforeEach(^{
      click = [dolphin click];
    });

    it(@"is loud", ^{
      expect(@(click.isLoud)).to(beTruthy());
    });

    it(@"has a high frequency", ^{
      expect(@(click.hasHighFrequency)).to(beTruthy());
    });
  });
});

QuickSpecEnd

dolphin例子中setup看起来不是那么的的必要;但是对于一些更复杂的对象来说,它省去很多的代码量!
每次执行这些代码后,都会执行afterEach

使用context模拟特定的环境

当海豚发现一些他们感兴趣的事情的时候,通过回声的次数来进行定位,通过释放有一系列的声音去确定他是什么。
这个测试展示在不同的环境不同的习惯下的click 情景;通常下,海豚只会发出一次震动,但是当它们发现特别有趣的事情的时候,就会发出多次的震动;
这些情况可以使用context函数:一个正常的context和当海豚接近感兴趣的东西的context

// Swift

import Quick
import Nimble

class DolphinSpec: QuickSpec {
  override func spec() {
    describe("a dolphin") {
      var dolphin: Dolphin!
      beforeEach { dolphin = Dolphin() }

      describe("its click") {
        context("when the dolphin is not near anything interesting") {
          it("is only emitted once") {
            expect(dolphin!.click().count).to(equal(1))
          }
        }

        context("when the dolphin is near something interesting") {
          beforeEach {
            let ship = SunkenShip()
            Jamaica.dolphinCove.add(ship)
            Jamaica.dolphinCove.add(dolphin)
          }

          it("is emitted three times") {
            expect(dolphin.click().count).to(equal(3))
          }
        }
      }
    }
  }
}
// Objective-C

@import Quick;
@import Nimble;

QuickSpecBegin(DolphinSpec)

describe(@"a dolphin", ^{
  __block Dolphin *dolphin = nil;
  beforeEach(^{ dolphin = [Dolphin new]; });

  describe(@"its click", ^{
    context(@"when the dolphin is not near anything interesting", ^{
      it(@"is only emitted once", ^{
        expect(@([[dolphin click] count])).to(equal(@1));
      });
    });

    context(@"when the dolphin is near something interesting", ^{
      beforeEach(^{
        [[Jamaica dolphinCove] add:[SunkenShip new]];
        [[Jamaica dolphinCove] add:dolphin];
      });

      it(@"is emitted three times", ^{
        expect(@([[dolphin click] count])).to(equal(@3));
      });
    });
  });
});

QuickSpecEnd

严格的来说,contextdescribe 是同义词;但是严格的规范化会使你的代码更加容易理解;

易读的测试:Quick 和 XCTest

Effective Tests Using XCTest: Arrange, Act, and Assert中, 我们看到每一个测试都使用一种方式测试使得测试高效明确. 在XCTest, 使用一个很长的方法名来表示:

func testDolphin_click_whenTheDolphinIsNearSomethingInteresting_isEmittedThreeTimes() {
  // ...
}

使用 Quick, 这种情况是更加容易去阅读和 我们能为每一个测试组去设置:

describe("a dolphin") {
  describe("its click") {
    context("when the dolphin is near something interesting") {
      it("is emitted three times") {
        // ...
      }
    }
  }
}

暂时禁用ExamplesGroups

你能够暂时禁用ExamplesGroups是测试时不通过;这个测试实例的名称和结果会打印出来,但是并不会执行该方法:
你可以在方法之前使用x来禁用测试方法:

// Swift

xdescribe("its click") {
  // ...none of the code in this closure will be run.
}

xcontext("when the dolphin is not near anything interesting") {
  // ...none of the code in this closure will be run.
}

xit("is only emitted once") {
  // ...none of the code in this closure will be run.
}
// Objective-C

xdescribe(@"its click", ^{
  // ...none of the code in this closure will be run.
});

xcontext(@"when the dolphin is not near anything interesting", ^{
  // ...none of the code in this closure will be run.
});

xit(@"is only emitted once", ^{
  // ...none of the code in this closure will be run.
});

临时的运行测试用例中的一个子集

有时,它可以使得我们更加专注一个或几个例子;运行一个或两个例子比全部运行更快。使用fit函数你可以只运行一个或者两个。你也可以使用fdescribefcontext关注一组例子:

//-------swifit
fit("is loud") {
  // ...only this focused example will be run.
}

it("has a high frequency") {
  // ...this example is not focused, and will not be run.
}

fcontext("when the dolphin is near something interesting") {
  // ...examples in this group are also focused, so they'll be run.
}
//-----oc
fit(@"is loud", {
  // ...only this focused example will be run.
});

it(@"has a high frequency", ^{
  // ...this example is not focused, and will not be run.
});

fcontext(@"when the dolphin is near something interesting", ^{
  // ...examples in this group are also focused, so they'll be run.
});

全局Setup/Teardown 使用beforeSuite / afterSuite

有些测试需要在测试之前进行一些设置或者提前执行一些操作;基于以上的原因使用beforeSuite / afterSuite
在下面的例子中,数据库中所有的海洋中的生物都必须在海洋创建之后运行;在全部的测试实例完成后销毁:

// Swift

import Quick

class DolphinSpec: QuickSpec {
  override func spec() {
    beforeSuite {
      OceanDatabase.createDatabase(name: "test.db")
      OceanDatabase.connectToDatabase(name: "test.db")
    }

    afterSuite {
      OceanDatabase.teardownDatabase(name: "test.db")
    }

    describe("a dolphin") {
      // ...
    }
  }
}
// Objective-C

@import Quick;

QuickSpecBegin(DolphinSpec)

beforeSuite(^{
  [OceanDatabase createDatabase:@"test.db"];
  [OceanDatabase connectToDatabase:@"test.db"];
});

afterSuite(^{
  [OceanDatabase teardownDatabase:@"test.db"];
});

describe(@"a dolphin", ^{
  // ...
});

QuickSpecEnd

如果你喜欢你也可是使用许多的beforeSuiteafterSuite;在测试运行之前执行所有的beforeSuite;在测试完成之后执行所有的afterSuite,在这里闭包是不能保证所有的按照顺序执行;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简简单单lym

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值