有没有办法根据其他测试的结果来运行特定的量角器测试?
这类问题以前也有人问过,但大多数问题的背景都相当复杂.场景很简单.假设我们正在测试我们最喜欢的 TODO 应用程序.接下来是测试用例:TC00 - '用户应该能够将 TODO 项添加到 TODO 列表'TC01 - '用户应该能够重命名 TODO 项'TC02 - '用户应该能够删除 TODO 项'如果 TC00 失败,我不想运行 TC01 和 TC02(未添加 TODO 项,因此我没有什么可删除或重命名的)
This kind of question has been asked before but most of this question has pretty complicated background. The scenario is simple. Let's say we are testing our favorite TODO app. Test cases are next: TC00 - 'User should be able to add a TODO item to the TODO list' TC01 - 'User should be able to rename TODO item' TC02 - 'User should be able to remove TODO item' I don't want to run the TC01 and TC02 if TC00 fails (the TODO item is not added so I have nothing to remove or rename)
所以过去 3 天我一直在研究这个问题,这个问题最常见的答案是:• 您的测试不应相互依赖• Protractor/Jasmine 没有动态打开/关闭测试的功能('it' 块)我在这里问这个问题的原因是因为它看起来像一个非常普遍的案例并且仍然没有明确的建议来处理这个问题(我的意思是我找不到任何)我的 javascript 技能很差,但我知道我需要玩弄,比如说'通过'完成'或添加 if 和里面的测试......
So I've been researching on this question for the past 3 days and the most common answers fro this question are: • Your tests should not depend on each other • Protractor/Jasmine does not have feature to dynamically turn on/off tests ('it' blocks) There reason why I'm asking this question here is because it looks like a very widespread case and still no clear suggestion to handle this (I mean I could not find any) My javascript skills are poor but I understand that I need to play around, let's say' passing 'done' or adding the if with the test inside...
it('should add a todo' ()=> {
todoInput.sendKeys('test')
addButton.click();
let item = element(by.cssContainingText('.list-item','test')
expect(item.isPresent()).toBe(true)
}
在我的情况下,在将项目添加到列表后有 15 个测试(it"块).如果父"测试失败,我想跳过一些测试.请注意:有一种解决方案可以在失败时跳过所有剩余的测试.这不符合我的需要
In my case there are like 15 tests ('it' blocks) after adding the item to the list. And I want to skip SOME OF THE tests if the 'parent' test failed. PLEASE NOTE: There is a solution out there which allows to skip ALL remaining test if one fails. This does not suit my needs
推荐答案
伙计,我花了好几个星期研究这个,是的,没有明确的答案,直到我意识到量角器的详细工作原理.如果您也了解这一点,您将找到最适合您的选择.
Man, I spent good couple of weeks researching this, and yes there was NO clear answers, until I realized how protractor works in details. If you understand this too you'll figure out the best option for you.
简短的理论之后的解决方案
1) 如果你尝试将异步函数传递给 describe
你会看到它会失败,因为它只接受同步函数
1) If you try to pass async function to describe
you see it'll fail, because it only accepts synchronous function
这对您意味着什么,无论您想传递给它的任何条件,它都不能基于 Promise(Promise == 有时会解决,但不会立即解决).你想要做的基本上是一个承诺(打开页面,做一些事情并等待看看条件是否满足你的标准)
What it means for you, is that whatever condition you want to pass to it block, it can't be Promise based (Promise == resolves somewhen, but not immediately). What you're trying to do essentially IS a Promise (open page, do something and wait to see if the condition satisfies your criteria)
if (conditionIsTrue) { // can't be Promise
it('name', () => {
})
}
这是首先要考虑的...
Thats first thing to consider...
2) 当你运行量角器时,它会获取配置中指定的规范文件并构建 describe/it
和 beforeAll/afterAll
块的队列.重要的细节是它发生在浏览器启动之前.
2) When you run protractor, it picks up spec files specified in config and builds the queue of describe/it
AND beforeAll/afterAll
blocks. IMPORTANT DETAIL HERE IS THAT IT HAPPENS BEFORE THE BROWSER EVEN STARTED.
看看这个例子
let conditionIsTrue; // undefined
it('name', () => {
conditionIsTrue = true;
})
if (conditionIsTrue) { // still undefined
it('name', () => {
})
}
当 Protractor 到达 if()
语句时,conditionIsTrue
的值仍然是 undefined
.当浏览器启动时,它可能会在 it
块内部被覆盖,但在构建队列时不会.所以它跳过它.
By the time Protractor reaches if()
statement, the value of conditionIsTrue
is still undefined
. And it maybe overwritten inside of it
block, when browser starts, later on, but not when it builds the queue. So it skips it.
换句话说,量角器在打开浏览器之前就知道它将运行哪些描述块,并且在执行期间不能修改此队列
In other words, protractor knows which describe blocks it'll run before it even opens the browser, and this queue can NOT be modified during execution
可能的解决方案
1.1 在describe
let conditionIsTrue; // undefined
describe("describe", () => {
it('name1', async () => {
conditionIsTrue = await element.isPresent(); // NOW IT'S TRUE if element is present
})
it('name2', async () => {
if (conditionIsTrue) {
//do whatever you want if the element is present
} else {
console.log("Skipping 'name2' test")
}
})
})
所以你不会跳过 it
块本身,但是你可以跳过 it
So you won't skip the it
block itself, however you can skip anything inside of it
1.2 使用环境变量,可以使用相同的方法跨不同规范跳过 it
块.示例:
1.2 The same approach can be used for skipping it
blocks across different specs, using environment variable. Example:
spec_1.js
describe(`Suite: 1`, () => {
it("element is present", async () => {
if (await element.isPresent()) {
process.env.FLAG = true
} else {
process.env.FLAG = false
}
});
});
spec_2.js
describe(`Suite: 2`, () => {
it("element is present", async () => {
if (process.env.FLAG) {
// do element specific actions
}
});
});
我发现但从未有机会检查的另一种可能性是使用 Grunt 任务运行器,它可以帮助您实现以下场景
Another possibility I found out, but never had a chance to check is to use Grunt task runner, which may help you implement the following scenario
- 运行量角器来执行一个规范
- 检查所需条件
- 将此条件导出到环境变量
- 退出量角器
- 在您的 Grunt 任务中,通过再次启动量角器来实现一个条件逻辑,以执行其余的条件规范
但老实说,我不明白你为什么要走这条耗时的路线,这需要大量代码......但仅供参考
But honestly, I don't see why you'd want to go this time consuming route, which requires a lot of code... But just as an FYI
相关文章