2015-07-13 2 views
4

Можно ли что-то сделать только в случае неудачи теста Жасмин? Сопоставимый с afterEach(), который выполняется после it(), независимо от результата, я ищу способ выполнить код только после того, как it() имеет неудачное ожидание.Выполнить код после отказа теста Жасмин

Этот вопрос не является угловым, но в моем сценарии я тестирую Угловую службу, которая выводит отладочные сообщения, используя $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 больше не работает.

ответ

1

Вот хак, чтобы повторно включить jasmine.getEnv().currentSpec в Jasmine 2 (вид, result не полный spec объект, но содержит id, description, fullName, failedExpectations и passedExpectations):

jasmine.getEnv().addReporter({ 
    specStarted(result) { 
     jasmine.getEnv().currentSpec = result; 
    }, 
    specDone() { 
     jasmine.getEnv().currentSpec = null; 
    } 
}); 
+0

Приятно! Я никогда не думал, чтобы (ab) использовал репортеров Jasmine, чтобы заменить этот бит функциональности, и мне это вообще не кажется взломанным. [Здесь] (http://jsfiddle.net/dimmreaper/Lfvhjdjh/1/) обновленная скрипка, показывающая это вместо старого jasmine.getEnv(). CurrentSpec', и это действительно позволяет вам проверять результаты спецификации сразу после его завершения. –

+0

Я принимаю это как лучший ответ, так как это чистое решение, которое обеспечивает функциональность, которую я искал. –

+0

Блестящее решение. WOW: D @tlrobinson Спасибо :) – ShellZero

0

Я все еще использую Jasmine 1.2, поэтому, возможно, в Jasmine 2.0 все по-другому.

В функции afterEach, вы должны быть в состоянии получить доступ к текущей спецификации, который только что закончил с использованием:

var currentSpec = jasmine.getEnv().currentSpec; 

Это возвращает объект, который имеет много свойств. Одним из них является то, сколько из встроенных тестов прошло (results_.passedCount).

Вы можете протестировать это значение и выполнить соответствующее ведение журнала.

Удачи вам!

+0

В поисках ответа я бы использовал код, похожий на то, что вы опубликовали, но, начиная с Jasmine 2.0, они удалили свойство currentSpec, чтобы я больше не мог его использовать. –

+0

Я только что загрузил версию 2.3.4 и выполнил команду, указанную в моем ответе. На объекте jasmine.getEnv() все еще есть свойство currentSpec. Если он был удален в версии 2.2, он вернётся в версии 2.3.4. Вы можете проверить наличие или отсутствие с помощью простого сообщения console.log в функции afterEach. Когда я запустил его на своей локальной машине, он показал currentSpec. – murmeister

+0

Я просто обновился до 2.3.4, надеясь. Но когда я запускаю консоль.log (jasmine.version + '' + jasmine.getEnv(). currentSpec) 'внутри my' afterEach() ', я получаю' 2.3.4 undefined'. Мне любопытно, как вы можете это увидеть ... –

3

Я, наконец, понял, как получить ссылку на результаты неудавшейся спецификации с Jasmine 2.3.4, но я не уверен, что это будет именно то, что вы ищете.

Я использовал файл Vanilla PlayerSpec.js, который поставляется с установкой Jasmine. Я выполнил файл 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 я добавил значение индекса к этому «объекту», который передается между его функциями, beforeEach и afterEach. Это позволяет мне общаться между ними по мере необходимости. Я использую этот механизм для передачи индекса. Осторожно! Если вы просто попытаетесь использовать значение индекса, это не сработает! Функции обрабатываются асинхронно, поэтому есть хорошая вероятность, что значение индекса НЕ будет тем, что вы ожидаете в функции afterEach.

В функции afterEach я проверяю, чтобы индекс был больше 0. В моем локальном тестировании первый spec не работает, но он не распознается до тех пор, пока не будет вызвано время SECOND. Это одна из причин, по которым я не уверен, что это будет работать. Затем я получаю ссылку на failExpectations и выполняю некоторую условную обработку, если распознаю ошибку.

Последнее изменение, которое присутствует, - это добавление новой спецификации, которая приведет к сбою.

Вот бедный копия моих результатов консоли Firebug:

failed: [Object { matcherName="toEqual", message="Expected 1 to equal 2.", stack="[email protected]://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) 

Эта проблема была поездка для меня. К сожалению, я должен перейти к другим вещам.

Я искренне надеюсь, что это решает вашу проблему или, по крайней мере, указывает на то, что вы в правильном направлении. Надеюсь, это тоже поможет другим.

Удачи!

+0

Вау, большое вам спасибо за все усилия, которые вы вложили в это. Мне нужно немного, чтобы переварить это и действительно понять, что происходит, и если это решает мою проблему. По крайней мере, это самая близкая вещь, которую я видел, когда кто-либо придумал, чтобы получить доступ к внутренним Jasmine так, как мы были в версии 1.3. –

+0

Вау ... Я долгое время возвращался к этому, сожалею об этом. Я впечатлен готовым решением, с которым вы столкнулись. Конечно, я бы предпочел не изменять Jasmine напрямую, но я принимаю это как лучшее (и предположительно только) решение. Тем не менее, необходимость в этом была просто отладки информации, так что я думаю, что я буду придерживаться ваниль Жасмин на данный момент. Большое вам спасибо за все усилия, которые вы вложили в это. –

+0

Я сейчас пытаюсь что-то подобное, но кажется, что 'jsApiReporter' не дает результатов сразу, поэтому только около половины спецификаций во время их' afterEach' может получить spec resut. Это с 2.4.1. – Gunchars

0

I хотел сделать что-то подобное на жасмине 2.5.2 (с пользовательским логгером, который будет распечатываться только тогда, когда тест завершится неудачей, без необходимости делать это вручную).

Боролся совсем немного, чтобы заставить его работать в общем через beforeEach/afterEach, в конце концов я сдалась к уродливой раствору

// 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; 
    } 
} 

некоторые ненужным типа Мамбо Джамбо там из-за @ типы/жасмин заслоняя некоторые детали фактическая реализация (я полагаю, это специально, типичная версия соответствует версии пакета жасмина), но я также хотел практиковать свою функцию «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 к конкретному тесту, когда он терпит неудачу, и вы боретесь с деталями, но это было интересное упражнение, чтобы немного узнать о жасмине more)

Смежные вопросы