| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- //
- // JXIntegrationTests.m
- // AICityTests
- //
- // Feature: 003-ios-api-https
- // 剧星平台集成测试
- //
- #import <XCTest/XCTest.h>
- #import "JXPlaybackProgressStorage.h"
- #import "JXAPIService.h"
- #import "JXCountFormatter.h"
- @interface JXIntegrationTests : XCTestCase
- @property (nonatomic, strong) JXPlaybackProgressStorage *storage;
- @property (nonatomic, strong) JXAPIService *apiService;
- @end
- @implementation JXIntegrationTests
- - (void)setUp {
- [super setUp];
- self.storage = [JXPlaybackProgressStorage sharedStorage];
- self.apiService = [JXAPIService sharedService];
-
- // 清空所有数据
- [self.storage clearAll];
- }
- - (void)tearDown {
- [self.storage clearAll];
- [super tearDown];
- }
- #pragma mark - 存储与API集成测试
- - (void)testStorageAPIIntegration {
- // Given
- NSString *episodeId = @"integration_ep_001";
- NSString *dramaId = @"integration_drama_001";
-
- XCTestExpectation *expectation = [self expectationWithDescription:@"Storage API integration"];
-
- // When - 保存进度到本地
- [self.storage saveProgressWithEpisodeId:episodeId
- dramaId:dramaId
- position:45000
- duration:120000
- isCompleted:NO
- synced:NO
- completion:^(BOOL success, NSError *error) {
- XCTAssertTrue(success, @"本地保存应该成功");
-
- // Then - 验证本地数据
- JXPlaybackProgressModel *progress = [self.storage getProgressWithEpisodeId:episodeId];
- XCTAssertNotNil(progress, @"应该能获取到本地数据");
- XCTAssertEqual(progress.position, 45000);
- XCTAssertEqualWithAccuracy(progress.progress, 0.375f, 0.01f); // 45000/120000
-
- [expectation fulfill];
- }];
-
- [self waitForExpectationsWithTimeout:5.0 handler:nil];
- }
- - (void)testMultipleEpisodesIntegration {
- // Given
- NSString *dramaId = @"multi_integration_drama";
- NSArray *episodes = @[@"ep001", @"ep002", @"ep003"];
-
- XCTestExpectation *expectation = [self expectationWithDescription:@"Multiple episodes"];
-
- // When - 保存多集进度
- __block NSInteger completedCount = 0;
- for (NSInteger i = 0; i < episodes.count; i++) {
- NSString *episodeId = episodes[i];
- [self.storage saveProgressWithEpisodeId:episodeId
- dramaId:dramaId
- position:(i + 1) * 30000
- duration:120000
- isCompleted:NO
- synced:NO
- completion:^(BOOL success, NSError *error) {
- completedCount++;
- if (completedCount == episodes.count) {
- // Then - 验证所有进度
- NSArray<JXPlaybackProgressModel *> *progresses = [self.storage getProgressByDramaId:dramaId];
- XCTAssertEqual(progresses.count, 3, @"应该有3集的进度");
-
- // 验证进度按更新时间排序
- for (NSInteger j = 0; j < progresses.count - 1; j++) {
- XCTAssertTrue([progresses[j].updatedAt compare:progresses[j+1].updatedAt] != NSOrderedAscending,
- @"进度应该按更新时间排序");
- }
-
- [expectation fulfill];
- }
- }];
- }
-
- [self waitForExpectationsWithTimeout:10.0 handler:nil];
- }
- - (void)testProgressUpdateFlow {
- // Given
- NSString *episodeId = @"update_flow_ep";
- NSString *dramaId = @"update_flow_drama";
-
- XCTestExpectation *expectation1 = [self expectationWithDescription:@"Initial save"];
- XCTestExpectation *expectation2 = [self expectationWithDescription:@"Update progress"];
- XCTestExpectation *expectation3 = [self expectationWithDescription:@"Complete progress"];
-
- // Step 1: 初始进度
- [self.storage saveProgressWithEpisodeId:episodeId
- dramaId:dramaId
- position:30000
- duration:120000
- isCompleted:NO
- synced:NO
- completion:^(BOOL success, NSError *error) {
- XCTAssertTrue(success);
-
- JXPlaybackProgressModel *progress = [self.storage getProgressWithEpisodeId:episodeId];
- XCTAssertEqual(progress.position, 30000);
-
- [expectation1 fulfill];
-
- // Step 2: 更新进度
- [self.storage saveProgressWithEpisodeId:episodeId
- dramaId:dramaId
- position:90000
- duration:120000
- isCompleted:NO
- synced:NO
- completion:^(BOOL success, NSError *error) {
- XCTAssertTrue(success);
-
- JXPlaybackProgressModel *updatedProgress = [self.storage getProgressWithEpisodeId:episodeId];
- XCTAssertEqual(updatedProgress.position, 90000);
- XCTAssertEqualWithAccuracy(updatedProgress.progress, 0.75f, 0.01f);
-
- [expectation2 fulfill];
-
- // Step 3: 完成观看
- [self.storage saveProgressWithEpisodeId:episodeId
- dramaId:dramaId
- position:114000
- duration:120000
- isCompleted:YES
- synced:NO
- completion:^(BOOL success, NSError *error) {
- XCTAssertTrue(success);
-
- JXPlaybackProgressModel *completedProgress = [self.storage getProgressWithEpisodeId:episodeId];
- XCTAssertTrue(completedProgress.isCompleted);
- XCTAssertTrue(completedProgress.progress >= 0.95f);
-
- [expectation3 fulfill];
- }];
- }];
- }];
-
- [self waitForExpectationsWithTimeout:15.0 handler:nil];
- }
- - (void)testSyncStatusManagement {
- // Given
- NSArray *episodeIds = @[@"sync_ep_001", @"sync_ep_002", @"sync_ep_003"];
- NSString *dramaId = @"sync_drama";
-
- XCTestExpectation *expectation = [self expectationWithDescription:@"Sync management"];
-
- // When - 保存未同步的进度
- __block NSInteger savedCount = 0;
- for (NSString *episodeId in episodeIds) {
- [self.storage saveProgressWithEpisodeId:episodeId
- dramaId:dramaId
- position:30000
- duration:120000
- isCompleted:NO
- synced:NO
- completion:^(BOOL success, NSError *error) {
- savedCount++;
- if (savedCount == episodeIds.count) {
- // 验证未同步状态
- NSArray<JXPlaybackProgressModel *> *unsyncedProgresses = [self.storage getUnsyncedProgresses];
- XCTAssertTrue(unsyncedProgresses.count >= episodeIds.count, @"应该有未同步的进度");
-
- // 标记第一个为已同步
- [self.storage markAsSyncedWithEpisodeId:episodeIds[0]];
-
- // 验证同步状态
- JXPlaybackProgressModel *syncedProgress = [self.storage getProgressWithEpisodeId:episodeIds[0]];
- XCTAssertTrue(syncedProgress.synced, @"应该被标记为已同步");
-
- NSArray<JXPlaybackProgressModel *> *remainingUnsynced = [self.storage getUnsyncedProgresses];
- BOOL foundSyncedInUnsynced = NO;
- for (JXPlaybackProgressModel *progress in remainingUnsynced) {
- if ([progress.episodeId isEqualToString:episodeIds[0]]) {
- foundSyncedInUnsynced = YES;
- break;
- }
- }
- XCTAssertFalse(foundSyncedInUnsynced, @"已同步的进度不应该在未同步列表中");
-
- [expectation fulfill];
- }
- }];
- }
-
- [self waitForExpectationsWithTimeout:10.0 handler:nil];
- }
- #pragma mark - 数据一致性测试
- - (void)testDataConsistencyAcrossOperations {
- // Given
- NSString *dramaId = @"consistency_drama";
- NSArray *episodeIds = @[@"ep001", @"ep002", @"ep003", @"ep004", @"ep005"];
-
- XCTestExpectation *expectation = [self expectationWithDescription:@"Data consistency"];
-
- // When - 并发保存多个进度
- __block NSInteger completedOperations = 0;
- for (NSString *episodeId in episodeIds) {
- int64_t position = [episodeId hash] % 100000;
- [self.storage saveProgressWithEpisodeId:episodeId
- dramaId:dramaId
- position:position
- duration:120000
- isCompleted:NO
- synced:NO
- completion:^(BOOL success, NSError *error) {
- completedOperations++;
- if (completedOperations == episodeIds.count) {
- // Then - 验证数据一致性
- NSArray<JXPlaybackProgressModel *> *allProgresses = [self.storage getProgressByDramaId:dramaId];
- XCTAssertEqual(allProgresses.count, episodeIds.count, @"应该有所有集的进度");
-
- // 验证每个进度的数据完整性
- for (NSString *episodeId in episodeIds) {
- JXPlaybackProgressModel *progress = [self.storage getProgressWithEpisodeId:episodeId];
- XCTAssertNotNil(progress, @"进度应该存在");
- XCTAssertEqualObjects(progress.dramaId, dramaId);
- XCTAssertTrue(progress.position >= 0);
- XCTAssertEqual(progress.duration, 120000);
- XCTAssertTrue(progress.progress >= 0.0f && progress.progress <= 1.0f);
- }
-
- [expectation fulfill];
- }
- }];
- }
-
- [self waitForExpectationsWithTimeout:10.0 handler:nil];
- }
- #pragma mark - 格式化工具集成测试
- - (void)testCountFormatterIntegration {
- // 测试格式化工具在实际场景中的使用
- NSArray *testCounts = @[@0, @999, @1500, @12345, @123456, @1234567, @123456789];
-
- for (NSNumber *count in testCounts) {
- long long countValue = [count longLongValue];
-
- // 测试所有格式化方法都能正常工作
- NSString *basicFormat = [JXCountFormatter formatCount:countValue];
- NSString *likeFormat = [JXCountFormatter formatLikeCount:countValue];
- NSString *commentFormat = [JXCountFormatter formatCommentCount:countValue];
- NSString *shareFormat = [JXCountFormatter formatShareCount:countValue];
- NSString *favoriteFormat = [JXCountFormatter formatFavoriteCount:countValue];
- NSString *playFormat = [JXCountFormatter formatPlayCount:countValue];
-
- // 验证格式化结果不为空
- XCTAssertNotNil(basicFormat);
- XCTAssertNotNil(likeFormat);
- XCTAssertNotNil(commentFormat);
- XCTAssertNotNil(shareFormat);
- XCTAssertNotNil(favoriteFormat);
- XCTAssertNotNil(playFormat);
-
- // 验证非零值的格式化一致性
- if (countValue > 0) {
- XCTAssertEqualObjects(basicFormat, likeFormat);
- XCTAssertEqualObjects(basicFormat, commentFormat);
- XCTAssertEqualObjects(basicFormat, shareFormat);
- XCTAssertEqualObjects(basicFormat, favoriteFormat);
- }
- }
- }
- #pragma mark - 错误处理测试
- - (void)testErrorHandlingIntegration {
- // 测试各种错误情况下的系统行为
-
- // 测试空字符串输入
- XCTestExpectation *expectation1 = [self expectationWithDescription:@"Empty string handling"];
- [self.storage saveProgressWithEpisodeId:@""
- dramaId:@"test_drama"
- position:30000
- duration:120000
- isCompleted:NO
- synced:NO
- completion:^(BOOL success, NSError *error) {
- // 应该处理错误而不崩溃
- [expectation1 fulfill];
- }];
-
- // 测试极端数值
- XCTestExpectation *expectation2 = [self expectationWithDescription:@"Extreme values"];
- [self.storage saveProgressWithEpisodeId:@"extreme_test"
- dramaId:@"test_drama"
- position:LLONG_MAX
- duration:120000
- isCompleted:NO
- synced:NO
- completion:^(BOOL success, NSError *error) {
- // 应该处理极端值而不崩溃
- [expectation2 fulfill];
- }];
-
- [self waitForExpectationsWithTimeout:10.0 handler:nil];
-
- // 验证系统仍然正常工作
- XCTestExpectation *expectation3 = [self expectationWithDescription:@"Normal operation after errors"];
- [self.storage saveProgressWithEpisodeId:@"normal_after_error"
- dramaId:@"test_drama"
- position:30000
- duration:120000
- isCompleted:NO
- synced:NO
- completion:^(BOOL success, NSError *error) {
- XCTAssertTrue(success, @"正常操作应该仍然有效");
- [expectation3 fulfill];
- }];
-
- [self waitForExpectationsWithTimeout:5.0 handler:nil];
- }
- #pragma mark - 单例模式测试
- - (void)testSingletonBehavior {
- // 验证存储管理器的单例行为
- JXPlaybackProgressStorage *storage1 = [JXPlaybackProgressStorage sharedStorage];
- JXPlaybackProgressStorage *storage2 = [JXPlaybackProgressStorage sharedStorage];
-
- XCTAssertTrue(storage1 == storage2, @"应该返回同一个实例");
-
- // 验证API服务的单例行为
- JXAPIService *service1 = [JXAPIService sharedService];
- JXAPIService *service2 = [JXAPIService sharedService];
-
- XCTAssertTrue(service1 == service2, @"应该返回同一个实例");
- }
- #pragma mark - 清理操作测试
- - (void)testCleanupOperations {
- // Given - 创建测试数据
- NSArray *episodeIds = @[@"cleanup_ep_001", @"cleanup_ep_002", @"cleanup_ep_003"];
- NSString *dramaId = @"cleanup_drama";
-
- XCTestExpectation *setupExpectation = [self expectationWithDescription:@"Setup data"];
-
- __block NSInteger setupCount = 0;
- for (NSString *episodeId in episodeIds) {
- [self.storage saveProgressWithEpisodeId:episodeId
- dramaId:dramaId
- position:30000
- duration:120000
- isCompleted:NO
- synced:YES
- completion:^(BOOL success, NSError *error) {
- setupCount++;
- if (setupCount == episodeIds.count) {
- [setupExpectation fulfill];
- }
- }];
- }
-
- [self waitForExpectationsWithTimeout:5.0 handler:nil];
-
- // When - 执行清理操作
- [self.storage cleanupOldRecords];
-
- // Then - 验证新数据不会被清理(因为刚创建)
- for (NSString *episodeId in episodeIds) {
- JXPlaybackProgressModel *progress = [self.storage getProgressWithEpisodeId:episodeId];
- XCTAssertNotNil(progress, @"新数据不应该被清理");
- }
-
- // 测试按剧删除
- [self.storage deleteProgressByDramaId:dramaId];
-
- NSArray<JXPlaybackProgressModel *> *remainingProgresses = [self.storage getProgressByDramaId:dramaId];
- XCTAssertEqual(remainingProgresses.count, 0, @"删除后应该没有进度");
- }
- @end
|