Добро пожаловать в двенадцатую главу нашего увлекательного путешествия по Objective-C! В этой главе мы познакомимся с тестированием — важным этапом разработки приложений, который помогает обеспечить их качество и надежность. Вы узнаете, как писать и запускать тесты, использовать фреймворк XCTest, а также получите практические советы по организации процесса тестирования. Как всегда, мы объясним все простым и понятным языком, чтобы вы могли легко во всем разобраться.
После создания проекта вы увидите две цели (Targets):
В папке TestingDemoTests находится файл TestingDemoTests.m, который содержит шаблон для ваших тестов.
#import <XCTest/XCTest.h>
@interface TestingDemoTests : XCTestCase
@end
@implementation TestingDemoTests
- (void)setUp {
[super setUp];
// Код, который выполняется перед запуском каждого теста
}
- (void)tearDown {
// Код, который выполняется после завершения каждого теста
[super tearDown];
}
- (void)testExample {
// Пример тестового метода
XCTAssert(YES, @"Проверка, что выражение истинно");
}
@end
setUp
и tearDown
setUp
: вызывается перед каждым тестовым методом. Используется для подготовки среды.tearDown
: вызывается после каждого тестового метода. Используется для очистки после теста.test
.Пример:
- (void)testAddition {
// Ваш тестовый код
}
Добавим в наш проект класс Calculator
с методом сложения.
Calculator.h
#import <Foundation/Foundation.h>
@interface Calculator : NSObject
- (NSInteger)addNumber:(NSInteger)a toNumber:(NSInteger)b;
@end
Calculator.m
#import "Calculator.h"
@implementation Calculator
- (NSInteger)addNumber:(NSInteger)a toNumber:(NSInteger)b {
return a + b;
}
@end
TestingDemoTests.m
#import <XCTest/XCTest.h>
#import "Calculator.h"
@interface TestingDemoTests : XCTestCase
@property (nonatomic, strong) Calculator *calculator;
@end
setUp
@implementation TestingDemoTests
- (void)setUp {
[super setUp];
// Инициализируем объект калькулятора перед каждым тестом
self.calculator = [[Calculator alloc] init];
}
- (void)tearDown {
// Обнуляем объект калькулятора после каждого теста
self.calculator = nil;
[super tearDown];
}
- (void)testAddition {
NSInteger result = [self.calculator addNumber:5 toNumber:7];
XCTAssertEqual(result, 12, @"Ожидается, что 5 + 7 = 12");
}
XCTAssertEqual
проверяет, что два значения равны.Если мы изменим ожидаемый результат в нашем тесте:
XCTAssertEqual(result, 10, @"Ожидается, что 5 + 7 = 10");
XCTAssert(expression, @"message")
: проверяет, что выражение истинно.XCTAssertTrue(expression, @"message")
: то же самое, что и XCTAssert
.XCTAssertFalse(expression, @"message")
: проверяет, что выражение ложно.XCTAssertEqual(a, b, @"message")
: проверяет, что a
равно b
.XCTAssertNotEqual(a, b, @"message")
: проверяет, что a
не равно b
.XCTAssertNil(a, @"message")
: проверяет, что a
равно nil
.XCTAssertNotNil(a, @"message")
: проверяет, что a
не равно nil
.- (void)testStringIsNotEmpty {
NSString *string = @"Hello, World!";
XCTAssertFalse([string isEqualToString:@""], @"Строка не должна быть пустой");
}
- (void)testArrayContainsObject {
NSArray *array = @[@1, @2, @3];
XCTAssertTrue([array containsObject:@2], @"Массив должен содержать число 2");
}
XCTAssertThrows
для проверки, что метод выбрасывает исключение.Пример:
- (void)testDivisionByZero {
Calculator *calculator = [[Calculator alloc] init];
XCTAssertThrows([calculator divideNumber:10 byNumber:0], @"Ожидается выброс исключения при делении на ноль");
}
divideNumber:byNumber:
в класс Calculator
, который выбрасывает исключение при делении на ноль.Calculator.h
- (double)divideNumber:(double)a byNumber:(double)b;
Calculator.m
- (double)divideNumber:(double)a byNumber:(double)b {
if (b == 0) {
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Деление на ноль" userInfo:nil];
}
return a / b;
}
measureBlock:
для измерения времени выполнения определенного кода.Пример:
- (void)testPerformanceExample {
[self measureBlock:^{
// Код, время выполнения которого нужно измерить
NSMutableArray *array = [NSMutableArray array];
for (NSInteger i = 0; i < 100000; i++) {
[array addObject:@(i)];
}
}];
}
setUp
и tearDown
setUp
.tearDown
.- (void)testUserLoginWithValidCredentials
Пример структуры:
Пример:
- (User *)testUser {
User *user = [[User alloc] init];
user.name = @"Тестовый пользователь";
user.age = 25;
return user;
}
Calculator
метод - (BOOL)isEvenNumber:(NSInteger)number
, который возвращает YES
, если число четное.testIsEvenNumber
для проверки этого метода с разными входными значениями.Решение:
Calculator.m
- (BOOL)isEvenNumber:(NSInteger)number {
return number % 2 == 0;
}
TestingDemoTests.m
- (void)testIsEvenNumber {
XCTAssertTrue([self.calculator isEvenNumber:4], @"4 должно быть четным числом");
XCTAssertFalse([self.calculator isEvenNumber:7], @"7 должно быть нечетным числом");
}
UserManager
метод - (BOOL)loginWithUsername:(NSString *)username password:(NSString *)password error:(NSError **)error
, который проверяет корректность учетных данных.NO
и заполнять NSError
.Решение:
UserManager.h
@interface UserManager : NSObject
- (BOOL)loginWithUsername:(NSString *)username password:(NSString *)password error:(NSError **)error;
@end
UserManager.m
- (BOOL)loginWithUsername:(NSString *)username password:(NSString *)password error:(NSError **)error {
if (username.length == 0 || password.length == 0) {
if (error) {
*error = [NSError errorWithDomain:@"UserManagerError" code:1001 userInfo:@{NSLocalizedDescriptionKey: @"Имя пользователя и пароль не могут быть пустыми"}];
}
return NO;
}
// Логика проверки учетных данных
return YES;
}
UserManagerTests.m
- (void)testLoginWithEmptyUsername {
UserManager *userManager = [[UserManager alloc] init];
NSError *error = nil;
BOOL success = [userManager loginWithUsername:@"" password:@"password123" error:&error];
XCTAssertFalse(success, @"Ожидается, что вход не будет успешным");
XCTAssertNotNil(error, @"Должна быть возвращена ошибка");
XCTAssertEqual(error.code, 1001, @"Код ошибки должен быть 1001");
}
- (void)testLoginWithValidCredentials {
UserManager *userManager = [[UserManager alloc] init];
NSError *error = nil;
BOOL success = [userManager loginWithUsername:@"user" password:@"password123" error:&error];
XCTAssertTrue(success, @"Ожидается, что вход будет успешным");
XCTAssertNil(error, @"Ошибка не должна быть возвращена");
}
measureBlock:
для измерения времени выполнения.Решение:
TestingDemoTests.m
- (void)testSortingPerformance {
// Генерация массива случайных чисел
NSMutableArray *randomNumbers = [NSMutableArray array];
for (NSInteger i = 0; i < 10000; i++) {
[randomNumbers addObject:@(arc4random_uniform(100000))];
}
[self measureBlock:^{
// Код сортировки
NSArray *sortedArray = [randomNumbers sortedArrayUsingSelector:@selector(compare:)];
XCTAssertNotNil(sortedArray, @"Результат сортировки не должен быть nil");
}];
}
Отличная работа! Вы познакомились с основами тестирования в Objective-C, узнали, как использовать фреймворк XCTest для написания и запуска тестов. Тестирование — неотъемлемая часть процесса разработки, и умение писать хорошие тесты делает вас более профессиональным разработчиком.
Мы подошли к концу нашего путешествия по основам Objective-C. Теперь вы обладаете базовыми знаниями и навыками для разработки приложений на этом языке. Не останавливайтесь на достигнутом — продолжайте изучать новые технологии, углубляйте свои знания и практикуйтесь.
Не забывайте:
Удачи в ваших будущих проектах, и пусть ваше кодирование будет успешным и приятным!
Просмотров: 45