使用Selenium WebDriver / Jest测试时,如何等待函数被调用?

时间:2018-12-05 14:24:37

标签: javascript testing selenium-webdriver extjs jestjs

我有一个使用Ext JS创建的应用程序,并且正在使用Selenium WebDriver(Node package-版本4.0.0-alpha.1)和Jest为其编写测试。在我的一个测试脚本中,我想等待一个函数被调用,然后继续其余的测试逻辑,但是我不确定如何实现此功能。为了帮助演示我要完成的任务,我使用Sencha Fiddle创建了一个示例应用程序。可以在以下位置找到该应用程序的所有代码以及该应用程序的运行版本:https://fiddle.sencha.com/#view/editor&fiddle/2o6m。如果您在小提琴的app文件夹中查看,则会看到其中有一个带有简单控制器的Test组件。控制器中有一个onAdd函数,这是我要继续之前要等待的函数,因为在我的实际应用程序中,该函数中的代码是其余测试所依赖的。我可以通过运行以下代码行在开发工具中访问该功能:Ext.ComponentQuery.query('test')[0] .getController()。onAdd(请注意,需要将activeElement设置为预览iFrame(文档小提琴中的.getElementsByName('fiddle-run-iframe')[0])才能正常工作)。这意味着我可以以相同的方式访问driver.executeScript中的函数,但是一旦有了该函数,就不确定如何继续调用该函数。我试图在Jest中使用模拟/间谍功能,但这无法正常工作,因为在driver.executeScript中未定义jest,因此无法调用jest.fn或jest.spyOn。我创建了一个与示例应用程序一起使用的示例测试脚本,以演示我正在尝试做的事情,但是现在它失败并显示错误,因为正如我说的那样,jest在driver.executeScript中未定义。这是示例测试脚本的代码:

const {Builder, By, Key, until} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');

const driver = global.driver = new Builder()
            .forBrowser('chrome')
            .setChromeOptions(new chrome.Options())
            .build();

jest.setTimeout(10000);

beforeAll(async () => {
    await driver.manage().window().maximize();
    await driver.get('https://fiddle.sencha.com/#view/editor&fiddle/2o6m');
});

afterAll(async () => {
    await driver.quit();
});


describe('check title', () => {
    it('should be SAMPLE STORE LOAD', async () => {
        expect(await driver.wait(until.elementLocated(By.css('.fiddle-title'))).getText()).toBe('SAMPLE STORE LOAD');
    });
});

describe('check store add', () => {
    it('should call add function', async () => {
        let spy;

        await driver.switchTo().frame(await driver.findElement(By.name('fiddle-run-iframe')));
        await driver.wait(until.elementIsNotVisible(await driver.wait(until.elementLocated(By.xpath('//div[starts-with(@id, "loadmask")]')))));
        await driver.executeScript(() => {
            const test = document.getElementsByName('fiddle-run-iframe')[0].contentWindow.Ext.ComponentQuery.query('test')[0];
            spy = jest.spyOn(test.getController(), 'onAdd'); //This throws an error since jest is not defined inside driver.executeScript
        });

        expect(spy).toHaveBeenCalled(); //wait for onAdd function to be called before continuing
    });

    //additional tests occur here after wait...
}); 

您可以忽略与切换到iFrame有关的所有逻辑,因为这对小提琴是唯一必要的,因为它在iFrame中运行应用程序的预览。我的实际应用程序不存在于iFrame中。尽管如此,我认为该脚本有效地演示了我要完成的工作,即要等到onAdd函数被调用之后才能继续测试。我不确定是否需要使用Selenium或Jest,两者的某种组合或完全使用其他测试工具来执行此操作。我是写测试的新手,这是我第一次在Stack Overflow上发帖,所以如果我说的话不清楚,我深表歉意。如果您有任何疑问,我很乐意澄清,并感谢您提供的任何建议!

1 个答案:

答案 0 :(得分:0)

从我的角度来看,在一个测试中结合使用2个不同的框架(测试的方法)可能不是最好的主意。以下是一些有关如何处理类似案件的想法。很少理论:

-在使用浏览器模拟最终用户行为方面表现出色。基本上,它可以模拟动作(单击,文本输入等),并且可以从浏览器窗口获取信息(元素,文本,样式等的存在)

Jest -是一个用于测试Java javascript代码的单元测试框架。

executeScript是Selenium的一种方法,它在浏览器中执行所有javascript代码。浏览器不了解有关jest的任何信息-因此,您可能会遇到所描述的错误。您的项目知道jest,因为它是专门导入到项目中的。

回到问题 “如何在Selenium中检查是否已调用js函数?”

  1. 最典型的解决方案-等待浏览器屏幕上的某些内容发生变化。典型案例:

    • 出现某些元素

    • 一些元素消失了

    • 某些元素的样式已更改

wait for condition in js example

  1. (有点技巧)另一个可能的解决方案是在应用程序的js代码中添加一些标志,该标志在调用函数之前为false,在调用函数后设置为true。然后,您可以在executeScript中访问该标志的值。

some possible implementations here