0

我正在使用 WDIO 并定义一个客户报告器以与 testrails api 集成。计划是使用 axios 在测试钩子中发出这些请求。

不幸的是,我无法让 axios 返回有关请求的任何有效数据。在大多数情况下,当我们await响应时,线程完全停止执行,没有任何日志输出。如果我足够吉米有时我可以让它返回一个未解决的承诺,但我无能为力最终解决这个承诺。

同样,在我的任何尝试中,testrails 都没有收到请求(我也测试了其他一些 url,我相当确定问题不在目的地)。

我已经确保网络访问和安全不是因素。我们还尝试使用 axios post 和直接 axios() 方法,但没有运气。

我将复制下面的文件,我添加了大约十几个尝试/配置,每个都附有关于我们得到什么的注释。问题的核心在于 addRun() 方法。

在大多数情况下,我们似乎永远不会解决承诺。有一个例外,我们根本不与响应交互,只需登录 then() 语句。如果我们这样做,我们可以看到那些日志,但是 axios 调用的结果永远不会生效(运行不是在 testrails 中创建的)。

const WDIOReporter = require('@wdio/reporter').default
const axios = require('axios').default;

module.exports = class TestrailsReporter extends WDIOReporter{
    constructor(options) {
        /*
         * make reporter to write to the output stream by default
         */
        options = Object.assign(options, { stdout: true })
        super(options)
    }

    // I have tried marking this as both async and not, no difference
    async onRunnerEnd(suite) {
        console.log("CHECKPOINT RUNNER END")
        this.recordResults(caseIds[5], results[5], 'renters api tests', 5);
    }
    /**
     * takes the results from a test suite and records them in testrails
     * @param suiteId -- the suite defined in the testrails project
     * @param projectId -- the project id defined in the testrails project
     * @param caseIds -- a list of cases with which to create the test run
     * @param results -- a list of case:result pairings
    */
    async recordResults(caseIds, results, name, projectId) {
        console.log(`CHECKPOINT RECORDING RESULTS ${projectId}`)
        let testRun = await this.addRun(results['suiteId'], caseIds['cases'], name, projectId);
        testRun.then(console.log)
        await this.addResults(testRun, results['cases']);
    }

    async addRun(suiteId, caseIds, name = '', projectId) {
        console.log("CHECKPOINT ADD RUN")
        let addRunConfig = {
            method: 'post',
            url: `https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`,
            headers: {
                'Content-Type': 'application/json',
                Authorization: token,
                Cookie: 'tr_session=041c4349-688f-440a-95a3-afc29d39320a'
            },
            data: JSON.stringify({
                suite_id: suiteId,
                include_all: false,
                case_ids: caseIds,
                name: name
            })
        };

        // let x = axios.get('https://www.google.com/')
        // console.log(x)

        axios.defaults.timeout = 1000;

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, RETURNS PENDING PROMISE TO RESPONSE
        // let response = axios(addRunConfig)
        //     .then(function (response) {
        //         console.log("WHAAAT?")
        //         return response.data.id;
        //     })
        //     .catch(function (error) {
        //         console.log("HELP!")
        //         console.log(error);
        //     });
        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, NO LOGGING APPEARS AFTER
        let response = await axios(addRunConfig)
            .then(function (response) {
                console.log("WHAAAT?")
                return response.data.id;
            })
            .catch(function (error) {
                console.log("HELP!")
                console.log(error);
            });

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT
        // await axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(
        //         function (response){
        //             console.log('WHAAAT?')
        //             console.log(response)
        //             console.log('NO WAY?')
        //         })

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, BUT RETURNS A PENDING PROMISE TO RESPONSE
        // let response = axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(
        //         function (run){
        //             console.log('WHAAAT?')
        //             console.log(run)
        //             console.log('NO WAY?')
        //         })

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, BUT RETURNS A PENDING PROMISE TO RESPONSE
        // let response = axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(
        //         function (run){
        //             console.log('WHAAAT?')
        //         })

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, BUT RETURNS A PENDING PROMISE TO RESPONSE
        // let response = axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(run => {
        //             console.log('WHAAAT?')
        //         })

        // THIS EXECUTES THE CONSOLE.LOG INSIDE THE THEN STATEMENT, BUT NOT AFTER
        // let response = await axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(console.log('WHAAAT?'))

        // THIS EXECUTES THE CONSOLE.LOG INSIDE THE THEN STATEMENT, AND AFTER
        // let response = axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(console.log('WHAAAT?'))

        // EXECUTES THE CONSOLE.LOG INSIDE THE THEN STATEMENT, NOTHING FROM THE CATCH, AND NOTHING AFTER
        // const response = await axios(addRunConfig).then(console.log("HI")).catch(function (error) {
        //     console.log("HELP!")
        //     console.log(error);
        // });

        console.log("ANYTHING")
        console.log(response)
        return response
    }```
4

3 回答 3

1

想通了,这是 WDIOReporter 父类不能很好地处理来自 axios 的异步调用。解决方案在这里找到: https ://github.com/webdriverio/webdriverio/issues/5701

于 2021-06-22T18:43:43.177 回答
0

您是否尝试过使用 await axios.post(...)而不是在 addRunConfig 对象中定义所有内容来调用该方法?

不确定它是否会有所作为,但可以尝试一下。

于 2021-06-22T17:56:02.310 回答
0

这里对定义函数、调用函数和异步函数的概念有些混淆。

首先:如果您正在调用一个异步函数并且不希望您的调用函数在该异步函数返回之前返回,那么您想要await该调用。

在这种情况下,您的recordResults函数等待某些东西,因此是异步的。因此,您可能希望onRunnerEnd等待您致电recordResults. 如果您不这样做,该函数将过早终止并且可能不会等待结果。

async onRunnerEnd(suite) {
    console.log("CHECKPOINT RUNNER END")
    await this.recordResults(caseIds[5], results[5], 'renters api tests', 5);
}

其次,如果一起使用thenand await,则表达式返回的值await是返回值中的任何函数then。因此,您在被调用的函数内没有返回值的所有尝试都then不会返回任何内容,而是返回一个 void promise。没有理由将这些概念结合起来。

第三,将函数调用(而不是声明或引用)放在 then 子句中,将立即调用该函数。即.then(console.log('WHAAAT?'))立即调用console.log 并注册一个不存在的函数作为回调then(因为console.log不返回函数引用)。

最后,传递未绑定的函数通常不会起作用。根据and的实现,做类似的事情是testRun.then(console.log)行不通的。要么做,要么就安全起见。thenconsole.logtestRun.then(console.log.bind(console)testRun.then((x) => console.log(x))


所以,首先,在里面添加 await onRunnerEnd,然后then在你的addRun:

async addRun(suiteId, caseIds, name = '', projectId) {
    console.log("CHECKPOINT ADD RUN")
    let addRunConfig = {
        method: 'post',
        url: `https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`,
        headers: {
            'Content-Type': 'application/json',
            Authorization: token,
            Cookie: 'tr_session=041c4349-688f-440a-95a3-afc29d39320a'
        },
        data: JSON.stringify({
            suite_id: suiteId,
            include_all: false,
            case_ids: caseIds,
            name: name
        })
    };

    // let x = axios.get('https://www.google.com/')
    // console.log(x)

    axios.defaults.timeout = 1000;

    let response = await axios(addRunConfig);
    console.log(response);
    console.log(response.data.id);
    return response.data.id;
}
于 2021-06-22T18:09:59.807 回答