茉莉花:如果异步,循环测试将无法运行

时间:2019-04-10 21:51:48

标签: javascript node.js typescript jasmine protractor

我正在实施一项测试,该测试将从给定目录中读取文件列表。然后对照使用文件名作为键的Map对象检查该列表。如果找到匹配项,我想执行一些测试,否则请跳过该文件并继续进行下一个测试。

如果我只是从Map中抓取一个对象,则可以进行测试,但是当我尝试循环时它会失败。我想通过循环多个文件来运行测试。

如果我在测试中有异步调用,这似乎只是一个问题。使用完全同步的循环,我可以使其运行正常。这是一个同步循环的示例(我意识到这是一个非常人为的示例,但是可以按预期工作)

describe('a test', () => {
  const list = ['a', 'b', 'c'];

  const test = (x) => {
    describe(`should run ${x}`, () => {
        beforeAll(async () => {
            console.log('beforeAll');
        });

        beforeEach(async () => {
            console.log('beforeEach');
        });

        for(let i = 0; i < 2; i++) {
          it(`should log iteration ${i}`, async () => {
            console.log(x, i);

            expect(i).toBeTruthy();
          });
        }
    });
  }

  for (let i = 0; i < list.length; i++) {
    test(list[i]);
  }
});

以上代码段的输出表明它运行得很好: enter image description here

如果异步,则相同的模式不起作用。实际上,据我所知,test中的嵌套描述甚至没有运行。我将project变量记录到控制台,以便可以看到它已被调用,但是logging in...中的beforeAll语句根本没有执行。似乎只是跳过它。我如何使用async/await来完成这项工作?

describe('Import Project', () => {
  const _page = new PageFactory();
  const utils = new Utils();
  const projPath = browser.params.projPath;

  let projectGuid: string;

  const test = (project) => {
    describe(`importing ${project.name}`, () => {
        beforeAll(async () => {
            console.log('logging in...'); //not getting executed for some reason
            await _page.loginPage.login(browser.params.username, browser.params.password);

            // import
            await _page.projectsPage.importProject(projectPath + project.filename)
                .withImportType(project.importType)
                .withProjectName(project.projectName)
                .inEnvironment(project.environment)
                .import();

            projectGuid = await utils.extractGuid();
        });

        afterEach(async () => {
            await _page.designerPage.navigateTo(projectGuid);
        });

        for(let i = 0; i < project.operations.length; i++) {
            const operation = project.operations[i];

            it(`should run ${operation.name} successfully`, async () => {
                await runOperation(operation.name);

                const status = await _page.operationLogsPage.getStatus(operation.outcomeTarget);
                expect(status).toEqual(operation.expectedStatus);
            });
        }
    });
  }

  utils.getProjects().then(projects => {
    // projects is a string[] of filenames
    // that are returned using fs.readdir()
    for (let i = 0; i < projects.length; i++) {
        const myProject = projectMap.get(projects[i]);

        if (myProject) {
            test(myProject);
        }
    }
  });
});

此输出仅为Executed 0 of 0 specs SUCCESS in 0.003 sec.

我不明白这与手动写出所有这些嵌套的描述块有什么不同。如果我把每一个都写出来,那会很好,但是由于某种原因,它不想循环。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我不知道如何使它按我想要的方式工作。相反,我决定使用节点的child_process.execSync并以此方式遍历每个文件。这不是理想的方法,但是可行。由于我要在其上运行测试的每个文件都创建了一个新会话,因此花费了更长的时间,但是我厌倦了尝试以其他方式使其工作。

我正在使用node ./path/to/test.js --baseUrl=http://<myUrl>

运行脚本

这是代码的相关部分:

fs.readdir(projectsPath, (err, files) => {
  if (err) {
    throw new Error('Unable to scan directory: ' + err);
  }

  let i = 0;

  const next = () => {
    if (i < files.length) {
        const file = files[i];
        console.log('running tests on:', file);            

        const runCmd = `nodenv --exec "yarn run e2e:all ${baseUrl} --params.projectToImport=${file} --suite import_projects"`            

        // exec
        try {
            execSync(runCmd, { cwd: workingDir, stdio: 'inherit' },
                (error, stdout, stderr) => {
                    if (error) {
                        console.error(error);
                        return;
                    }

                    console.log(stdout);
                });
        } catch (err) {
            if (err.stderr) {
                console.log('stderr:', err.stderr.toString());
            }
        }

        // next iteration
        i++;
        next();
      }
  }

  next();
});