A baseline is a combination of the average time performance in ten runs of the test method with a measure of the standard deviation of each run.
Where to Start When Testing
When you start to create tests, keep the following ideas in mind:
When creating unit tests, focus on testing the most basic foundations of your code, the Model classes and methods, which interact with the Controller. 单元测试需要对每个细小的代码单元进行测试，单元的划分要合理
When creating UI tests, start by considering the most common workflows. Think of what the user does when getting started using the app and what UI is exercised immediately in that process. Using the UI recording feature is a great way to capture a sequence of user actions into a UI test method that can be expanded upon to implement tests for correctness and/or performance.
UI tests of this type tend to start with a relatively coarse-grained focus and might cut across several subsystems; they can return a lot of information that can be hard to analyze at first. As you work with your UI test suite, you can refine the testing granularity and focus UI tests to reflect specific subsystem behaviors more clearly. UI测试，按照最平常的操作流程写测试代码，考虑界面应该如何正确响应，多次测试之后再慢慢去细化测试的每个部分
Flow of Test Execution
For each class, testing starts by running the class setup method. For each test method, a new instance of the class is allocated and its instance setup method executed. After that it runs the test method, and after that the instance teardown method. This sequence repeats for all the test methods in the class. After the last test method teardown in the class has been run, Xcode executes the class teardown method and moves on to the next class. This sequence repeats until all the test methods in all test classes have been run.
简单来说，这个顺序从前往后就是：class func setUp() , func setUp() , func testFunc() , func tearDown() , class func tesrDown() 。
Writing Tests with Swift
The Swift access control model, as described in the Access Control section of The Swift Programming Language (Swift 4), prevents an external entity from accessing anything declared as internal in an app or framework. By default, to be able to access these items from your test code, you would need to elevate their access level to at least public, reducing the benefits of Swift’s type safety.
Xcode provides a two-part solution to this problem:
When you set the
Enable Testabilitybuild setting to
Yes, which is true by default for test builds in new projects, Xcode includes the
-enable-testingflag during compilation. This makes the Swift entities declared in the compiled module eligible for a higher level of access.
When you add the
@testableattribute to an import statement for a module compiled with testing enabled, you activate the elevated access for that module in that scope. Classes and class members marked as internal or public behave as if they were marked open. Other entities marked as internal act as if they were declared public.
@testable provides access only for internal functions; file-private and private declarations are not visible outside of their usual scope when using
Using Assertions with Objective-C and Swift
For Objective-C, assertions marked for scalar types can be used with the types that can be used with the equality comparison operators:
>. If the expression resolves to any C type, struct, or array comparison that works with these operators, it is considered a scalar. 使用Objc写测试代码时，要注意值类型和引用类型的区别，而Swift不用。
Using XCTest assertions in your tests also differs between Objective-C and Swift because of how the languages differ in treating data types and implicit conversions.
For Objective-C, the use of implicit conversions in the XCTest implementation allows the comparisons to operate independent of the expressions’ data types, and no check is made of the input data types.
For Swift, implicit conversions are not allowed because Swift is stricter about type safety; both parameters to a comparison must be of the same type. Type mismatches are flagged at compile time and in the source editor.
Test Debugging Workflow
Here are some common issues to keep in mind:
Is the logic of the test correct? Is the implementation correct? 逻辑是否正确？实现是否正确？字面量有没有打错？
It’s always a good idea to check for typos and incorrect literal values that you might be using as the reference standard that the test method is using as a basis of comparison.
What are the assumptions? 多定义一些错误类型，写测试的时候也有可能传错数据
For example, you might be using the wrong data type in the test method, creating a range error for the code you’re testing.
Are you using the correct assertion to report the pass/fail status? 有没有用错Assetion？
For example, perhaps the condition of the test needs
XCTAssertFalse. It’s sometimes easy to make this error.
Enable Code Coverage
Code coverage data collection incurs a performance penalty. Whether the penalty is significant or not, it should affect execution of the code in a linear fashion so performance results remain comparable from test run to test run when it is enabled. However, you should consider whether to have code coverage enabled when you are critically evaluating the performance of routines in your tests.
Writing Testable Code
Define API requirements. It is important to define requirements and outcomes for each method or function that you add to your project. For requirements, include input and output ranges, exceptions thrown and the conditions under which they are raised, and the type of values returned (especially if the values are instances of classes). Specifying requirements and making sure that requirements are met in your code help you write robust, secure code.
See the Unit Testing Apps and Frameworks sample-code project for an example of using exceptions to identify and report incorrect library usage by client code. 尽可能避免使用全局变量，传参到方法里然后返回某种类型的结果
Write test cases as you write code. As you design and write each method or function, write one or more test cases to ensure that the API’s requirements are met. Remember that it’s harder to write tests for existing code than for code you are writing. 尽早写测试代码，写一个方法就写对应的测试代码，为已有的代码写测试极其痛苦！
Check boundary conditions. If a parameter for a method must have values in a specific range, your tests should pass values that include the lowest and highest values of the range. For example, if a procedure has an integer parameter that can have values between
100, inclusive, the test code for that method should pass the values
100for the parameter. 测试用例使用的测试值要覆盖全面的情况
Use negative tests. Negative tests ensure that your code responds to error conditions appropriately. Verify that your code behaves correctly when it receives invalid or unexpected input values. Also verify that it returns error codes or raises exceptions when it should. For example, if an integer parameter must have values in the range
100, inclusive, create test cases that pass the values
101to ensure that the procedure raises an exception or returns an error code. 测试用例甚至需要使用各种异常的值，比如越界、类型异常等等都可以考虑在内
Write comprehensive test cases. Comprehensive tests combine different code modules to implement some of the more complex behavior of your API. Although simple, isolated tests provide value, stacked tests exercise complex behaviors and tend to catch many more problems. These kinds of tests mimic the behavior of your code under more realistic conditions. For example, in addition to adding objects to an array, you could create the array, add several objects to it, remove a few of them using different methods, and then ensure that the set and number of remaining objects are correct. 将测试用例综合起来进行测试，有些测试用例分开进行时没问题，结合起来就发生了故障
Cover your bug fixes with test cases. Whenever you fix a bug, write one or more tests cases that verify the fix. 修复BUG之后，完善BUG对应的测试用例