You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Protractor中exceljs readFile与it-expect组合使用问题求助

问题分析与解决方案

你的问题核心出在两个点上:异步操作没有正确告知Protractor等待,以及试图在测试运行时动态创建it()测试块(Jasmine不支持这种写法)。我们一步步来解决:

1. 为什么你的代码会报错?

  • 第一个错误:你在it()里调用了wb.xlsx.readFile(),但没有把这个Promise返回给Protractor。Protractor会认为这个it()已经执行完成,而后续的expect()是在测试上下文之外运行的,所以会抛出"expect was used when there was no current spec"。
  • 第二个问题:你尝试在循环里动态创建it()块,Jasmine的测试套件是静态解析的,运行时动态添加的it()不会被识别执行,所以即使你取消注释那些it(),它们也不会跑起来。

2. 正确的解决方案

步骤一:提前加载Excel数据

我们需要在所有测试运行前就加载好Excel数据,用beforeAll结合async/await(exceljs的方法都返回Promise,用async/await比then链更清晰),确保Protractor等待数据加载完成后再执行测试。

步骤二:基于Excel数据生成静态测试用例

在describe块内部,遍历加载好的Excel数据,提前创建对应的it()测试块——Jasmine会在运行前扫描所有it(),这样每个测试用例都会被正确识别。

修改后的完整代码

import { AppPage } from './app.po';
import { browser, logging, element, by } from 'protractor'
import { Workbook, Row, Cell, Worksheet } from 'exceljs';

// 先初始化日志配置(可以放在这里,避免在describe里重复初始化)
const log4js = require('log4js');
log4js.configure({
  appenders: { igwan: { type: 'file', filename: 'cheese.log' } },
  categories: { default: { appenders: ['igwan'], level: 'error' } }
});
const logger = log4js.getLogger('IGWAN');
logger.level = 'trace';

describe('E2E Tests', () => {
  let page = new AppPage();
  let dataContainer: any[] = []; // 存储Excel加载的数据

  // 在所有测试前加载Excel数据
  beforeAll(async () => {
    const wb: Workbook = new Workbook();
    // 等待Excel文件读取完成
    await wb.xlsx.readFile('e2e/src/testsE2E.xlsx');
    const sheet: Worksheet = wb.getWorksheet("Eqpt");
    
    // 解析Excel数据到dataContainer
    for (let l = 1; l <= sheet.rowCount; l++) {
      const rowObject = sheet.getRow(l);
      const rowData: string[] = [];
      for (let m = 1; m <= sheet.columnCount; m++) {
        const cellObject = rowObject.getCell(m);
        rowData.push(cellObject.toString());
      }
      dataContainer.push(rowData);
    }
    console.log("Excel数据加载完成:", dataContainer);
    console.log("hello2"); // 现在这个日志会正常输出了
  });

  // 设置全局隐式等待并打开页面
  beforeAll(() => {
    browser.manage().timeouts().implicitlyWait(30000);
    page.navigateToPark();
  });

  // 遍历Excel数据,生成对应的测试用例
  dataContainer.forEach((row, rowIndex) => {
    // 跳过标记为"1"以外的行
    if (row[0].toString() !== "1") {
      console.log(`第${rowIndex+1}行被作者标记为跳过`);
      return;
    }

    const deviceName = row[1];
    // 为每个设备创建一个测试块,包含所有字段验证
    it(`应该正确显示设备${deviceName}的所有信息`, async () => {
      // 输入设备名并搜索
      await element(by.id('device_input')).clear();
      await element(by.id('device_input')).sendKeys(deviceName);
      await element(by.id('search_button')).click();

      // 验证各个字段
      await expect(element(by.id('type')).getText()).toEqual(row[2]);
      await expect(element(by.id('pop')).getText()).toEqual(row[3]);
      await expect(element(by.id('ipMngt')).getText()).toEqual(row[4]);
      await expect(element(by.id('internalState')).getText()).toEqual(row[5]);
      await expect(element(by.id('prodState')).getText()).toEqual(row[6]);
      await expect(element(by.id('currentSwRelease')).getText()).toEqual(row[7]);
      await expect(element(by.id('hwChassis')).getText()).toEqual(row[8]);
      await expect(element(by.id('rfsNode')).getText()).toEqual(row[9]);
      await expect(element(by.id('peId')).getText()).toEqual(row[10]);
    });
  });

  afterEach(async () => {
    // 检查浏览器日志
    const logs = await browser.manage().logs().get(logging.Type.BROWSER);
    expect(logs).not.toContain(jasmine.objectContaining({
      level: logging.Level.SEVERE,
    } as logging.Entry));
  });
});

关键改进点说明

  • 用beforeAll+async/await加载Excel:确保Protractor等待数据加载完成后再执行测试,避免异步操作导致的上下文丢失。
  • 静态生成it()测试块:在describe内部遍历Excel数据,提前创建所有测试用例,Jasmine会正确识别并执行它们。
  • 简化异步操作:用await替代then链,代码更易读,也确保Protractor等待每个操作完成。
  • 统一页面初始化:把navigateToPark()放在beforeAll里,避免重复执行。

这样修改后,你的Excel读取会正常执行("hello2"会输出),每个设备的验证也会作为独立的测试用例运行,不会再出现expect上下文错误。

内容的提问来源于stack exchange,提问作者C DV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:15:52