自动化测试框架如何读取应用内的文件
=================

#### 问题现象

使用自动化测试框架编写一些脚本模拟用户的行为，比如打开应用，点击某些页面，触发某些异常，然后需要将产生的结果数据与理想的结果的数据进行对比并校验。

结果数据存储在应用沙箱，如何读取这些数据？

#### 背景知识

1.  基于Hypium的自动化测试框架指南：[应用UI测试（基于Python）](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/hypium-python-guidelines)。
2.  基于单元测试和UI测试的自动化测试框架指南：[自动化测试框架使用指导](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkxtest-guidelines)。

#### 解决方案

假设要测试如下代码：

import { fileIo as fs, ReadOptions } from '@kit.CoreFileKit';
import { buffer } from '@kit.ArkTS';

@Entry
@Component
struct Index {
  hostContext = this.getUIContext().getHostContext();

  build() {
    Column() {
      Button('保存文件')
        .id('save')
        .onClick(async () => {
          await this.saveFile();
        })
    }
    .height('100%')
    .width('100%')
  }

  async saveFile() {
    const str = '测试数据';
    const file\_path = this.hostContext?.cacheDir + '/test.txt';
    let file = fs.openSync(file\_path, fs.OpenMode.READ\_WRITE | fs.OpenMode.CREATE);
    try {
      await fs.write(file.fd, str);
      let arrayBuffer = new ArrayBuffer(1024);
      let readOptions: ReadOptions = {
        offset: 0,
        length: arrayBuffer.byteLength
      };
      let readLen = await fs.read(file.fd, arrayBuffer, readOptions);
      let buf = buffer.from(arrayBuffer, 0, readLen);
      console.info('文件内容: ' + buf.toString());
    } catch {
      console.error('something wrong');
    } finally {
      fs.close(file);
    }

  }
}

*   **方案1**：基于Hypium的自动化测试框架。
    
    通过driver.pull\_file将应用内的文件内容读取到PC侧，然后通过Python的with open()方法获取到file对象，即可比对数据。
    
    from devicetest.core.test\_case import TestCase, Step
    from hypium import UiDriver, BY
    
    
    class TC\_001(TestCase):
    
        def \_\_init\_\_(self, controllers):
            self.TAG = self.\_\_class\_\_.\_\_name\_\_
            super().\_\_init\_\_(self.TAG, controllers)
            self.driver = UiDriver(self.device1)
            self.packageName = "com.huawei.myapplication"
            self.abilityName = "EntryAbility"
    
        def setup(self):
            Step('1.关闭应用')
            self.driver.stop\_app(self.packageName)
    
        def process(self):
            Step('2.启动应用')
            self.driver.start\_app(self.packageName, self.abilityName)
    
            Step('3.点击保存数据按钮')
            component = self.driver.find\_component(BY.text('保存文件'))
            component.click()
    
            Step('4.获取应用缓存文件')  _\# 此处需要使用真实路径_
            self.driver.pull\_file(f"/data/app/el2/100/base/{self.packageName}/haps/entry/cache/test.txt", "test.txt")
            Step('5.读取本地文件')
            with open('test.txt', 'r', encoding='utf-8') as f:
                data = f.read()
                print(data)
                self.driver.log.info('文件数据: ' + data)
    
*   **方案2**：基于UITest的自动化测试。
    
    通过[fs.openSync](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-file-fs#fsopensync)读取应用文件后通过expect()断言比对数据。
    
    import { describe, it, expect } from '@ohos/hypium';
    _// 导入测试依赖kit_
    import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit';
    import { UIAbility, Want } from '@kit.AbilityKit';
    import {fileIo as fs, ReadOptions } from '@kit.CoreFileKit'
    import { buffer } from '@kit.ArkTS';
    
    const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator()
    const bundleName = abilityDelegatorRegistry.getArguments().bundleName;
    function sleep(time: number) {
      return new Promise<void>((resolve: Function) => setTimeout(resolve, time));
    }
    
    export default function abilityTest() {
      describe('IndexTextTest', () => {
        _// UI测试_
        it('testUiExample',0, async (done: Function) => {
          console.info("uitest: TestUiExample begin");
          //start tested ability
          const want: Want = {
            bundleName: bundleName,
            abilityName: 'EntryAbility'
          }
          await delegator.startAbility(want);
          await sleep(1000);
      _    //check top display ability_
          const ability: UIAbility = await delegator.getCurrentTopAbility();
          console.info("get top ability");
          expect(ability.context.abilityInfo.name).assertEqual('EntryAbility');
         _ //init driver_
          const driver = Driver.create();
    
         _ // 读取应用缓存目录下的文件_
          const save\_file\_btn = await driver.findComponent(ON.id('save'));
          await save\_file\_btn.click();
          await driver.delayMs(1000);
          const file\_path = ability.context.cacheDir + '/test.txt'
          let file = fs.openSync(file\_path,fs.OpenMode.READ\_WRITE | fs.OpenMode.CREATE)
          try {
            let arrayBuffer = new ArrayBuffer(1024)
            let readOptions: ReadOptions = {
              offset: 0,
              length: arrayBuffer.byteLength
            }
            let readLen = await fs.read(file.fd, arrayBuffer, readOptions)
            let buf = buffer.from(arrayBuffer, 0 ,readLen)
          _  // 断言数据_
            console.info(buf.toString())
            expect(buf.toString()).assertEqual('测试数据')
          } catch {
            console.error('something wrong')
          } finally {
            fs.close(file)
          }
          done();
        })
      })
    }