JavaScript / Jest:如何仅在测试失败时显示测试用例的日志?

Pau*_*aul 6 javascript logging winston jestjs

我正在使用 selenium 开发端到端测试套件,其中测试用例是使用 jest 测试运行程序用 JavaScript 编写的。

我的问题是,当某些东西无法正常工作时,硒通常会毫不客气地失败,而对其失败的原因几乎没有解释。不用说,像这样调试测试可能非常困难。

我正在寻找一种方法来登录每个测试用例,所以我知道测试失败的地方,但是如果测试实际失败,只在测试输出中显示这些日志(为了不污染测试的控制台输出,有很多不必要的日志)。

所以我想做一些类似的事情:

describe(() => {
    it('case 1', async () => {
        // this log should only be printed on the console if this test fails
        logger.info('message from case 1');
        // ...
    });

    it('case 2', () => {
        logger.info('message from case 2');
        // ...
    });
});
Run Code Online (Sandbox Code Playgroud)

因此,如果测试case 1失败并且case 2没有失败,我会message from case 1在控制台输出中看到(理想情况下就在该测试用例的错误之前)而不是 message from case 2.

这可能是开玩笑的吗?我可以为此自由使用任何日志库。

cas*_*der 9

我遇到了同样的问题,找不到明确的解决方案。Facebook 的待办事项列表似乎很少,所以这里有一个解决方法。它使用了我在这里这里找到的代码片段。这个想法是在每次玩笑运行之前,您设置一个消息存储并全局覆盖控制台以将所有日志记录转移到该处。每次测试后,检查该测试是否失败,如果失败,则打印出隐藏的消息。

包.json :

"jest": {
    ...
    "verbose": true,
    "setupFilesAfterEnv": ["<rootDir>/test/setup.js"],
    ...
  }
Run Code Online (Sandbox Code Playgroud)

设置.js

"jest": {
    ...
    "verbose": true,
    "setupFilesAfterEnv": ["<rootDir>/test/setup.js"],
    ...
  }
Run Code Online (Sandbox Code Playgroud)

如果您需要进行任何其他清理,您可以像这样在测试文件中“扩展” afterEach :

some.test.js

const util = require('util')

global.consoleMessages = []

// get information about the current test
jasmine.getEnv().addReporter({
    specStarted: result => jasmine.currentTest = result,
    specDone: result => jasmine.currentTest = result,
})

function squirrelAway(text, logger) {
    // use error to get stack trace
    try {
        throw new Error('stacktrace')
    } catch (err) {
        let trace = err.stack.split('\n')
        trace.shift()   // removes Error: stacktrace
        trace.shift()   // removes squirrelAway() call from the "throw" command
        trace.shift()   // removes console logger call in the console override
        consoleMessages.push({logger: logger, payload: text, stacktrace: trace.join('\n')})
    }
}

const orig = console
global.console = {...console,
    // use jest.fn() to silence, comment out to leave as it is
    log: (text => squirrelAway(text, orig.log)),
    error: (text => squirrelAway(text, orig.error)),
    warn: (text => squirrelAway(text, orig.warn)),
    info: (text => squirrelAway(text, orig.info)),
    debug: (text => squirrelAway(text, orig.debug))
}

global.afterEach(() => {
    // this includes tests that got aborted, ran into errors etc.
    let failed = (jasmine && jasmine.currentTest
                  && Array.isArray(jasmine.currentTest.failedExpectations)) ?
                 jasmine.currentTest.failedExpectations.length>0 : true
    //orig.log(`test "${jasmine.currentTest.fullName}" finished. failed? ${failed}`)
    if (failed) {
        //orig.log(`Logging for "${jasmine.currentTest.fullName}" start`)
        consoleMessages.forEach(msg => {
            if (typeof msg.payload === 'object' || typeof msg.payload === 'function') {
                msg.payload = util.inspect(msg.payload, false, null, true)
            }
            msg.logger.call(msg.logger, msg.payload + '\n' + msg.stacktrace)
        })
        //orig.log(`Logging for "${jasmine.currentTest.fullName}" end`)
    }
    consoleMessages = []
})
Run Code Online (Sandbox Code Playgroud)

缺点

  • 因为我们覆盖了控制台,日志的堆栈跟踪丢失了,当调用控制台时,jest 使用的堆栈跟踪只包含设置中被覆盖的 console.log(/debug/error/...) 调用的堆栈文件。因此,为了获取原始堆栈跟踪,我们抛出一个错误。然后可以将其附加到正在记录的文本中。不是特别漂亮,但有效。


Alw*_*ing 5

有一些方法可以巧妙地处理您的expect呼叫,让您知道故障发生在哪里。这样的东西有用吗?

const location = "case 1 failed";
const result = someFunction();  
expect({result: result, location}).toEqual({result: "hello", location});
Run Code Online (Sandbox Code Playgroud)

现在,如果someFunction()返回“hello”以外的内容,它会告诉您位置值,因为它会抱怨预期的内容。

仅当您收到 Jest 错误,但无法从正常expect失败消息中获取足够的信息并且您需要更多详细信息时,这实际上才有用。