在Jasmine测试失败后执行代码

时间:2015-07-13 17:49:48

标签: logging jasmine

只有在Jasmine测试失败时才可以做某事吗?与afterEach()并列,无论结果如何都在it()之后执行,我只是在it()期望失败后才寻找执行代码的方法。

这个问题不是Angular特有的,但在我的场景中,我正在测试Angular服务,它使用$log输出调试消息。我不想让我的控制台混乱以获得成功的测试,但只显示失败测试的附加信息。

describe("MyService", function() {
    var MyService, $log;

    beforeEach(function() {
        inject(function (_MyService_, _$log_) {
            MyService = _MyService_;
            $log = _$log_;
        });
    });

    afterEach(function () {
        if (/* test failed */) {
            //console.log($log.debug.logs);
        }
    });

    it("should output debug logs when this fails", function() {
        //do something with MyService that would put a message in $log
        expect(false).toBe(true);
    });
});

我正在运行Jasmine 2.2.0。

编辑:here是一个非常简单的小提琴,显示Jasmine 1.3 jasmine.getEnv().currentSpec解决方案不再有效。

4 个答案:

答案 0 :(得分:8)

这是在Jasmine 2中重新启用jasmine.getEnv().currentSpec的黑客攻击(result不是完整的spec对象,而是包含id,{{1 }},descriptionfullNamefailedExpectations):

passedExpectations

答案 1 :(得分:4)

我终于弄清楚如何使用Jasmine 2.3.4获取对失败规范结果的引用,但我不确定它是否正是您正在寻找的内容

我使用随Jasmine设置一起安装的vanilla PlayerSpec.js文件。我运行了SpecRunner.html文件来执行测试。

以下是我在PlayerSpec文件中更改的内容:

describe("Player", function() {
  var player;
  var song;
  var index = 0;

  beforeEach(function() {
    player = new Player();
    song = new Song();
    this.index = index++;
  });

  afterEach(function() {
    if (this.index > 0)
    {   var failed = jsApiReporter.specResults(this.index -1, 1)[0].failedExpectations;
        console.log('failed: ', failed);
        if (failed.length > 0)
        {
            console.log('After: ', this, failed[0].message);
            alert('ha');
        }
    }
  });
  it("should not fail", function()
  { expect(1).toEqual(2);
  });
...

文件的其余部分与原来的相同。

以下是我改变的内容:

添加了一个索引变量来跟踪当前的规格编号。

在beforeEach函数中,我将索引值添加到" this"在it,beforeEach和afterEach函数之间传递的对象。这允许我根据需要在它们之间进行通信。我只使用这种机制来传递索引。谨防!如果您只是尝试使用索引值,它就不会起作用!这些函数是异步处理的,所以索引值很可能不是你在afterEach函数中所期望的那样。

在afterEach函数中,我检查以确保索引大于0.在我的本地测试中,第一个规范失败,但直到第二次调用afterEach时才能识别。这是我不确定这会使你想要的原因之一。然后,我获取对failedExpectations的引用,并在识别出错误时进行一些条件处理。

最后一次更改是添加了一个会导致失败的新规范。

这是我的FireBug控制台结果的糟糕副本:

failed: [Object { matcherName="toEqual",  message="Expected 1 to equal 2.",  stack="stack@http://localhost:4...ne-2.3.4/boot.js:110:5\n",  more...}]
PlayerSpec.js (line 15)
After: Object { index=1} Expected 1 to equal 2.
PlayerSpec.js (line 18)
failed: []
PlayerSpec.js (line 15)
failed: []
PlayerSpec.js (line 15)
failed: []
PlayerSpec.js (line 15)
failed: []
PlayerSpec.js (line 15)

这个问题一直是我的旅程。可悲的是,我必须转向其他事情。

我真诚地希望这可以解决您的问题,或者至少指出您正确的方向。希望它也会帮助其他人。

祝你好运!

答案 2 :(得分:1)

我还在使用Jasmine 1.2,所以在Jasmine 2.0中可能会有所不同。

在afterEach函数中,您应该能够使用以下命令访问刚刚完成的当前规范:

var currentSpec = jasmine.getEnv().currentSpec;

这将返回一个具有许多属性的对象。其中之一是传递了多少嵌入式测试(results_.passedCount)。

您可以针对该值进行测试并适当地执行日志记录。

祝你好运!

答案 3 :(得分:0)

我想在jasmine 2.5.2上做类似的事情(拥有自定义记录器对象,只有在测试失败时才会打印出来,而不必手动执行)。

为了让它在每次/每次之后都能正常工作而挣扎了很多,最后我陷入了一个更丑陋的解决方案

// logger print on fail

function collectSpecs(suite: jasmine.Suite): jasmine.Spec[] {
    const result: jasmine.Spec[] = [];
    const process = [suite];
    while (process.length) {
        const suite = process.pop();
        const children = <jasmine.SuiteOrSpec[]> <any> suite.children; // wrong jasmine typing
        children.forEach(item => {
            switch (item.constructor.name) {
                case "Suite":
                    process.push(<jasmine.Suite>item);
                    break;
                case "Spec":
                    result.push(<jasmine.Spec>item);
                    break;
            }
        });
    }
    return result;
}

function findSpec(specId: string): jasmine.Spec {
    const rootSuite: jasmine.Suite = jasmine.getEnv()["topSuite"]();
    return collectSpecs(rootSuite)
        .filter(s => `${s.id}` === specId)[0];  // wrong jasmine typing on id
}

const loggerSpecProperty = "logger";

function createReporter(): jasmine.CustomReporter {
    return {
        specDone: (result: jasmine.CustomReporterResult) => {
            const spec = findSpec(result.id);
            if (result.failedExpectations.length) {
                const logger: modLog.MemoryLogger = spec[loggerSpecProperty];
                if (logger) {
                    console.log(`\nfailed spec logger:\n${logger.lines.join("\n")}`);
                }
            }
            delete spec[loggerSpecProperty];
        }
    };
}

export function registerReporter(): void {
    jasmine.getEnv().addReporter(createReporter());
}

function createLogger(): modLog.MemoryLogger {
    return new modLog.MemoryLogger(modLog.LogLevel.debug);
}

interface IItCallback {
    (done?: Function): void;
}

interface IItFunctionTyping {
    (name: string, callback: IItCallback): void;
}

interface IItFunction {
    (name: string, callback: IItCallback): jasmine.Spec;
}

// bad typings on it/xit/fit, actually returns Spec but is typed as void
export function lit(fnIt: IItFunctionTyping, name: string, callback: IItCallback): jasmine.Spec {
    function inner(spec: jasmine.Spec, done?: Function) {
        const log = createLogger();
        this.log = log;
        spec[loggerSpecProperty] = log;
        callback.call(this, done);
    }
    const itFunc = <IItFunction> (fnIt || it);
    if (callback.length) {
        const spec = itFunc(name, function (done) {
            inner.call(this, spec, done);
        });
        return spec;
    } else {
        const spec = itFunc(name, function () {
            inner.call(this, spec);
        });
        return spec;
    }
}
由于@ types / jasmine隐藏了实际实现的一些细节(我认为它是故意的,输入版本与jasmine包版本相匹配),但是我还想练习我的TypeScript

,因为某些不必要的类型mumbo jumbo

传递“it”函数以在需要时仍然允许xit / fit modLog是我的记录器模块,覆盖它以满足您的需求

用法:

而不是

it("should do something", function (done) {
    done();
});

使用

lit(it, "should do something", function (done) {
    this.log.debug("test");
    fail("test output");
    done();
});

(记录不是很好,但我认为你可以得到图片)

如果有一种方法可以让customReporter访问规范上下文

,那就更好了

(然后这一切基本上只是为了调试目的,你也可以将console.log添加到特定的测试中,当它失败并且你正在努力解决细节时,但是对于了解一点茉莉花是有趣的练习更多)