OpenHarmony UiTest測試用例開發(fā)實踐
前言
這篇文章主要對UiTest測試用例的開發(fā)做一個簡單的開發(fā)實踐。
概述
UiTest提供模擬UI操作的能力,供開發(fā)者在測試場景使用,主要支持如點擊、雙擊、長按、滑動等UI操作能力。
UiTest主要包含以下幾個關(guān)鍵、常用的類:
- On:提供控件特征描述能力,用于控件篩選匹配查找。
- Component:代表UI界面上的指定控件,提供控件屬性獲取,控件點擊,滑動查找,文本注入等能力。
- Driver:入口類,提供控件匹配/查找,按鍵注入,坐標(biāo)點擊/滑動,截圖等能力。
- UiWindow:入口類,提供窗口屬性獲取,窗口拖動、調(diào)整窗口大小等能力。
開發(fā)步驟
打開應(yīng)用
了解OpenHarmony應(yīng)用工程結(jié)構(gòu)的同學(xué)應(yīng)該知道,每個模塊最終都會編譯成一個hap,例如我們最熟悉的entry模塊,而ohosTest模塊最終也會編譯成一個hap,并安裝在桌面上。
讀過上篇文章或者了解OpenHarmony應(yīng)用開發(fā)的同學(xué)也知道,這個hap默認(rèn)打開的是TestAbility中指定的頁面,而開發(fā)者如果想測試的是其他hap(例如筆者這里測試的是entry模塊編譯的hap),首先需要使用startAbility的方式進(jìn)行拉起。
it(BUNDLE + 'StartAbility_001', 0, async function (done) {
console.info(TAG, BUNDLE + 'StartAbility_001 begin')
try {
await abilityDelegator.startAbility({
bundleName: 'com.example.myapplication',
abilityName: 'EntryAbility'
})
done()
} catch (exception) {
console.info(TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`)
expect().assertFail()
}
console.info(TAG, BUNDLE + 'StartAbility_001 end')
})
創(chuàng)建Driver對象
Driver類作為UiTest測試框架的總?cè)肟?,在使用控件匹?查找,按鍵注入,坐標(biāo)點擊/滑動,截圖等能力之前,需要使用Driver.create()方法創(chuàng)建一個Driver對象。
let driver = Driver.create()
控件匹配、操作
On類提供了豐富的控件特征描述,可以指定某個控件的id、類型、文本內(nèi)容等條件進(jìn)行匹配,例如筆者這里分別給TextInput和Button組件設(shè)置了id,然后就可以使用ON.id()進(jìn)行條件匹配。
也可以同時指定目標(biāo)控制的id和type,例如:
ON.id('button').type('Button')
在查找目標(biāo)控件之前,可以使用斷言API斷言當(dāng)前界面是否存在滿足給出的目標(biāo)屬性的控件,如不滿足則會報錯退出。
await driver.assertComponentExist(ON.id('textInput'))
在使用On類指定條件后,可以使用driver.findComponent()方法進(jìn)行控件匹配,匹配成功后返回符合條件的Component對象,然后就可以使用Component類提供的方法進(jìn)行點擊、滑動、注入文本等操作。
let textInput = await driver.findComponent(ON.id('textInput'))
await textInput.inputText('OpenHarmony');
運(yùn)行效果
完整代碼
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'
import { Driver, ON } from '@ohos.UiTest'
const TAG = '[Sample_MyApplication]'
const BUNDLE = 'myApplication_'
const DELAY_TIME = 1000;
export default function abilityTest() {
let driver = Driver.create()
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
describe('ActsAbilityTest', function () {
/**
* 打開應(yīng)用
*/
it(BUNDLE + 'StartAbility_001', 0, async function (done) {
console.info(TAG, BUNDLE + 'StartAbility_001 begin')
try {
await abilityDelegator.startAbility({
bundleName: 'com.example.myapplication',
abilityName: 'EntryAbility'
})
done()
} catch (exception) {
console.info(TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`)
expect().assertFail()
}
console.info(TAG, BUNDLE + 'StartAbility_001 end')
})
it(BUNDLE + 'function_001', 0, async function () {
console.info(TAG, BUNDLE + 'function_001 begin')
await driver.delayMs(DELAY_TIME)
// 向文本框控件中輸入文本
await driver.assertComponentExist(ON.id('textInput'))
let textInput = await driver.findComponent(ON.id('textInput'))
await textInput.inputText('OpenHarmony');
await driver.delayMs(DELAY_TIME)
// 點擊按鈕
await driver.assertComponentExist(ON.id('button'))
let btn = await driver.findComponent(ON.id('button'))
await btn.click();
await driver.delayMs(DELAY_TIME)
// 清空文本框控件的文本信息
await textInput.clearText();
console.info(TAG, BUNDLE + 'function_001 end')
})
})
}
常見問題
1、失敗日志有“execute timeout 15000ms”錯誤信息
問題分析
默認(rèn)測試執(zhí)行時長為15000ms,當(dāng)測試用例執(zhí)行超時就會自動退出并報該錯誤。
解決方法
在如下位置修改執(zhí)行超時時長。
2、失敗日志有“uitest-api dose not allow calling concurrently”錯誤信息
問題分析
可能為報錯位置前面調(diào)用的異步接口沒有使用await調(diào)用,或者并行執(zhí)行多個測試用例,導(dǎo)致前面的API沒有執(zhí)行完,就調(diào)用了新的API。
解決方法
1.檢查用例實現(xiàn),異步接口增加await調(diào)用。
2.避免多進(jìn)程執(zhí)行UI的測試用例。
結(jié)語
本文只是對UiTest接口做一個簡單的實踐,旨在讓開發(fā)者了解UiTest測試用例的開發(fā)流程以及部分接口介紹。UiTest除此之外還提供更加強(qiáng)大、更加復(fù)雜的能力,大家可以自行探索。