解毒剂 帮助工具 密码JS
在iOS和Android上测试移动应用程序可以看起来像这样:
I.setLandscapeOrientation();
I.fillField('#text', 'a new text');
I.see('a new text', '#textValue');
I.dontSeeElement('#createdAndVisibleText');
I.click({ ios: '#GoButton', android: 'Button' });
I.waitForElement('#createdAndVisibleText', 20);
I.seeElement('#createdAndVisibleText');
I.runOnAndroid(() => {
I.click('Save');
I.see('Text Saved', '#message');
});
I.runOnIOS(() => {
I.click('SAVE');
I.see('SAVED!');
});
示例输出 :
creating output directory: /Users/runner/work/detox-helper/detox-helper/test/output
***************************************
nodeInfo: 20.14.0
osInfo: macOS 14.5
cpuInfo: (3) arm64 Apple M1 (Virtual)
chromeInfo: 125.0.6422.142
edgeInfo: Not Found
firefoxInfo: undefined
safariInfo: 17.5
If you need more detailed info, just run this: npx codeceptjs info
***************************************
CodeceptJS v3.6.3 #StandWithUkraine
Using test root "/Users/runner/work/detox-helper/detox-helper/test"
Helpers: Detox, ExpectHelper
Plugins: screenshotOnFail
Acceptance Tests --
[1] Starting recording promises
Timeouts:
11:44:06.770 detox[8813] i App started
11:44:28.445 detox[8813] i com.wix.demo.react.native launched. To watch simulator logs, run:
/usr/bin/xcrun simctl spawn F44382C2-F0BE-466A-9683-AA6B37591FBA log stream --level debug --style compact --predicate 'process == "example"'
11:44:28.557 detox[8813] i --- STARTED "before each" hook: Before for "App started" ---
11:44:28.583 detox[8813] i I launch app
11:44:30.037 detox[8813] i com.wix.demo.react.native launched. To watch simulator logs, run:
/usr/bin/xcrun simctl spawn F44382C2-F0BE-466A-9683-AA6B37591FBA log stream --level debug --style compact --predicate 'process == "example"'
11:44:30.043 detox[8813] i I wait for element visible "#hello_button", 15
11:44:31.253 detox[8813] i --- ENDED "before each" hook: Before for "App started" ---
11:44:31.273 detox[8813] i I see "Welcome"
11:44:31.289 detox[8813] i ✔ OK in 25ms
11:44:31.289 detox[8813] i
11:44:31.301 detox[8813] i Get platform
11:44:34.736 detox[8813] i com.wix.demo.react.native launched. To watch simulator logs, run:
/usr/bin/xcrun simctl spawn F44382C2-F0BE-466A-9683-AA6B37591FBA log stream --level debug --style compact --predicate 'process == "example"'
11:44:40.582 detox[8813] i --- STARTED "before each" hook: Before for "Get platform" ---
11:44:40.588 detox[8813] i I launch app
11:44:42.271 detox[8813] i com.wix.demo.react.native launched. To watch simulator logs, run:
/usr/bin/xcrun simctl spawn F44382C2-F0BE-466A-9683-AA6B37591FBA log stream --level debug --style compact --predicate 'process == "example"'
11:44:42.274 detox[8813] i I wait for element visible "#hello_button", 15
11:44:43.126 detox[8813] i --- ENDED "before each" hook: Before for "Get platform" ---
11:44:43.150 detox[8813] i I grab platform
11:44:43.152 detox[8813] i I expect ""ios"" to equal ""ios""
11:44:43.158 detox[8813] i ✔ OK in 31ms
11:44:43.158 detox[8813] i
11:44:43.166 detox[8813] i Show hello screen after tap
11:44:46.251 detox[8813] i com.wix.demo.react.native launched. To watch simulator logs, run:
/usr/bin/xcrun simctl spawn F44382C2-F0BE-466A-9683-AA6B37591FBA log stream --level debug --style compact --predicate 'process == "example"'
11:44:52.308 detox[8813] i --- STARTED "before each" hook: Before for "Show hello screen after tap" ---
11:44:52.321 detox[8813] i I launch app
11:47:22.243 detox[8813] i com.wix.demo.react.native launched. To watch simulator logs, run:
/usr/bin/xcrun simctl spawn F44382C2-F0BE-466A-9683-AA6B37591FBA log stream --level debug --style compact --predicate 'process == "example"'
11:47:22.319 detox[8813] i I wait for element visible "#hello_button", 15
11:47:23.637 detox[8813] i --- ENDED "before each" hook: Before for "Show hello screen after tap" ---
11:47:23.668 detox[8813] i I dont see "Hello!!!"
11:47:23.699 detox[8813] i I click "#hello_button"
11:47:24.308 detox[8813] i I see "Hello!!!"
11:47:24.323 detox[8813] i ✔ OK in 684ms
11:47:24.323 detox[8813] i
11:47:24.334 detox[8813] i Show world screen after tap
11:47:27.298 detox[8813] i com.wix.demo.react.native launched. To watch simulator logs, run:
/usr/bin/xcrun simctl spawn F44382C2-F0BE-466A-9683-AA6B37591FBA log stream --level debug --style compact --predicate 'process == "example"'
11:47:33.604 detox[8813] i --- STARTED "before each" hook: Before for "Show world screen after tap" ---
11:47:33.608 detox[8813] i I launch app
11:47:36.074 detox[8813] i com.wix.demo.react.native launched. To watch simulator logs, run:
/usr/bin/xcrun simctl spawn F44382C2-F0BE-466A-9683-AA6B37591FBA log stream --level debug --style compact --predicate 'process == "example"'
11:47:36.110 detox[8813] i I wait for element visible "#hello_button", 15
11:47:36.450 detox[8813] i --- ENDED "before each" hook: Before for "Show world screen after tap" ---
11:47:36.452 detox[8813] i I click "#world_button"
11:47:37.314 detox[8813] i I see "World!!!"
11:47:37.408 detox[8813] i ✔ OK in 935ms
11:47:37.409 detox[8813] i
11:47:37.468 detox[8813] i
11:47:37.470 detox[8813] i OK | 4 passed // 7m
CodeceptJS 提供了标准Detox的下个特征:
- 统一 API。同样的测试可以在 Appium 或 Detox 中执行。 统一API帮助不同的团队使用相同的语法和从一个引擎到另一个引擎的轻松端口测试.
- 交互暂停。当开始/停止应用程序需要很长时间时,调试和写作测试可能很困难. CodeceptJS通过延缓处决并让你尝试不同的命令和定位器来解决了这个问题. 使用此特性, 在一个运行的会话中可以进行拼写测试 .
- 一次Android和IOS测试当Android和IOS的应用程序不同时,您可以为这两个系统提供相应的系统定位器。 当需要时,Android和IOS可以执行不同的代码,将其保存在同一测试中.
API 密码
目录
- 解毒剂
解毒剂
扩展帮助
上面是包装纸 解毒剂 库,旨在统一 CodeceptJS 框架的测试经验. Detox为移动应用程序提供灰盒测试,对React Industrial Apps特别好.
德多克斯的演奏与Appium相当不同. 要建立解毒测试,您需要以特殊的方式构建移动应用程序来注入解毒码. 为什么 解毒是灰盒测试 解决方案,所以您需要访问应用程序源代码,以及构建和执行模拟器的方法.
与Appium相比,Detox运行速度快,稳定性更强,但需要额外的建设设置.
设置
需要在 package.json 下级 detox 节.
如果你完成了第1步和第2步,你应该有一个类似的配置:
"detox": {
"configurations": {
"ios.sim.debug": {
"device": "simulator",
"app": "ios.debug"
}
},
"apps": {
"ios.debug": {
"type": "ios.app",
"binaryPath": "../test/ios/build/Build/Products/Debug-iphonesimulator/MyTestApp.app",
"build": "xcodebuild -workspace ../test/ios/MyTestApp.xcworkspace -scheme MyTestApp -configuration Debug -sdk iphonesimulator -derivedDataPath ../test/ios/build"
}
},
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 15"
}
}
}
}
配置
除了Detox配置外,CodeceptJS也应该被配置到使用Detox.
单位 codecept.conf.js 启用 Detox 帮助 :
helpers: {
Detox: {
require: '@codeceptjs/detox-helper',
configuration: '<detox-configuration-name>',
}
}
必须指定一个软件包名称 require 区域及当前解毒配置 package.json。 。 。 .
选项 :
configuration- 一个解毒配置名称。 要求.reloadReactNative- 应启用反应原生应用程序.reuse- 用于测试的再利用申请。 默认情况下,Detox重新安装并重新启动了app.registerGlobals- (默认: 真实) 注册 Detox 帮助函数by, (中文(简体) ),element, (中文(简体) ),expect, (中文(简体) ),waitFor在全球.url- URL通过深链接打开,每次应用程序启动(android)或紧接之后(iOS). 在与博览会合作的测试开始时打开捆绑的 URL 有用 .
参数
config
保存脚本
将截图保存到输出目录
I.saveScreenshot('main-window.png');
参数
name字符串
重新启动App
重新启动应用程序.
I.relaunchApp();
启动 App
启动一个应用程序。 如果应用程序实例已经存在, 请使用 重新启动App。 。 。 .
I.launchApp();
安装 App
安装已配置的应用程序. 应用程序默认安装.
I.installApp();
摇动Device
摇动装置.
I.shakeDevice();
回头
回到了Android上 继续
I.goBack(); // on Android only
设置
切换设备到地貌方向
I.setLandscapeOrientation();
图像
切换设备到肖像方向
I.setPortraitOrientation();
抓取公式
抓取设备平台
const platform = await I.grabPlatform();
运行OnIOS
只执行 iOS 上的代码
I.runOnIOS(() => {
I.click('Button');
I.see('Hi, IOS');
});
参数
fn函数 一个将在 iOS 上执行的函数
运行Android
只在Android上执行代码
I.runOnAndroid(() => {
I.click('Button');
I.see('Hi, Android');
});
参数
fn函数 一个将在 android 上执行的函数
窃听
拍到一个元素. 元素可以通过它的文本或id或可访问的id来定位.
第二个参数是缩小搜索的上下文元素.
与 单击
I.tap('Login'); // locate by text
I.tap('~nav-1'); // locate by accessibility label
I.tap('#user'); // locate by id
I.tap('Login', '#nav'); // locate by text inside #nav
I.tap({ ios: 'Save', android: 'SAVE' }, '#main'); // different texts on iOS and Android
参数
locator密码JS.Locator OrStringcontext(CodeceptJS.Locator OrString = 无效) (可选,默认)null(中文(简体) )
多标签
在一个元素上多下水. 元素可以通过它的文本或id或可访问的id来定位.
在第二个参数中设置水龙头的数量 . 可选用第三个参数定义上下文要素.
I.multiTap('Login', 2); // locate by text
I.multiTap('~nav', 2); // locate by accessibility label
I.multiTap('#user', 2); // locate by id
I.multiTap('Update', 2, '#menu'); // locate by id
参数
locator密码JS.Locator OrString 要定位的元素num编号 水龙头数context(CodeceptJS.Locator OrString = 无效) 上下文元素( 可选, 默认)null(中文(简体) )
长发压
磁带元素并保存到请求的时间 .
I.longPress('Login', 2); // locate by text, hold for 2 seconds
I.longPress('~nav', 1); // locate by accessibility label, hold for second
I.longPress('Update', 2, '#menu'); // locate by text inside #menu, hold for 2 seconds
参数
locator密码JS.Locator OrString 要定位的元素sec编号 抓取水龙头的秒数context(CodeceptJS.Locator OrString = 无效) 上下文元素( 可选, 默认)null(中文(简体) )
单击
点击元素. 元素可以通过其文本或id或可访问性id找到
第二个参数是上下文(id QQ type QQ可访问性 id)来缩小搜索范围.
与 窃听
I.click('Login'); // locate by text
I.click('~nav-1'); // locate by accessibility label
I.click('#user'); // locate by id
I.click('Login', '#nav'); // locate by text inside #nav
I.click({ ios: 'Save', android: 'SAVE' }, '#main'); // different texts on iOS and Android
参数
locator密码JS.Locator OrStringcontext(CodeceptJS.Locator OrString = 无效) (可选,默认)null(中文(简体) )
音标
点击元素. 元素可以通过它的标签找到
第二个参数是上下文(id QQ type QQ可访问性 id)来缩小搜索范围.
I.tapByLabel('Login'); // locate by text
I.tapByLabel('Login', '#nav'); // locate by text inside #nav
参数
locator密码JS.Locator OrStringcontext(CodeceptJS.Locator OrString = 无效) (可选,默认)null(中文(简体) )
点击点
以水平和垂直偏移单击元素. 一个元素通过文本,id,可访问性id找到.
I.clickAtPoint('Save', 10, 10);
I.clickAtPoint('~save', 10, 10); // locate by accessibility id
参数
见
选中要可见的文本 . 使用第二个参数缩小搜索范围 .
I.see('Record created');
I.see('Record updated', '#message');
I.see('Record deleted', '~message');
参数
text字符串 检查可见度context(CodeceptJS.Locator OrString = 无效) 查找文本的元素(可选,默认)null(中文(简体) )
看不见
选中要显示的文本 . 使用第二个参数缩小搜索范围 .
I.dontSee('Record created');
I.dontSee('Record updated', '#message');
I.dontSee('Record deleted', '~message');
参数
text字符串 检查隐形context(CodeceptJS.Locator OrString = 无效) 查找文本的元素(可选,默认)null(中文(简体) )
可见元素
检查元素的能见度 . 使用第二个参数缩小搜索范围 .
I.seeElement('~edit'); // located by accessibility id
I.seeElement('~edit', '#menu'); // element inside #menu
参数
locator密码JS.Locator OrString 要定位的元素context(CodeceptJS.Locator OrString = 无效) 上下文元素( 可选, 默认)null(中文(简体) )
检查是否元素元素
检查元素是否存在 .
I.checkIfElementExists('~edit'); // located by accessibility id
I.checkIfElementExists('~edit', '#menu'); // element inside #menu
参数
locator密码JS.Locator OrString 要定位的元素context(CodeceptJS.Locator OrString = 无效) 上下文元素( 可选, 默认)null(中文(简体) )
不见元素
检查该元素不可见 . 使用第二个参数缩小搜索范围 .
I.dontSeeElement('~edit'); // located by accessibility id
I.dontSeeElement('~edit', '#menu'); // element inside #menu
参数
locator密码JS.Locator OrString 要定位的元素context(CodeceptJS.Locator OrString = 无效) 上下文元素( 可选, 默认)null(中文(简体) )
见元素
检查元素是否存在 。 一个元素可以可见或不可见. 使用第二个参数缩小搜索范围 .
I.seeElementExists('~edit'); // located by accessibility id
I.seeElementExists('~edit', '#menu'); // element inside #menu
参数
locator密码JS.Locator OrString 要定位的元素context密码JS.Locator OrString 上下文元素( 可选, 默认)null(中文(简体) )
不见元素
检查该元素不存在. 使用第二个参数缩小搜索范围 .
I.dontSeeElementExist('~edit'); // located by accessibility id
I.dontSeeElementExist('~edit', '#menu'); // element inside #menu
参数
locator密码JS.Locator OrString 要定位的元素context密码JS.Locator OrString 上下文元素( 可选, 默认)null(中文(简体) )
填写字段
在应用程序中填入文本字段. 一个字段可以通过文本,可访问性id,id找到.
I.fillField('Username', 'davert');
I.fillField('~name', 'davert');
I.fillField({ android: 'NAME', ios: 'name' }, 'davert');
参数
field密码JS.Locator OrString 要填入的输入元素value字符串 要填充的值
抓取返回键
磁带返回键. 一个字段可以通过文本,可访问性id,id找到.
I.tapReturnKey('Username');
I.tapReturnKey('~name');
I.tapReturnKey({ android: 'NAME', ios: 'name' });
参数
field密码JS.Locator OrString 要填入的输入元素
清除字段
清除文本字段. 一个字段可以通过文本,可访问性id,id找到.
I.clearField('~name');
参数
field密码JS.Locator OrString 要清除的输入元素
附录字段
将文本插入字段. 一个字段可以通过文本,可访问性id,id找到.
I.appendField('name', 'davert');
参数
field密码JS.Locator OrStringvalue字符串
滚动
向元素顶部滚动.
I.scrollUp('#container');
参数
locator密码JS.Locator OrString
向下滚动
向元素底部滚动.
I.scrollDown('#container');
参数
locator密码JS.Locator OrString
卷轴
在元素左边滚动.
I.scrollLeft('#container');
参数
locator密码JS.Locator OrString
向右滚动
向元素右边滚动 .
I.scrollRight('#container');
参数
locator密码JS.Locator OrString
刷新
在一个元素内部进行刷新.
可能会 slow 或者说 fast 刷取来.
I.swipeUp('#container');
参数
locator密码JS.Locator OrString 用于进行擦拭的元素speed字符串 执行速度 :slow或者说fast. (可选,默认)'slow'(中文(简体) )
刷新下方
在一个元素内部进行刷新.
可能会 slow 或者说 fast 刷取来.
I.swipeUp('#container');
参数
locator密码JS.Locator OrString 用于进行擦拭的元素speed字符串 执行速度 :slow或者说fast. (可选,默认)'slow'(中文(简体) )
刷新左边
在一个元素内部进行刷新.
可能会 slow 或者说 fast 刷取来.
I.swipeUp('#container');
参数
locator密码JS.Locator OrString 用于进行擦拭的元素speed字符串 执行速度 :slow或者说fast. (可选,默认)'slow'(中文(简体) )
刷对
在一个元素内部进行刷新.
可能会 slow 或者说 fast 刷取来.
I.swipeUp('#container');
参数
locator密码JS.Locator OrString 用于进行擦拭的元素speed字符串 执行速度 :slow或者说fast. (可选,默认)'slow'(中文(简体) )
单单
等待数秒
I.wait(2); // waits for 2 seconds
参数
sec编号 等待的秒数
等待备忘
等待页面中存在元素 .
I.waitForElement('#message', 1); // wait for 1 second
参数
locator密码JS.Locator OrString 一个等待的元素sec编号 要等待的秒数, 默认为 5( 可选, 默认)5(中文(简体) )
等待可视化
等待元素在页面上可见 .
I.waitForElementVisible('#message', 1); // wait for 1 second
参数
locator密码JS.Locator OrString 一个等待的元素sec编号 要等待的秒数( 可选, 默认)5(中文(简体) )
等待隐藏
等待精灵变得看不见.
I.waitToHide('#message', 2); // wait for 2 seconds
参数
locator密码JS.Locator OrString 一个等待的元素sec编号 要等待的秒数( 可选, 默认)5(中文(简体) )
滚动到元素
在可滚动容器内滚动到元素.