Bagaimana cara melewatkan tes di moka secara terprogram?

142

Saya memiliki kode di mana tes tertentu akan selalu gagal di lingkungan CI. Saya ingin menonaktifkannya berdasarkan kondisi lingkungan.

Bagaimana cara melewatkan tes di moka secara terprogram selama eksekusi runtime?

Gajus
sumber
3
Secara terprogram melewatkan tes tercakup this.skip()dalam mochajs.org/#inclusive-tests dan jawaban @ zatziky di bawah ini. Sisa jawaban sudah usang untuk Mocha v3 +
Patrick
1
uraikan.skip ('deskripsi', () => {}) / uraikan.hanya ('deskripsi', () => {}) / it.skip ('deskripsi', () => {}) / itu. hanya ('deskripsi', () => {})
Jun711
ada jawaban yang diterima?
Paul Rooney

Jawaban:

168

Anda dapat melewati tes dengan menempatkan x di depan deskripsikan atau memblokirnya, atau menempatkan .skipsetelahnya.

xit('should work', function (done) {});

describe.skip('features', function() {});

Anda juga dapat menjalankan tes tunggal dengan menempatkan .onlytes. misalnya

describe('feature 1', function() {});
describe.only('feature 2', function() {});
describe('feature 3', function() {});

Hanya blok fitur 2 yang akan berjalan dalam kasus ini.

Tampaknya tidak ada cara untuk melewatkan tes secara terprogram, tetapi Anda bisa melakukan semacam pemeriksaan dalam sebuah beforeEachpernyataan dan hanya menjalankan tes jika flag ditetapkan.

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,
         }
    }
}
KJ3
sumber
8
Upaya ke-2 Anda pada solusi tidak akan berhasil, karena urutan eksekusi bukan yang Anda pikirkan. Ketika beforeEachpanggilan dijalankan, Mocha mencatat fungsi anonim ("kait") untuk digunakan di masa depan , ketika describepanggilan dieksekusi, Mocha segera mengeksekusi fungsi anonim yang diteruskan ke sana. Jadi pada saat if (runTest)dieksekusi, beforeEach kait tidak akan berjalan.
Louis
22
Bagaimana jawaban ini memiliki 27 upvote? Pertanyaannya adalah tentang melewatkan tes secara terprogram, sehingga menambahkan ".skip" atau ".only" tidak membantu. Kemudian secara eksplisit mengatakan Anda tidak dapat melakukan apa yang OP ingin lakukan, meskipun pada kenyataannya jawaban lain memberi tahu Anda bagaimana melakukannya.
Graeme Perrow
3
Tidak akan bekerja, bukan jawaban untuk pertanyaan itu, lihat respon @Gajus sebagai gantinya
NorTicUs
1
Jawaban ini memiliki kelebihan untuk pertanyaan berbeda yang tidak ditanyakan di sini. Saya tidak memiliki kekuatan untuk mengubah apa pun di sini. Lihat jawaban this.skip ().
Andrew Martinez
3
ini tidak menjawab pertanyaan
Ingo Renner
109

Ada cara yang tidak berdokumen untuk melewatkan tes secara terprogram:

// test.js

describe('foo', function() {
  before(function() {
    this.skip();
  });

  it('foo', function() {
    // will not run
    console.log('This will not be printed');
  });
});

berlari:

$ mocha test.js


  foo
    - foo


  0 passing (9ms)
  1 pending

Ini dibahas di https://github.com/mochajs/mocha/issues/1901 .

Gajus
sumber
13
Pembaca mungkin ingin tahu bahwa ini menandai keseluruhan describesebagai dilewati (yaitu semua tes di describedilewati).
Louis
Dokumentasi "pending test" Mocha
lasec0203
uraikan.skip ('deskripsi', () => {}) / uraikan.hanya ('deskripsi', () => {}) / it.skip ('deskripsi', () => {}) / itu. hanya ('deskripsi', () => {})
Jun711
Saya tidak mengerti mengapa jawaban seperti ini terangkat. ini adalah hack - dan bukan preety.
chenop
2
dokumentasi aktual mochajs.org/#inclusive-tests , ini bukan hack btw dengan cara apa pun, tetapi metode yang benar untuk mengecualikan beberapa tes berdasarkan pengaturan runtime. yaitu menjawab dengan tepat apa yang ditanyakan pertanyaan aslinya. Terima kasih @xavdid
WowPress.host
41

Jawaban ini berfungsi untuk ES6 .

Dari pada:

describe('your describe block', () => {

Kamu ingin:

(condition ? describe : describe.skip)('your describe block', () => {

Kondisi ini melewatkan semua tes dalam blok uraian JIKA kondisinya salah.

Atau, bukannya:

it('your it block', () => {

Kamu ingin:

(condition ? it : it.skip)('your it block', () => {

Persyaratan ini melewatkan satu pengujian JIKA kondisinya salah.

danday74
sumber
4
Saya mendapatkan apa yang Anda sarankan, tetapi pertama-tama Anda perlu mendefinisikan deskripsi kontekstual seperti ini: const contextualDescribe = shouldAvoidTests ? describe.skip : describe kemudian Anda dapat menggunakannya: contextualDescribe('your it block', () => {
Ser
3
@Ser Untuk mendapatkan satu baris, saya menggunakan sesuatu seperti ini:(condition ? describe : describe.skip)('your describe block', () => {
joshden
Bagaimana cara melakukan async ini? Saya perlu mencari kondisi loncatan berdasarkan flag redis, yang merupakan operasi async (kami menyimpan flag fitur di redis).
Patrick Finnigan
Sudah lama tapi saya punya kebutuhan semacam ini sebelumnya juga, saya pikir saya baru saja membungkus semua barang moka dalam fungsi yang dipanggil setelah panggilan balik async selesai - tidak dapat mengingat detail yang tepat
danday74
Saya dulu menggunakan teknik ini tetapi sekarang gagal untuk saya. coba saja menulis(it)('my test', () => {})
cyrf
33

Saya menggunakan runtime skipping dari Mocha untuk skenario yang sama seperti yang Anda gambarkan. Ini adalah salinan dari dokumen :

it('should only test in the correct environment', function() {
  if (/* check test environment */) return this.skip();

  // make assertions
});

Seperti yang Anda lihat, tes ini dilewati berdasarkan lingkungan. Kondisiku sendiri if(process.env.NODE_ENV === 'continuous-integration').

Amio.io
sumber
2
Sepakat! Mungkin satu kapal dengan melakukan pengembalian awal mungkin? Seperti: if (/* skipTestCondition */) return this.skip();- sunting: karya: D
SidOfc
12

untuk melewati tes, gunakan describe.skipatauit.skip

describe('Array', function() {
  it.skip('#indexOf', function() {
    // ...
  });
});

untuk memasukkan tes yang dapat Anda gunakan describe.onlyatauit.only


describe('Array', function() {
  it.only('#indexOf', function() {
    // ...
  });
});

Info lebih lanjut di https://mochajs.org/#inclusive-tests

lfender6445
sumber
6

Tergantung bagaimana Anda ingin melewatkan tes secara terprogram. Jika kondisi untuk dilewati dapat ditentukan sebelum kode pengujian dijalankan, maka Anda dapat menelepon itatau it.skipsesuai kebutuhan, berdasarkan kondisi. Misalnya, ini akan melewati beberapa tes jika variabel lingkungan ONEdisetel ke nilai apa pun:

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!");
    });

});

Jika kondisi yang ingin Anda periksa hanya dapat ditentukan pada waktu tes, itu sedikit lebih rumit. Jika Anda tidak ingin mengakses apa pun yang tidak sepenuhnya merupakan bagian dari API pengujian, maka Anda dapat melakukan ini:

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!");
    });

});

Sedangkan contoh pertama saya adalah menandai tes yang dilewati secara formal (alias "tertunda"), metode yang baru saja saya tunjukkan hanya akan menghindari melakukan tes yang sebenarnya tetapi tes tidak akan ditandai sebagai dilewati secara resmi. Mereka akan ditandai sebagai lulus. Jika Anda benar-benar ingin agar mereka dilewati, saya tidak tahu cara apa pun untuk mengakses bagian yang tidak berbicara dengan benar sebagai bagian dari API pengujian:

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!");
    });

});
Louis
sumber
3

Saya tidak yakin apakah ini memenuhi syarat sebagai "lompatan terprogram", tetapi untuk melewati beberapa tes khusus untuk lingkungan CI kami, saya menggunakan fitur penandaan Mocha ( https://github.com/mochajs/mocha/wiki/Tagging ). Dalam describe()atau it()pesan, Anda dapat menambahkan tag seperti @ no-ci. Untuk mengecualikan tes tersebut, Anda dapat menentukan "target ci" spesifik di package.json Anda dan menggunakan --grepdan --invertparameter seperti:

"scripts": {
  "test": "mocha",
  "test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}
martin
sumber
Ini adalah salah satu cara untuk melewati tes. Contoh kecil akan sangat berguna. Tetapi saya sangat setuju bahwa tautan yang Anda bagikan memiliki contoh di awal. @martin
Krishna Pravin
2

Anda dapat menggunakan paket saya mocha-berasumsi untuk melewati tes pemrograman, tetapi hanya dari luar tes. Anda menggunakannya seperti ini:

assuming(myAssumption).it("does someting nice", () => {});

Mocha-menganggap hanya akan menjalankan tes Anda saat myAssumptionini true, jika tidak maka akan melewatkannya (menggunakan it.skip) dengan pesan yang bagus.

Inilah contoh yang lebih rinci:

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... */
        });
    });
});

Dengan menggunakan cara ini, Anda dapat menghindari kegagalan cascading. Katakanlah tes "Does something cool"akan selalu gagal ketika beberapa Asumsi tidak berlaku - Tapi asumsi ini sudah diuji di atas (dalam Tests that verify someAssuption is always true").

Jadi kegagalan tes tidak memberi Anda informasi baru. Bahkan, itu bahkan salah-positif: Tes tidak gagal karena "sesuatu yang keren" tidak berfungsi, tetapi karena prasyarat untuk tes tidak memuaskan. dengan mocha-assumeAnda sering dapat menghindari positif palsu seperti itu.

David Tanzer
sumber
Ini benar-benar keren, sedih bahwa proyek itu tampaknya ditinggalkan ...
Victor Schröder
@ VictorSchröder Yah, saya mendapat kesan tidak ada yang menggunakannya. Mungkin akan memperbaikinya dalam beberapa minggu ke depan, jika saya punya waktu. Bisakah Anda membuka masalah di github dan memberi tahu saya apa yang ingin Anda lihat?
David Tanzer
Saya belum menggunakannya, @ David Tanzer, saya baru saja menemukan ide Anda keren . Saya melihat diri saya melakukan persiapan ujian dan melewatkan banyak persyaratan dan antarmuka seperti ini jauh lebih mudah dibaca. Saya masih harus mencobanya, tetapi saya membayangkan itu akan keren untuk dapat menghubungkan beberapa asumsi dan mendukung fungsi async sebagai asumsi. Mungkin semua ini sudah didukung, saya belum memeriksa.
Victor Schröder
1
Namun, ada masalah dengan contoh kedua dalam jawaban ini. The beforeAllkail tidak dijamin untuk menjalankan sebelum semua tes dikumpulkan. Sebenarnya, itu sangat mungkin hanya berjalan setelahnya, tetapi dalam kasus assuming(someAssumption)ini sudah akan menerima nilai awal (tidak ditentukan). Dibutuhkan untuk membungkus bagian itu dalam suatu fungsi juga untuk mencapai efek yang diinginkan.
Victor Schröder
2

Kita dapat menulis fungsi pembungkus bersih yang bagus untuk menjalankan tes bersyarat sebagai berikut:

function ifConditionIt(title, test) {
  // Define your condition here
  return condition ? it(title, test) : it.skip(title, test);
}

Ini kemudian dapat diminta dan digunakan dalam pengujian Anda sebagai berikut:

ifConditionIt('Should be an awesome test', (done) => {
  // Test things
  done();
});
dcr24
sumber
Saya pikir ini adalah solusi paling elegan yang disajikan di sini. Dapat diperpanjang dengan mudah untuk melakukan logika yang lebih rumit, dan memiliki bonus tambahan bahwa tes yang dilewati dengan cara ini ditandai sebagai dilewati dalam laporan pengujian
Joshua Evans
0

Katakanlah saya ingin melewati tes parametrized saya jika deskripsi tes saya berisi string "foo", saya akan melakukan ini:

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

Dalam kasus Anda, saya percaya bahwa jika Anda ingin memeriksa variabel lingkungan, Anda bisa menggunakan NodeJS:

process.env.ENV_VARIABLE

Misalnya (Peringatan: Saya belum menguji sedikit kode ini!), Mungkin kira-kira seperti ini:

(process.env.NODE_ENV.indexOf("prod") === -1 ? it : it.skip)("should...", function(done) {
    // Code here
});

Di mana Anda dapat menetapkan ENV_VARIABLE menjadi apa pun yang Anda pilih, dan menggunakan nilai itu, lewati atau jalankan pengujian. (FYI dokumentasi untuk proses.env NodeJS ada di sini: https://nodejs.org/api/process.html#process_process_env )

Saya tidak akan mengambil kredit lengkap untuk bagian pertama dari solusi ini, saya menemukan dan menguji jawabannya dan bekerja sempurna untuk melewati tes berdasarkan kondisi sederhana melalui sumber daya ini: https://github.com/mochajs/mocha/issues / 591

Semoga ini membantu! :)

Rubicon
sumber
0

Ini tidak benar-benar menggunakan fitur mocha, melainkan men-tweak untuk mendapatkan perilaku yang saya inginkan.

Saya ingin melewati setiap 'itu' berikutnya dalam tes mocha busur derajat saya dan satu 'itu' gagal. Ini karena begitu satu langkah tes perjalanan gagal, hampir pasti sisanya akan gagal, dan mungkin memakan waktu lama dan memakan server build jika mereka menggunakan browser menunggu elemen muncul di halaman, dll.

Ketika hanya menjalankan tes moka standar (bukan busur derajat) ini dapat dicapai dengan kait global sebelum dan setiap kait dengan melampirkan bendera 'lewati' ke induk tes (jelaskan) seperti ini:

    beforeEach(function() {
      if(this.currentTest.parent.skipSubsequent) {
            this.skip();
      }
    }); 


    afterEach(function() {
      if (this.currentTest.state === 'failed') {
        this.currentTest.parent.skipSubsequent = 'true'
      }
    })

Ketika mencoba ini dengan busur derajat dan moka itu ruang lingkup 'ini' telah berubah dan kode di atas tidak berfungsi. Anda berakhir dengan pesan kesalahan seperti 'panggilan kesalahan dilakukan ()' dan berhenti busur derajat.

Sebaliknya saya berakhir dengan kode di bawah ini. Bukan yang tercantik, tetapi akhirnya menggantikan penerapan fungsi tes yang tersisa dengan this.skip (). Ini mungkin akan berhenti berfungsi jika / ketika internal mocha berubah dengan versi yang lebih baru.

Itu ditemukan melalui beberapa percobaan dan kesalahan dengan men-debug dan memeriksa internal mocha ... membantu membuat suite tes browser selesai lebih cepat ketika tes gagal.

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'
    }
});
Paul Silvester
sumber
-2

Sebagai @danielstjules menjawab di sini ada cara untuk melewati tes. @author dari topik ini telah menyalin jawaban dari diskusi mochajs github.com, tetapi tidak ada info dalam versi mocha apa yang tersedia.

Saya menggunakan modul grunt-mocha-test untuk mengintegrasikan fungsionalitas tes mocha dalam proyek saya. Melompat ke versi terakhir (untuk sekarang) - 0.12.7 bawakan saya mocha versi 2.4.5 dengan implementasi this.skip ().

Jadi, di package.json saya

  "devDependencies": {
    "grunt-mocha-test": "^0.12.7",
    ...

Lalu

npm install

Dan itu membuat saya senang dengan kait ini:

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();
        }

        ...
Victor Perov
sumber
-2

Tolong jangan. Tes yang tidak bekerja secara konsisten di seluruh lingkungan harus diakui seperti itu oleh infrastruktur bangunan Anda. Dan itu bisa sangat membingungkan ketika CI membangun memiliki jumlah tes yang berbeda dari lokal.

Itu juga mengacaukan pengulangan. Jika tes yang berbeda berjalan di server dan lokal saya dapat memiliki tes gagal di dev dan lulus di CI atau sebaliknya. Tidak ada fungsi pemaksaan dan saya tidak memiliki cara untuk dengan cepat dan akurat memperbaiki bangunan yang gagal.

Jika Anda harus mematikan tes di antara lingkungan, alih-alih menjalankan pengujian secara kondisional, beri tag pada pengujian Anda dan gunakan filter untuk menghilangkan tes yang tidak berfungsi pada target build tertentu. Dengan begitu semua orang tahu apa yang terjadi dan itu sesuai dengan harapan mereka. Ini juga membuat semua orang tahu bahwa ada ketidakkonsistenan dalam kerangka pengujian, dan seseorang mungkin memiliki solusi yang membuat mereka berjalan dengan baik lagi. Jika Anda hanya menonaktifkan tes, mereka mungkin tidak tahu ada masalah.

Jason
sumber