鸿蒙轻松背单词应用开发实战(七)-应用测试与性能优化

前言

测试和性能优化是保证应用质量的关键环节。本文详细介绍轻松背单词应用的测试策略和性能优化实践。

为什么需要测试和优化?

  1. 质量保证:确保功能正确性
  2. 性能提升:提高用户体验
  3. 问题预防:及早发现和解决问题
  4. 代码质量:提升代码可维护性

测试优化流程

单元测试

集成测试

性能测试

优化实施

验证结果

满足要求?

发布

一、单元测试

1.1 测试框架配置

import { describe, it, expect, beforeEach } from '@ohos/hypium';

export default function wordModelTest() {
  describe('WordModel', () => {
    let word: WordModel;
    
    beforeEach(() => {
      word = new WordModel();
      word.id = 1;
      word.word = 'apple';
      word.translation = '苹果';
      word.phonetic = '/ˈæpl/';
    });
    
    it('should create word model correctly', () => {
      expect(word.id).assertEqual(1);
      expect(word.word).assertEqual('apple');
      expect(word.translation).assertEqual('苹果');
    });
    
    it('should return correct display text', () => {
      const displayText = word.getDisplayText();
      expect(displayText).assertEqual('apple - 苹果');
    });
  });
}

1.2 数据管理器测试

export default function dataManagerTest() {
  describe('WordDataManager', () => {
    let manager: WordDataManager;
    
    beforeEach(() => {
      manager = WordDataManager.getInstance();
    });
    
    it('should be singleton', () => {
      const instance1 = WordDataManager.getInstance();
      const instance2 = WordDataManager.getInstance();
      expect(instance1 === instance2).assertTrue();
    });
    
    it('should add word correctly', () => {
      const word = new WordModel();
      word.word = 'test';
      word.translation = '测试';
      
      manager.addWord(word);
      const words = manager.getAllWords();
      
      expect(words.length).assertLarger(0);
    });
    
    it('should search words correctly', () => {
      const results = manager.searchWords('app');
      expect(results.length).assertLarger(0);
      
      for (const word of results) {
        expect(word.word.includes('app')).assertTrue();
      }
    });
  });
}

1.3 文件解析器测试

export default function fileParserTest() {
  describe('FileParser', () => {
    let parser: FileParser;
    
    beforeEach(() => {
      parser = new FileParser();
    });
    
    it('should parse TXT file correctly', async () => {
      const content = 'apple - 苹果\nbanana - 香蕉';
      const words = await parser.parseTXT(content);
      
      expect(words.length).assertEqual(2);
      expect(words[0].word).assertEqual('apple');
      expect(words[1].word).assertEqual('banana');
    });
    
    it('should handle empty content', async () => {
      const words = await parser.parseTXT('');
      expect(words.length).assertEqual(0);
    });
    
    it('should handle invalid format', async () => {
      const content = 'invalid line without separator';
      const words = await parser.parseTXT(content);
      expect(words.length).assertEqual(0);
    });
  });
}

二、集成测试

2.1 页面集成测试

export default function pageIntegrationTest() {
  describe('MainPage Integration', () => {
    it('should display word list after import', async () => {
      // 导入单词文件
      const fileContent = 'apple - 苹果\nbanana - 香蕉';
      await WordDataManager.getInstance().importWords(fileContent);
      
      // 验证单词列表显示
      const wordList = await driver.findComponent(BY.text('apple'));
      expect(wordList).assertNotNull();
    });
    
    it('should navigate to study page', async () => {
      // 点击学习按钮
      const studyButton = await driver.findComponent(BY.text('开始学习'));
      await studyButton.click();
      
      // 验证页面跳转
      const studyPage = await driver.findComponent(BY.text('手动涂抹'));
      expect(studyPage).assertNotNull();
    });
  });
}

2.2 数据流集成测试

export default function dataFlowTest() {
  describe('Data Flow Integration', () => {
    it('should save study progress correctly', async () => {
      const manager = WordDataManager.getInstance();
      const progressManager = ProgressManager.getInstance();
      
      // 添加单词
      const word = new WordModel();
      word.id = 1;
      word.word = 'test';
      word.translation = '测试';
      manager.addWord(word);
      
      // 记录学习结果
      progressManager.recordResult(1, true);
      
      // 验证进度
      const progress = progressManager.getProgress(1);
      expect(progress).assertNotNull();
      expect(progress?.totalAttempts).assertEqual(1);
      expect(progress?.correctAttempts).assertEqual(1);
    });
  });
}

2.3 测试流程图

界面 数据层 应用 测试用例 界面 数据层 应用 测试用例 初始化应用 准备测试数据 执行UI操作 触发数据更新 返回更新结果 验证UI状态 验证数据状态

三、性能测试

3.1 启动性能测试

export default function startupPerformanceTest() {
  describe('Startup Performance', () => {
    it('should start within 2 seconds', async () => {
      const startTime = Date.now();
      
      // 启动应用
      await driver.startApp('com.example.wordstudy');
      
      const endTime = Date.now();
      const duration = endTime - startTime;
      
      expect(duration).assertLess(2000);
    });
    
    it('should load words within 500ms', async () => {
      const startTime = Date.now();
      
      // 加载单词列表
      await WordDataManager.getInstance().loadWords();
      
      const endTime = Date.now();
      const duration = endTime - startTime;
      
      expect(duration).assertLess(500);
    });
  });
}

3.2 渲染性能测试

export default function renderPerformanceTest() {
  describe('Render Performance', () => {
    it('should render 100 words within 1 second', async () => {
      // 准备100个单词
      const words = generateTestWords(100);
      WordDataManager.getInstance().setWords(words);
      
      const startTime = Date.now();
      
      // 渲染单词列表
      await driver.findComponent(BY.id('word_list'));
      
      const endTime = Date.now();
      const duration = endTime - startTime;
      
      expect(duration).assertLess(1000);
    });
    
    it('should scroll smoothly', async () => {
      const list = await driver.findComponent(BY.id('word_list'));
      
      const startTime = Date.now();
      
      // 滚动列表
      for (let i = 0; i < 10; i++) {
        await list.scroll(Direction.Down, 100);
      }
      
      const endTime = Date.now();
      const duration = endTime - startTime;
      
      // 平均每帧小于16.67ms
      expect(duration / 10).assertLess(16.67);
    });
  });
}

3.3 内存性能测试

export default function memoryPerformanceTest() {
  describe('Memory Performance', () => {
    it('should not have memory leak', async () => {
      const initialMemory = getMemoryUsage();
      
      // 执行多次操作
      for (let i = 0; i < 100; i++) {
        const manager = WordDataManager.getInstance();
        manager.addWord(generateTestWord());
        manager.clearCache();
      }
      
      const finalMemory = getMemoryUsage();
      const memoryIncrease = finalMemory - initialMemory;
      
      // 内存增长不超过10MB
      expect(memoryIncrease).assertLess(10 * 1024 * 1024);
    });
  });
}

图 1 运行日志界面
在这里插入图片描述

四、性能优化

4.1 启动优化

// 延迟加载非关键资源
@Entry
@Component
struct MainPage {
  @State isReady: boolean = false;
  
  async aboutToAppear() {
    // 并行加载关键数据
    await Promise.all([
      this.loadUserSettings(),
      this.loadCurrentBook()
    ]);
    
    this.isReady = true;
    
    // 延迟加载非关键数据
    setTimeout(() => {
      this.loadStatistics();
      this.loadRecommendations();
    }, 1000);
  }
  
  build() {
    if (!this.isReady) {
      this.LoadingView();
    } else {
      this.MainContent();
    }
  }
}

4.2 渲染优化

// 使用LazyForEach优化长列表
@Component
struct OptimizedWordList {
  private dataSource: WordDataSource = new WordDataSource();
  
  build() {
    List() {
      LazyForEach(this.dataSource, (word: WordModel) => {
        ListItem() {
          WordItem({ word: word });
        }
      }, (word: WordModel) => word.id.toString());
    }
    .width('100%')
    .height('100%')
    .cachedCount(5)  // 缓存5个列表项
    .scrollBar(BarState.Auto);
  }
}

// 数据源实现
class WordDataSource implements IDataSource {
  private words: WordModel[] = [];
  private listeners: DataChangeListener[] = [];
  
  totalCount(): number {
    return this.words.length;
  }
  
  getData(index: number): WordModel {
    return this.words[index];
  }
  
  registerDataChangeListener(listener: DataChangeListener): void {
    this.listeners.push(listener);
  }
}

4.3 内存优化

// 使用对象池减少内存分配
export class ObjectPool<T> {
  private pool: T[] = [];
  private factory: () => T;
  
  constructor(factory: () => T, initialSize: number = 10) {
    this.factory = factory;
    
    for (let i = 0; i < initialSize; i++) {
      this.pool.push(factory());
    }
  }
  
  acquire(): T {
    if (this.pool.length > 0) {
      return this.pool.pop()!;
    }
    return this.factory();
  }
  
  release(obj: T): void {
    this.pool.push(obj);
  }
}

// 使用示例
const wordPool = new ObjectPool<WordModel>(() => new WordModel(), 20);

function processWord(data: any): WordModel {
  const word = wordPool.acquire();
  word.word = data.word;
  word.translation = data.translation;
  return word;
}

function releaseWord(word: WordModel): void {
  wordPool.release(word);
}

4.4 性能优化流程

启动

渲染

内存

网络

性能问题

性能分析

瓶颈类型

启动优化

渲染优化

内存优化

网络优化

实施优化

性能测试

满足要求?

优化完成

五、网络优化

5.1 请求优化

export class NetworkManager {
  private static instance: NetworkManager;
  private requestQueue: Map<string, Promise<any>> = new Map();
  
  static getInstance(): NetworkManager {
    if (!NetworkManager.instance) {
      NetworkManager.instance = new NetworkManager();
    }
    return NetworkManager.instance;
  }
  
  // 请求去重
  async request<T>(url: string, options: RequestOptions): Promise<T> {
    // 检查是否有相同请求正在进行
    const key = `${url}_${JSON.stringify(options)}`;
    if (this.requestQueue.has(key)) {
      return this.requestQueue.get(key)!;
    }
    
    const promise = this.doRequest<T>(url, options);
    this.requestQueue.set(key, promise);
    
    try {
      const result = await promise;
      return result;
    } finally {
      this.requestQueue.delete(key);
    }
  }
  
  // 批量请求
  async batchRequest<T>(urls: string[]): Promise<T[]> {
    return Promise.all(urls.map(url => this.request<T>(url, {})));
  }
}

5.2 缓存策略

export class CacheStrategy {
  // 缓存优先
  static async cacheFirst<T>(
    key: string,
    fetcher: () => Promise<T>,
    ttl: number = 3600000
  ): Promise<T> {
    const cached = MemoryCache.getInstance().get(key);
    if (cached) {
      return cached;
    }
    
    const data = await fetcher();
    MemoryCache.getInstance().set(key, data, ttl);
    return data;
  }
  
  // 网络优先
  static async networkFirst<T>(
    key: string,
    fetcher: () => Promise<T>,
    ttl: number = 3600000
  ): Promise<T> {
    try {
      const data = await fetcher();
      MemoryCache.getInstance().set(key, data, ttl);
      return data;
    } catch (error) {
      const cached = MemoryCache.getInstance().get(key);
      if (cached) {
        return cached;
      }
      throw error;
    }
  }
}

六、监控与分析

6.1 性能监控

export class PerformanceMonitor {
  private static instance: PerformanceMonitor;
  private metrics: Map<string, number[]> = new Map();
  
  static getInstance(): PerformanceMonitor {
    if (!PerformanceMonitor.instance) {
      PerformanceMonitor.instance = new PerformanceMonitor();
    }
    return PerformanceMonitor.instance;
  }
  
  // 记录性能指标
  recordMetric(name: string, value: number): void {
    if (!this.metrics.has(name)) {
      this.metrics.set(name, []);
    }
    this.metrics.get(name)!.push(value);
  }
  
  // 计算平均值
  getAverage(name: string): number {
    const values = this.metrics.get(name);
    if (!values || values.length === 0) return 0;
    
    const sum = values.reduce((a, b) => a + b, 0);
    return sum / values.length;
  }
  
  // 性能装饰器
  static measure(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    
    descriptor.value = async function (...args: any[]) {
      const startTime = Date.now();
      const result = await originalMethod.apply(this, args);
      const duration = Date.now() - startTime;
      
      PerformanceMonitor.getInstance().recordMetric(propertyKey, duration);
      
      return result;
    };
  }
}

6.2 性能分析报告

export class PerformanceReport {
  generateReport(): PerformanceSummary {
    const monitor = PerformanceMonitor.getInstance();
    
    return {
      startupTime: monitor.getAverage('startup'),
      renderTime: monitor.getAverage('render'),
      networkTime: monitor.getAverage('network'),
      memoryUsage: getMemoryUsage(),
      cpuUsage: getCPUUsage()
    };
  }
}

七、总结

本文详细介绍了应用测试与性能优化的实践。通过单元测试、集成测试、性能测试和多种优化策略,保证了应用的质量和性能。

核心要点

  1. 测试策略:单元测试、集成测试、性能测试全覆盖
  2. 性能优化:启动优化、渲染优化、内存优化、网络优化
  3. 监控分析:实时监控性能指标,持续优化
  4. 质量保证:测试驱动开发,持续集成

系列文章导航:
下期预告: 鸿蒙轻松背单词应用开发实战(八)-应用发布与运维

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐