上一篇讲解了运行环境的搭建和开始写测试用例。接下来讲一下测试用例编写的常用技巧
一. 封装封装封装
你可以将所有的功能操作封装成简单的函数,然后在每个测试用例中调用,复杂操作也可以由简单操作合并而成。这里的好处是显而易见的,一是你的用例很清晰,每一步操作对应一个函数。二是在以后的项目迭代中,会大大简化你的用例维护成本,你只用改对应的操作函数,比如selector,比如操作流程修改等等。
二.puppeteer本身的操作点击无效坑
亲测在打开很多页面后,使用page.click或者page.type有时候无法点击或输入。具体原因不清楚。但是单个用例执行是没有问题的。
所以我们做了一些操作优化
1)点击操作
const click = async function (page, sel, num = 0) {
await page.waitFor(sel)
await page.evaluate((sel, num) => {
document.querySelectorAll(sel)[num].click()
}, sel, num)
};
2)输入操作(最大的坑是如果原有输入框有内容,如何把他替换掉)
const type = async function (page, sel, value, num = 0) {
const edit = async () => {
const elementHandle = (await page.$$(sel))[num]
elementHandle.click({clickCount: 3})
await elementHandle.press('Backspace')
await elementHandle.type(value, {delay: 20})
await page.waitFor(1000)
return await page.evaluate((sel, num) => {
return document.querySelectorAll(sel)[num].value
}, sel, num)
}
let cname_value
await page.waitFor(sel)
let i = 0
do {
cname_value = await edit()
} while (cname_value !== value && i++ < 20)
}
3)上传图片的坑(文件路径一定要全路径,不要相对路径)
uploadImage: async function (page, file_path, index = 0) {
await page.waitFor(500)
const fileUploaders = await page.$$('input[type="file"]')
console.log('fileUploaders=', fileUploaders.length)
await fileUploaders[index].uploadFile(path.resolve(__dirname, '../image/' + file_path))
await page.waitFor(2000)
},
三.页面错误崩溃捕获打印
可以在页面启动时候调用
page.on('pageerror', function (err) {
if (err.message.indexOf('BJ_REPORT is not defined') >= 0
|| err.message.indexOf('template is not defined') >= 0
|| err.message.indexOf('$ is not defined') >= 0
|| err.message.indexOf('request was interrupted by a call to pause') >= 0
|| err.message.indexOf('seajs is not defined')
) {
return
}
throw err
})
page.on('error', err => {
throw err
})
page.on('console', msg => {
for (let i = 0; i < msg.args.length; ++i) {
console.log(`${i}: ${msg.args[i]}`)
}
})
四.mock网络请求数据
有些按需测试某些条件下的用例,或者屏蔽后台请求的就可以mock网络请求。
const mergeMockDataList = {
uniform_inventory: 'uniform_inventory',
get_card_info: 'get_card_info',
convert_cardid: 'convert_cardid',
get_apply_condition: 'get_apply_condition_all'
}
const mockRequest = request => mockCgiData(request, mergeMockDataList)
function mockCgiData (interceptedRequest, mock_data_list) {
const getMockFileName = (url) => {
for (let key in mock_data_list) {
if (url.indexOf(key) >= 0) {
return mock_data_list[key]
}
}
return null
}
const url = interceptedRequest.url()
const mockFile = getMockFileName(url)
if (mockFile) {
const file_path = path.resolve(__dirname, '../mock_data/' + mockFile)
fs.readFile(file_path, 'utf8', function (err, data) {
interceptedRequest.respond({
contentType: 'application/json',
body: data
})
})
} else {
interceptedRequest.continue()
}
}
将上面的mockRequest传递到openNewPage中
const page = await __BROWSER__.openNewPage(mockRequest)