Mam kod, w którym pewne testy zawsze kończą się niepowodzeniem w środowisku CI. Chciałbym je wyłączyć na podstawie warunków środowiskowych.
Jak programowo pominąć test w mokce podczas wykonywania?
Mam kod, w którym pewne testy zawsze kończą się niepowodzeniem w środowisku CI. Chciałbym je wyłączyć na podstawie warunków środowiskowych.
Jak programowo pominąć test w mokce podczas wykonywania?
Odpowiedzi:
Możesz pominąć testy, umieszczając x przed opisem lub blokując lub umieszczając .skip
po nim.
xit('should work', function (done) {});
describe.skip('features', function() {});
Możesz również uruchomić pojedynczy test, umieszczając .only
na teście. na przykład
describe('feature 1', function() {});
describe.only('feature 2', function() {});
describe('feature 3', function() {});
W tym przypadku działałby tylko blok funkcji 2.
Wygląda na to, że nie ma sposobu na programistyczne pominięcie testów, ale można po prostu sprawdzić beforeEach
instrukcję i uruchomić test tylko wtedy, gdy flaga została ustawiona.
beforeEach(function(){
if (wrongEnvironment){
runTest = false
}
}
describe('feature', function(){
if(runTest){
it('should work', function(){
// Test would not run or show up if runTest was false,
}
}
}
beforeEach
wywołanie jest wykonywane, Mocha zapisuje anonimową funkcję („haczyk”) do wykorzystania w przyszłości , kiedy describe
wywołanie jest wykonywane, Mocha natychmiast wykonuje przekazaną mu funkcję anonimową. Więc zanim if (runTest)
zostanie wykonany, beforeEach
hak nie będzie działał.
Istnieje nieudokumentowany sposób na programowe pomijanie testów:
// test.js
describe('foo', function() {
before(function() {
this.skip();
});
it('foo', function() {
// will not run
console.log('This will not be printed');
});
});
bieganie:
$ mocha test.js
foo
- foo
0 passing (9ms)
1 pending
Jest to omówione na https://github.com/mochajs/mocha/issues/1901 .
describe
jako pominiętą (tj. Wszystkie testy w sekcji describe
są pomijane).
Ta odpowiedź działa w ES6 .
Zamiast:
describe('your describe block', () => {
Chcesz:
(condition ? describe : describe.skip)('your describe block', () => {
To warunkowo pomija wszystkie testy w bloku opisywania, JEŚLI warunek jest fałszywy.
Lub zamiast:
it('your it block', () => {
Chcesz:
(condition ? it : it.skip)('your it block', () => {
To warunkowo pomija jeden test, JEŚLI warunek jest fałszywy.
const contextualDescribe = shouldAvoidTests ? describe.skip : describe
następnie możesz go użyć: contextualDescribe('your it block', () => {
(condition ? describe : describe.skip)('your describe block', () => {
(it)('my test', () => {})
Używam pomijania w czasie wykonywania z Mocha dla tego samego scenariusza, który opisujesz. To jest kopia wklej z dokumentów :
it('should only test in the correct environment', function() {
if (/* check test environment */) return this.skip();
// make assertions
});
Jak widać, pomija test oparty na środowisku. Mój własny stan to if(process.env.NODE_ENV === 'continuous-integration')
.
if (/* skipTestCondition */) return this.skip();
- edit: works: D
describe.skip
lubit.skip
describe('Array', function() {
it.skip('#indexOf', function() {
// ...
});
});
describe.only
lubit.only
describe('Array', function() {
it.only('#indexOf', function() {
// ...
});
});
Więcej informacji na https://mochajs.org/#inclusive-tests
Zależy to od tego, jak chcesz programowo pominąć test. Jeśli warunki pomijania można określić przed uruchomieniem kodu testowego, możesz po prostu wywołać it
lub it.skip
w razie potrzeby, na podstawie warunku. Na przykład spowoduje to pominięcie niektórych testów, jeśli zmienna środowiskowa ONE
ma dowolną wartość:
var conditions = {
"condition one": process.env["ONE"] !== undefined
// There could be more conditions in this table...
};
describe("conditions that can be determined ahead of time", function () {
function skip_if(condition, name, callback) {
var fn = conditions[condition] ? it.skip: it;
fn(name, callback);
};
skip_if("condition one", "test one", function () {
throw new Error("skipped!");
});
// async.
skip_if("condition one", "test one (async)", function (done) {
throw new Error("skipped!");
});
skip_if("condition two", "test two", function () {
console.log("test two!");
});
});
Jeśli warunki, które chcesz sprawdzić, można określić tylko w czasie testu, jest to nieco bardziej skomplikowane. Jeśli nie chcesz uzyskać dostępu do niczego, co nie jest ściśle mówiąc częścią testowego API, możesz zrobić to:
describe("conditions that can be determined at test time", function () {
var conditions = {};
function skip_if(condition, name, callback) {
if (callback.length) {
it(name, function (done) {
if (conditions[condition])
done();
else
callback(done);
});
}
else {
it(name, function () {
if (conditions[condition])
return;
callback();
});
}
};
before(function () {
conditions["condition one"] = true;
});
skip_if("condition one", "test one", function () {
throw new Error("skipped!");
});
// async.
skip_if("condition one", "test one (async)", function (done) {
throw new Error("skipped!");
});
skip_if("condition two", "test two", function () {
console.log("test two!");
});
});
Podczas gdy moim pierwszym przykładem było oznaczanie testów jako formalnie pominiętych (inaczej „oczekujących”), metoda, którą właśnie pokazałem, pozwoli po prostu uniknąć wykonywania rzeczywistego testu, ale testy nie zostaną oznaczone jako formalnie pominięte. Zostaną oznaczone jako zaliczone. Jeśli absolutnie chcesz je pominąć, nie znam żadnego sposobu na dostęp do części, które nie są poprawnie mówiącą częścią testowego API:
describe("conditions that can be determined at test time", function () {
var condition_to_test = {}; // A map from condition names to tests.
function skip_if(condition, name, callback) {
var test = it(name, callback);
if (!condition_to_test[condition])
condition_to_test[condition] = [];
condition_to_test[condition].push(test);
};
before(function () {
condition_to_test["condition one"].forEach(function (test) {
test.pending = true; // Skip the test by marking it pending!
});
});
skip_if("condition one", "test one", function () {
throw new Error("skipped!");
});
// async.
skip_if("condition one", "test one (async)", function (done) {
throw new Error("skipped!");
});
skip_if("condition two", "test two", function () {
console.log("test two!");
});
});
Nie jestem pewien, czy kwalifikuje się to jako „programowe pomijanie”, ale aby wybiórczo pominąć niektóre testy dla naszego środowiska CI, używam funkcji tagowania Mocha ( https://github.com/mochajs/mocha/wiki/Tagging ). W wiadomościach describe()
lub it()
możesz dodać znacznik, taki jak @ no-ci. Aby wykluczyć te testy, można zdefiniować specyficzny „ci docelowej” w package.json i użytkowania --grep
oraz --invert
parametrów takich jak:
"scripts": {
"test": "mocha",
"test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}
Możesz użyć mojego pakietu mocha-zakładaj, aby pominąć testy programowo, ale tylko spoza testów. Używasz tego w ten sposób:
assuming(myAssumption).it("does someting nice", () => {});
Mocha-zakładaj uruchomi twój test tylko wtedy , gdy myAssumption
jest true
, w przeciwnym razie pominie go (używającit.skip
) z ładnym komunikatem.
Oto bardziej szczegółowy przykład:
describe("My Unit", () => {
/* ...Tests that verify someAssuption is always true... */
describe("when [someAssumption] holds...", () => {
let someAssumption;
beforeAll(() => {
someAssumption = /* ...calculate assumption... */
});
assuming(someAssumption).it("Does something cool", () => {
/* ...test something cool... */
});
});
});
Używając go w ten sposób, możesz uniknąć kaskadowych awarii. Powiedzmy, że test "Does something cool"
zawsze kończy się niepowodzeniem, gdy jakieś założenie nie jest spełnione - ale to założenie zostało już przetestowane powyżej (wTests that verify someAssuption is always true"
).
Zatem niepowodzenie testu nie daje żadnych nowych informacji. W rzeczywistości jest to nawet fałszywie dodatni wynik: test nie zakończył się niepowodzeniem, ponieważ „coś fajnego” nie zadziałało, ale dlatego, że warunek wstępny testu nie został spełniony. z mocha-assume
tobą często można uniknąć takich fałszywych alarmów.
beforeAll
ma gwarancji, że hak będzie działał przed zebraniem wszystkich testów. W rzeczywistości jest bardzo prawdopodobne, że zostanie uruchomiony dopiero później, ale w tym przypadku assuming(someAssumption)
otrzymałby już początkową (nieokreśloną) wartość. Konieczne jest również owinięcie tej części funkcji, aby osiągnąć pożądany efekt.
Możemy napisać ładną, czystą funkcję opakowującą do warunkowego uruchamiania testów w następujący sposób:
function ifConditionIt(title, test) {
// Define your condition here
return condition ? it(title, test) : it.skip(title, test);
}
Może to być następnie wymagane i użyte w testach w następujący sposób:
ifConditionIt('Should be an awesome test', (done) => {
// Test things
done();
});
Powiedzmy, że chcę pominąć sparametryzowany test, jeśli opis testu zawiera ciąg „foo”, zrobiłbym to:
// Skip parametrized test if description contains the string "foo"
(test.description.indexOf("foo") === -1 ? it : it.skip)("should test something", function (done) {
// Code here
});
// Parametrized tests
describe("testFoo", function () {
test({
description: "foo" // This will skip
});
test({
description: "bar" // This will be tested
});
});
W twoim przypadku uważam, że jeśli chcesz sprawdzić zmienne środowiskowe, możesz użyć NodeJS:
process.env.ENV_VARIABLE
Na przykład (Ostrzeżenie: nie testowałem tego fragmentu kodu!), Może coś takiego:
(process.env.NODE_ENV.indexOf("prod") === -1 ? it : it.skip)("should...", function(done) {
// Code here
});
Tam, gdzie możesz ustawić ENV_VARIABLE na wszystko, od czego wyłączasz, i używając tej wartości, pomiń lub uruchom test. (FYI dokumentacja dotycząca process.env NodeJS jest tutaj: https://nodejs.org/api/process.html#process_process_env )
Nie będę w pełni zasługiwał na pierwszą część tego rozwiązania, znalazłem i przetestowałem odpowiedź i działało idealnie, aby pominąć testy oparte na prostym warunku za pośrednictwem tego zasobu: https://github.com/mochajs/mocha/issues / 591
Mam nadzieję że to pomoże! :)
To nie jest tak naprawdę korzystanie z funkcji mokki, a raczej ulepszanie jej, aby uzyskać zachowanie, które chciałem.
Chciałem pominąć kolejne „to” w moich testach mokki z kątomierzem i jedno „to” nie powiodło się. Dzieje się tak, ponieważ gdy jeden etap testu podróży się nie powiódł, było prawie pewne, że reszta się nie powiedzie i może zająć dużo czasu i obciążać serwer kompilacji, jeśli używają przeglądarki, która czeka na pojawienie się elementów na stronie itp.
Po prostu uruchamiając standardowe testy mokka (nie kątomierz) można to osiągnąć za pomocą haków global beforeEach i afterEach, dołączając flagę „skipSubsequent” do elementu nadrzędnego testu (opisz) w następujący sposób:
beforeEach(function() {
if(this.currentTest.parent.skipSubsequent) {
this.skip();
}
});
afterEach(function() {
if (this.currentTest.state === 'failed') {
this.currentTest.parent.skipSubsequent = 'true'
}
})
Przy próbie tego z kątomierzem i mokką zakres „tego” uległ zmianie i powyższy kod nie działa. Kończy się komunikatem o błędzie, takim jak „błąd wywoływania funkcji done ()” i zatrzymanie kątomierza.
Zamiast tego otrzymałem poniższy kod. Nie jest to najładniejsze, ale kończy się zastąpieniem implementacji pozostałych funkcji testowych metodą this.skip (). To prawdopodobnie przestanie działać, jeśli / kiedy wewnętrzne elementy mokki zmienią się w późniejszych wersjach.
Zostało to ustalone metodą prób i błędów, debugując i sprawdzając wewnętrzne elementy mokki ... pomaga jednak w szybszym ukończeniu zestawów testów przeglądarki, gdy testy kończą się niepowodzeniem.
beforeEach(function() {
var parentSpec = this.currentTest.parent;
if (!parentSpec.testcount) {
parentSpec.testCount = parentSpec.tests.length;
parentSpec.currentTestIndex = 0;
} else {
parentSpec.currentTestIndex = parentSpec.currentTestIndex + 1;
}
if (parentSpec.skipSubsequent) {
parentSpec.skipSubsequent = false;
var length = parentSpec.tests.length;
var currentIndex = parentSpec.currentTestIndex;
for (var i = currentIndex + 1; i < length; i++) {
parentSpec.tests[i].fn = function() {
this.skip();
};
}
}
});
afterEach(function() {
if (this.currentTest.state === 'failed') {
this.currentTest.parent.skipSubsequent = 'true'
}
});
mocha test/ --grep <pattern>
Jak odpowiedział @danielstjules tutaj , jest sposób na pominięcie testu. @autor tego tematu skopiował odpowiedź z dyskusji mochajs na github.com, ale nie ma informacji w jakiej wersji mocha jest dostępna.
Używam modułu grunt-mocha-test do integracji funkcji testu mokka w moim projekcie. Przeskakuję do ostatniej (na razie) wersji - 0.12.7, przynieś mi mokkę w wersji 2.4.5 z implementacją this.skip ().
Tak więc w moim pliku package.json
"devDependencies": {
"grunt-mocha-test": "^0.12.7",
...
I wtedy
npm install
I cieszy mnie ten haczyk:
describe('Feature', function() {
before(function () {
if (!Config.isFeaturePresent) {
console.log('Feature not configured for that env, skipping...');
this.skip();
}
});
...
it('should return correct response on AB', function (done) {
if (!Config.isABPresent) {
return this.skip();
}
...
Proszę nie. Test, który nie działa konsekwentnie w różnych środowiskach, powinien zostać uznany za taki przez infrastrukturę kompilacji. Może to być bardzo dezorientujące, gdy kompilacje CI mają inną liczbę testów niż lokalne.
To także psuje powtarzalność. Jeśli różne testy są uruchamiane na serwerze i lokalne, mogę mieć testy, które kończą się niepowodzeniem w tworzeniu i przechodzą w CI lub odwrotnie. Nie ma funkcji wymuszającej i nie mam możliwości szybkiego i dokładnego poprawienia nieudanej kompilacji.
Jeśli musisz wyłączyć testy między środowiskami, zamiast warunkowo uruchamiać testy, otaguj testy i użyj filtru, aby wyeliminować testy, które nie działają w niektórych celach kompilacji. W ten sposób każdy wie, co się dzieje, a to osłabia ich oczekiwania. Dzięki temu wszyscy wiedzą, że we frameworku testowym jest niespójność i ktoś może mieć rozwiązanie, które sprawi, że znów będą działać poprawnie. Jeśli po prostu wyciszysz test, mogą nawet nie wiedzieć, że jest problem.
this.skip()
w mochajs.org/#inclusive-tests i odpowiedzi @ zatziky poniżej. Pozostałe odpowiedzi są nieaktualne dla Mocha v3 +