Ini adalah panduan komprehensif untuk memberikan keandalan dalam JavaScript dan Node.js. Di sini dikumpulkan puluhan pos, buku, dan alat terbaik.
Pertama, berurusan dengan metode pengujian yang diterima secara umum yang mendasari aplikasi apa pun. Dan kemudian Anda dapat mempelajari bidang yang menarik bagi Anda: frontend dan antarmuka, backend, CI atau semua hal di atas.
Isi
Bagian 0. Aturan Emas
0. Golden Rule: Stick to Lean Testing
Apa yang harus dilakukan Kode uji berbeda dari apa yang beroperasi. Jadikan sesederhana mungkin, pendek, bebas dari abstraksi, lajang, hebat di tempat kerja dan hemat. Orang lain harus melihat tes dan segera mengerti apa yang dia lakukan.
Kepala kami sibuk dengan kode produksi, mereka tidak memiliki ruang bebas untuk kompleksitas tambahan. Jika kita memasukkan bagian baru kode kompleks ke dalam pikiran kita yang buruk, ini akan memperlambat pekerjaan seluruh tim pada tugas, untuk kepentingan yang sedang kita uji. Bahkan, karena ini, banyak tim hanya menghindari tes.
Tes - ini adalah kesempatan untuk mendapatkan asisten yang ramah dan tersenyum, dengan siapa sangat baik untuk bekerja dan yang memberikan pengembalian besar pada investasi kecil. Para ilmuwan percaya bahwa di otak kita ada dua sistem: satu untuk tindakan yang tidak membutuhkan usaha, seperti mengemudi di jalan kosong, dan yang kedua untuk operasi kompleks yang membutuhkan kesadaran, seperti menyelesaikan persamaan matematika. Buat tes Anda untuk sistem pertama, sehingga ketika Anda melihat kode Anda mendapatkan perasaan kesederhanaan yang sebanding dengan mengedit dokumen HTML, dan bukan dengan solusi
2X(17 × 24)
.
Ini dapat dicapai dengan pemilihan metode, alat, dan tujuan pengujian yang cermat, sehingga ekonomis dan memberikan ROI yang besar. Uji sebanyak yang diperlukan, cobalah bersikap fleksibel. Terkadang ada baiknya membuang beberapa tes dan mengorbankan keandalan demi kecepatan dan kesederhanaan.

Sebagian besar rekomendasi di bawah ini berasal dari prinsip ini.
Apakah kamu siapBagian 1. Anatomi ujian
1.1 Nama setiap tes harus terdiri dari tiga bagian
Apa yang harus dilakukan Laporan pengujian harus menunjukkan apakah revisi aplikasi saat ini memenuhi persyaratan dari orang-orang yang tidak terbiasa dengan kode: penguji yang terlibat dalam penyebaran insinyur DevOps, serta diri Anda dalam dua tahun. Akan lebih baik jika tes melaporkan informasi dalam bahasa persyaratan, dan namanya terdiri dari tiga bagian:
- Apa sebenarnya yang sedang diuji? Misalnya, metode
ProductsService.addNewProduct
. - Dalam kondisi dan skenario apa? Misalnya, harga tidak diteruskan ke metode.
- Apa hasil yang diharapkan? Misalnya, produk baru tidak disetujui.
Jika tidak. Penyebaran gagal, tes yang disebut "Tambah produk" gagal. Apakah Anda mengerti apa yang salah?
Catatan Setiap bab memiliki kode contoh, dan terkadang ilustrasi. Lihat spoiler.
Contoh kodeBagaimana cara melakukannya dengan benar. Nama tes terdiri dari tiga bagian.
1.2 Struktur tes sesuai dengan pola AAA
Apa yang harus dilakukan Setiap tes harus terdiri dari tiga bagian yang dipisahkan dengan jelas: Atur (persiapan), Tindakan (tindakan) dan Tegas (hasil). Mematuhi struktur seperti itu memastikan bahwa pembaca kode Anda tidak harus menggunakan prosesor otak untuk memahami rencana pengujian:
Atur: semua kode yang membawa sistem untuk menyatakan sesuai dengan skenario pengujian. Ini mungkin termasuk membuat instance dari modul dalam perancang tes, menambahkan catatan ke database, membuat bertopik bukan objek, dan kode lain yang menyiapkan sistem untuk menjalankan tes.
Act: eksekusi kode sebagai bagian dari tes. Biasanya hanya satu baris.
Menegaskan: pastikan bahwa nilai yang diperoleh memenuhi harapan. Biasanya hanya satu baris.
Jika tidak. Anda tidak hanya akan menghabiskan berjam-jam bekerja dengan kode utama, tetapi otak Anda akan membengkak juga dari apa yang seharusnya menjadi pekerjaan sederhana - dari pengujian.
Contoh kodeBagaimana cara melakukannya dengan benar. Tes terstruktur sesuai dengan pola AAA.
describe.skip('Customer classifier', () => { test('When customer spent more than 500$, should be classified as premium', () => {
Contoh dari antipattern. Tidak ada pemisahan, dalam satu bagian, lebih sulit untuk ditafsirkan.
test('Should be classified as premium', () => { const customerToClassify = {spent:505, joined: new Date(), id:1} const DBStub = sinon.stub(dataAccess, "getCustomer") .reply({id:1, classification: 'regular'}); const receivedClassification = customerClassifier.classifyCustomer(customerToClassify); expect(receivedClassification).toMatch('premium'); });
1.3 Jelaskan harapan dalam bahasa produk: sebutkan dengan gaya BDD
Apa yang harus dilakukan Tes pemrograman dalam gaya deklaratif memungkinkan pengguna untuk segera memahami esensi tanpa menghabiskan siklus prosesor otak tunggal. Ketika Anda menulis kode imperatif yang dikemas dalam logika kondisional, pembaca harus berusaha keras. Dari sudut pandang ini, Anda perlu menggambarkan harapan dalam bahasa mirip manusia dalam gaya BDD deklaratif menggunakan ekspektasi / seharusnya dan tidak menggunakan kode khusus. Jika di Chai dan Jest tidak ada pernyataan yang perlu, yang sering diulang, maka Anda dapat
memperluas Matcher Jest atau menulis
plugin Anda sendiri untuk Chai .
Jika tidak. Tim akan menulis lebih sedikit tes dan menghias tes yang mengganggu
with .skip()
.
Contoh kodeContoh menggunakan Mocha .
Contoh dari antipattern. Untuk memahami esensi dari tes ini, pengguna dipaksa untuk melewati kode imperatif yang agak panjang.
it("When asking for an admin, ensure only ordered admins in results" , ()={
Bagaimana cara melakukannya dengan benar. Membaca tes deklaratif ini sangat mudah.
it("When asking for an admin, ensure only ordered admins in results" , ()={
1.4 Patuhi pengujian kotak hitam: uji hanya metode publik
Apa yang harus dilakukan Menguji bagian dalam akan menyebabkan overhead besar dan hampir tidak akan menghasilkan apa-apa. Jika kode atau API Anda memberikan hasil yang benar, apakah layak untuk menghabiskan tiga jam pengujian BAGAIMANA itu bekerja secara internal dan kemudian mendukung tes rapuh ini? Ketika Anda memeriksa perilaku publik, Anda secara bersamaan secara implisit memeriksa implementasi itu sendiri, pengujian Anda akan gagal hanya jika ada masalah tertentu (misalnya, output yang salah). Pendekatan ini juga disebut pengujian perilaku. Di sisi lain, jika Anda menguji internal (metode "kotak putih"), maka alih-alih merencanakan output komponen, Anda akan fokus pada detail kecil, dan tes Anda mungkin rusak karena perubahan kecil pada kode, bahkan jika hasilnya baik-baik saja, tetapi pengawalan akan membutuhkan lebih banyak sumber daya.
Jika tidak. Tes Anda akan berperilaku seperti
anak laki -
laki yang berteriak "Serigala!" : Dengan keras melaporkan positif palsu (misalnya, tes gagal karena perubahan nama variabel pribadi). Tidak mengherankan bahwa segera orang akan mulai mengabaikan pemberitahuan CI, dan suatu hari mereka akan kehilangan bug yang sebenarnya ...
Contoh kodeContoh dari antipattern. menguji bagian dalam tanpa alasan yang bagus.
Contoh menggunakan Mocha .
class ProductService{
1.5 Pilih implementasi simulasi yang tepat: hindari benda palsu yang mendukung stub dan mata-mata
Apa yang harus dilakukan Implementasi yang disimulasikan (tes ganda) adalah kejahatan yang diperlukan karena mereka terkait dengan internal aplikasi, dan beberapa bernilai tinggi (
menyegarkan memori implementasi yang ditiru: benda palsu (tiruan), bertopik (bertopik), dan objek mata-mata (mata-mata) ) Namun, tidak semua teknik itu setara. Mata-mata dan bertopik dirancang untuk menguji persyaratan, tetapi memiliki efek samping yang tak terhindarkan - mereka juga sedikit mempengaruhi bagian dalam. Dan benda-benda palsu dirancang untuk menguji bagian dalam, yang mengarah ke overhead besar, seperti yang dijelaskan dalam bab 1.4.
Sebelum menggunakan implementasi simulasi, tanyakan pada diri sendiri pertanyaan paling sederhana: "Apakah saya menggunakan ini untuk menguji fungsionalitas yang telah muncul atau mungkin muncul dalam dokumentasi dengan persyaratan?" Jika tidak, itu menampar pengujian kotak putih.
Misalnya, jika Anda ingin mengetahui apakah aplikasi berperilaku sebagaimana mestinya ketika layanan pembayaran tidak tersedia, Anda dapat membuat tulisan rintisan dan mengembalikan "Tidak ada jawaban" untuk memeriksa apakah modul yang diuji mengembalikan nilai yang benar. Jadi, Anda dapat memeriksa perilaku / respons / keluaran aplikasi dalam skenario tertentu. Anda juga dapat mengkonfirmasi dengan bantuan mata-mata bahwa ketika layanan tidak tersedia, surat itu dikirim, itu juga pengujian perilaku, yang lebih baik tercermin dalam dokumentasi dengan persyaratan ("Kirim surat jika informasi pembayaran tidak dapat disimpan"). Pada saat yang sama, jika Anda membuat layanan pembayaran palsu dan memastikan bahwa itu disebut menggunakan tipe JS yang benar, maka pengujian Anda ditujukan untuk internal yang tidak terkait dengan fungsi aplikasi dan yang cenderung sering berubah.
Jika tidak. Setiap refactoring kode melibatkan menemukan dan memperbarui semua objek palsu dalam kode. Tes dari asisten teman berubah menjadi beban.
Contoh kodeContoh dari antipattern. Benda palsu adalah untuk nyali.
Contoh menggunakan Sinon .
it("When a valid product is about to be deleted, ensure data access DAL was called once, with the right product and right config", async () => {
Bagaimana cara melakukannya dengan benar. Mata-mata dirancang untuk menguji persyaratan, tetapi ada efek samping - mereka pasti mempengaruhi bagian dalam.
it("When a valid product is about to be deleted, ensure an email is sent", async () => {
1.6 Jangan menggunakan "foo", gunakan input realistis
Apa yang harus dilakukan Seringkali bug produksi terjadi dengan data input yang sangat spesifik dan mengejutkan. Semakin realistis data selama pengujian, semakin besar kemungkinan untuk menangkap bug tepat waktu. Untuk menghasilkan data pseudo-nyata yang mensimulasikan variasi dan jenis data produksi, gunakan perpustakaan khusus, misalnya,
Faker . Perpustakaan semacam itu dapat menghasilkan nomor telepon yang realistis, nama panggilan pengguna, kartu bank, nama perusahaan, bahkan teks "lorem ipsum". Anda dapat membuat tes (di atas unit test, dan bukan sebaliknya) yang mengacak data palsu agar sesuai dengan modul ke dalam tes, atau bahkan mengimpor data nyata dari lingkungan produksi. Ingin melangkah lebih jauh? Baca bab berikutnya (tentang pengujian berbasis properti).
Jika tidak. Pengujian pengembangan Anda akan terlihat berhasil menggunakan input sintetik seperti "Foo", dan data produksi mungkin macet ketika peretas
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
garis rumit seperti
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
.
Contoh kodeContoh dari antipattern. Rangkaian uji yang berhasil dijalankan karena penggunaan data yang tidak realistis.
Contoh menggunakan Jest .
const addProduct = (name, price) =>{ const productNameRegexNoSpace = /^\S*$/;
Bagaimana cara melakukannya dengan benar. Acak input realistis.
it("Better: When adding new valid product, get successful confirmation", async () => { const addProductResult = addProduct(faker.commerce.productName(), faker.random.number());
1.7 Gunakan pengujian berbasis properti untuk memvalidasi beberapa kombinasi input
Apa yang harus dilakukan Biasanya untuk setiap tes kami memilih beberapa sampel data input. Bahkan jika format input mirip dengan data nyata (lihat bab “Jangan gunakan“ foo ”), kami hanya mencakup beberapa kombinasi data input (metode
('', true, 1)
, metode
("string" , false" , 0)
Tetapi dalam operasi, API yang disebut dengan lima parameter dapat dipanggil dengan ribuan kombinasi yang berbeda, salah satunya dapat menyebabkan proses
crash (
fuzzing ). Bagaimana jika Anda dapat menulis satu tes yang secara otomatis mengirim 1000 kombinasi data input dan memperbaiki, pada kombinasi apa kode tidak mengembalikan jawaban yang benar? Hal yang sama kita lakukan dengan m todike tes berdasarkan sifat: dengan mengirimkan semua kemungkinan kombinasi dari input data ke dalam unit uji kami meningkatkan kesempatan deteksi bug, misalnya, kita memiliki metode.
addNewProduct(id, name, isDiscount)
Mendukung perpustakaan akan memanggil metode ini dengan sejumlah kombinasi.
(, , )
, misalnya,
(1, "iPhone", false)
,
(2, "Galaxy", true)
, dll. Anda dapat menguji berdasarkan properti menggunakan pelari uji favorit Anda (Mocha, Jest dll) dan perpustakaan seperti
js-verifikasi atau
testcheck (ini memiliki dokumentasi yang jauh lebih baik). Anda juga dapat
mencoba perpustakaan periksa cepat , yang menawarkan fitur-fitur tambahan dan secara aktif disertai oleh penulis.
Jika tidak. Anda tanpa berpikir memilih data input untuk pengujian, yang hanya mencakup jalur eksekusi kode yang berfungsi dengan baik. Sayangnya, ini mengurangi efektivitas pengujian sebagai cara mendeteksi kesalahan.
Contoh kodeBagaimana cara melakukannya dengan benar. Uji banyak kombinasi dengan uji mocha.
require('mocha-testcheck').install(); const {expect} = require('chai'); const faker = require('faker'); describe('Product service', () => { describe('Adding new', () => {
1.8 Jika perlu, gunakan hanya pemotretan singkat dan inline.
Apa yang harus dilakukan Ketika Anda perlu
menguji berdasarkan snapshot , gunakan snapshot pendek tanpa semua tambahan (misalnya, dalam 3-7 baris), termasuk sebagai bagian dari pengujian (
Inline Snapshot ), dan bukan sebagai file eksternal. Mengikuti rekomendasi ini akan membuat tes Anda jelas dan lebih dapat diandalkan.
Di sisi lain, panduan dan alat "snapshot klasik" memprovokasi kami untuk menyimpan file besar (misalnya, markup untuk rendering komponen atau hasil JSON API) di media eksternal dan membandingkan hasilnya dengan versi yang disimpan setiap kali tes dijalankan. Itu bisa, katakanlah, secara implisit mengaitkan pengujian kami dengan 1000 baris yang berisi 3.000 nilai yang tidak pernah dilihat oleh penulis tes yang tidak diharapkannya. Kenapa ini buruk? Karena ada 1000 alasan mengapa tes gagal. Bahkan satu baris dapat membatalkan snapshot, dan ini bisa sering terjadi. Berapa banyak Setelah setiap ruang, komentar, atau perubahan kecil dalam CSS atau HTML. Selain itu, nama tes tidak akan memberi tahu Anda tentang kegagalan, karena hanya memeriksa bahwa 1000 baris tidak berubah, dan juga mendorong penulis tes untuk mengambil selama yang diinginkan dokumen panjang yang ia tidak bisa menganalisis dan memverifikasi. Semua ini adalah gejala dari tes yang tidak jelas dan tergesa-gesa yang tidak memiliki tugas yang jelas dan berusaha untuk mencapai terlalu banyak.
Perlu dicatat bahwa ada beberapa situasi di mana dapat diterima untuk menggunakan gambar panjang dan eksternal, misalnya, ketika mengkonfirmasi skema, dan bukan data (mengekstraksi nilai dan fokus pada bidang), atau ketika dokumen yang diterima jarang berubah.
Jika tidak. Tes UI gagal. Kode terlihat baik, piksel ideal ditampilkan di layar, jadi apa yang terjadi? Pengujian Anda dengan snapshot baru saja mengungkapkan perbedaan antara dokumen asli dan yang baru diterima - karakter spasi ditambahkan ke markup ...
Contoh kodeContoh dari antipattern. Mengaitkan tes dengan beberapa 2000 baris kode yang tidak diketahui.
it('TestJavaScript.com is renderd correctly', () => {
Bagaimana cara melakukannya dengan benar. Harapan terlihat dan menjadi sorotan.
it('When visiting TestJavaScript.com home page, a menu is displayed', () => {
1.9 Hindari bangku tes global dan data awal, tambahkan data ke setiap tes secara terpisah
Apa yang harus dilakukan Menurut aturan emas (bab 0), setiap tes harus menambah dan bekerja dalam rangkaian barisnya sendiri dalam database untuk menghindari binding, dan lebih mudah bagi pengguna untuk memahami tes. Pada kenyataannya, penguji sering melanggar aturan ini, sebelum menjalankan tes mengisi database dengan data awal (biji) (
juga disebut "bangku tes" ) untuk meningkatkan produktivitas. , (. « »), . . , , (, ).
. , , , ? , , , .
. - .
before(() => {
. , .
it("When updating site name, get successful confirmation", async () => {
1.10 ,
. , - , try-catch-finally , . ( ), .
Chai:
expect(method).to.throw
( Jest:
expect(method).toThrow()
). , , . , , .
. (, CI-) , .
. , try-catch .
/it("When no product name, it throws error 400", async() => { let errorWeExceptFor = null; try { const result = await addNewProduct({name:'nest'});} catch (error) { expect(error.code).to.equal('InvalidInput'); errorWeExceptFor = error; } expect(errorWeExceptFor).not.to.be.null;
. , , , QA .
it.only("When no product name, it throws error 400", async() => { expect(addNewProduct)).to.eventually.throw(AppError).with.property('code', "InvalidInput"); });
1.11
. :
- smoke-,
- IO-less,
- , , ,
- , pull request', .
, , , #cold #api #sanity. . , Mocha :
mocha — grep 'sanity'
.
. , , , , , , , .
. '#cold-test' (Cold=== , - , ).
1.12
. , Node.js . , Node.
TDD . , , , .
-- , - . , , . , . , , , , (, ..).
. , .
2:
️2.1 :
. 10 , . . , 10 (, , ), , ,
? ?
: 2019- , TDD , , , . , , ,
. IoT-, Kafka RabbitMQ, , - . , , ? (, , ), , - .
( ) , , (« API, , !» (consumer-driven contracts)). , : , , , .
: TDD - . TDD , . , .
. ROI, Fuzz, , 10 .
. Cindy Sridharan 'Testing Microservices — the sane way'

Contoh:
2.2
. , . , . , , ? — . : TDD-, .
«», API, , (, , in-memory ), , , . , , « », .
. , , 20 %.
. Express API ( ).

2.3 , API
. , ( ). - , ! — , , . «
-22 » : , , .
(consumer-driven contracts) PACT : , … ! PACT — «», . PACT- — . , API CI, .
. — .
.
2.4
. , Express-. . , , , JS- {req,res}. , (,
Sinon ) {req,res}, , .
node-mock-http {req,res} . , , HTTP-, res- (. ).
. Express- === .
2.5
. . CI- , . (, ), (, ), .
Sonarqube (2600+
)
Code Climate (1500+
). ::
Keith Holliday. , .
. CodeClimate, :

2.6 , Node
. , . ( ) . , - , ? ? , API 50 % ? , Netflix - (
Chaos Engineering ). : , . , Netflix,
chaos monkey , , , , - ( Kubernetes
kube-monkey , ). , . , , Node- , , v8 1,7 , UX , ?
node-chaos (-), , Node.
. , production .
. Node-chaos , Node.js, .

2.7 ,
. ( 0), , , . , (seeds) (
« » ) . , (. « »), , . . , , (, ).
. , , , ? , , , .
. - .
before(() => {
. , .
it("When updating site name, get successful confirmation", async () => {
3:
3.1. UI
. , , , . , , ( HTML CSS) . , (, , , ), , , .
. 10 , 500 (100 = 1 ) - - .
. .
test('When users-list is flagged to show only VIP, should display only VIP members', () => {
. UI . test('When flagging to show only VIP, should display only VIP members', () => {
3.2 HTML- ,
. HTML- , . , , CSS-. , 'test-id-submit-button'. . , , .
. , , . — , , Ajax . . , CSS 'thick-border' 'thin-border'
. , .
. CSS-.
<!-- the markup code (part of React component) --> <span id="metric" className="d-flex-column">{value}</span> <!-- what if the designer changes the classs? -->
3.3
. , , . , , . , — - , (.
« » ). (, ) , .
, : , . ( ) . , .
. , . ?
. .
class Calendar extends React.Component { static defaultProps = {showFilters: false} render() { return ( <div> A filters panel with a button to hide/show filters <FiltersPanel showFilter={showFilters} title='Choose Filters'/> </div> ) } } //Examples use React & Enzyme test('Realistic approach: When clicked to show filters, filters are displayed', () => { // Arrange const wrapper = mount(<Calendar showFilters={false} />) // Act wrapper.find('button').simulate('click'); // Assert expect(wrapper.text().includes('Choose Filter')); // This is how the user will approach this element: by text })
. .
test('Shallow/mocked approach: When clicked to show filters, filters are displayed', () => {
3.4 .
. (, ). (,
setTimeOut
) , . (,
Cypress cy.request('url') ), API,
wait(expect(element)) @testing-library/DOM . , API, , . , ,
hurry-up the clock . — , , ( ). , , - npm- , ,
wait-for-expect .
. , . , . .
. E2E API (Cypress).
. , DOM- (@testing-library/dom).
. .
test('movie title appears', async () => {
3.5.
. - , . , , . :
pingdom , AWS CloudWatch
gcp StackDriver , , SLA. , , (,
lighthouse ,
pagespeed ), . — , :
,
(TTI) . , , , , , DOM, SSL . , CI, 247 CDN.
. , , , , - CDN.
. Lighthouse .

3.6 API
. ( 2), , , ( ). API (,
Sinon ,
Test doubles ), API. . API , ( ). API, . , , API . , : .
. , API 100 , 20 .
3.7 ,
. E2E (end-to-end, ) UI (. 3.6). , , . , , - . , — (, ), . - , , UI-
Cypress Pupeteer . , : 50 , , . 10 . , , , — . , .
. UI , , ( , UI) .
3.8
. , API , , . (before-all), - . , : . , . - API- . , . (, ), , , . , : , API (. 3.6).
. , 200 , 100 , 20 .
. (before-all), (before-each) (, Cypress).
Cypress .
let authenticationToken;
3.9 smoke-,
. production- , , . , , , , . smoke- . production, , , . , smoke- , .
. , , production . /Payment.
. Smoke- .
it('When doing smoke testing over all page, should load them all successfully', () => {
3.10
. , . «» , , , , . , ( ) , , -, , , . « », .
. ,
Cucumber JavaScript .
StoryBook UI- , (, , , ..) , . , , .
. , .
. cucumber-js.
. Storybook , .

3.11
. , . , . , . , - . , . , , , . , - . UI « ». , (,
wraith , PhantomCSS), . (,
Applitools ,
Perci.io ) , , « » (, ), DOM/CSS, .
. , ( ) , ?
. : , .

. wraith UI.
# Add as many domains as necessary. Key will act as a label domains: english: "http://www.mysite.com" # Type screen widths below, here are a couple of examples screen_widths: - 600 - 768 - 1024 - 1280 # Type page URL paths below, here are a couple of examples paths: about: path: /about selector: '.about' subscribe: selector: '.subscribe' path: /subscribe
4:
4.1 (~80 %),
. — , . , . — (, ), . ? , 10-30 % . 100 % , . . , : Airbus, ; , 50 % . , , 80 % (
Fowler: «in the upper 80s or 90s» ), , , .
: (CI), (
Jest ) , . , . , ( ) — . , — , , . , .
. . , , . .
.
. ( Jest).

4.2 ,
. , . , , , , . , , - , .
PricingCalculator
, , , 10 000 … , , . , . 80- , . : , , , . , - .
. , , , .
. ? , QA . : , - . , - API .

4.3
. : 100 %, . Bagaimana bisa begitu? , , , . . - : , , , .
, . JavaScript-
Stryker :
- « ». ,
newOrder.price===0
newOrder.price!=0
. «» .
- , , : , . , , .
, , , .
. , 85- 85 % .
. 100 %, 0 %.
function addNewOrder(newOrder) { logger.log(`Adding new order ${newOrder}`); DB.save(newOrder); Mailer.sendMail(newOrder.assignee, `A new order was places ${newOrder}`); return {approved: true}; } it("Test addNewOrder, don't use such test names", () => { addNewOrder({asignee: "John@mailer.com",price: 120}); });
. Stryker reports, , ().

4.4 -
. ESLint. ,
eslint-plugin-mocha , (
describe()
),
, .
eslint-plugin-jest , ( ).
. 90- , , , . , .
. , , .
describe("Too short description", () => { const userToken = userService.getDefaultToken()
5: CI
5.1 ,
. — . , . , ( !). , . (
ESLint standard Airbnb ), . ,
eslint-plugin-chai-expect , .
Eslint-plugin-promise ( ).
Eslint-plugin-security , DOS-.
eslint-plugin-you-dont-need-lodash-underscore , , V8, ,
Lodash._map(…)
.
. , , . Apa yang sedang terjadi , , . . , , .
. , . , ESLint production-.

5.2
. CI , , ..? ,
. Mengapa : (1) -> (2) -> (3) . , , .
, , , , - .
CI- ( ,
CircleCI local CLI ) . ,
wallaby , ( ) . npm- package.json, , (, , , ). (non-zero exit code)
concurrently . — ,
npm run quality
. githook (
husky ).
. , .
. Npm-, , , .
"scripts": { "inspect:sanity-testing": "mocha **/**--test.js --grep \"sanity\"", "inspect:lint": "eslint .", "inspect:vulnerabilities": "npm audit", "inspect:license": "license-checker --failOn GPLv2", "inspect:complexity": "plato .", "inspect:all": "concurrently -c \"bgBlue.bold,bgMagenta.bold,yellow\" \"npm:inspect:quick-testing\" \"npm:inspect:lint\" \"npm:inspect:vulnerabilities\" \"npm:inspect:license\"" }, "husky": { "hooks": { "precommit": "npm run inspect:all", "prepush": "npm run inspect:all" } }
5.3 production-
. — CI-. . —
Docker-compose . (, ) production-.
AWS Local AWS-.
, serverless
AWS SAM Faas-.
Kubernetes CI-, . , « Kubernetes»
Minikube MicroK8s , , . « Kubernetes»: CI- (,
Codefresh ) Kubernetes-, CI- ; .
. .
: CI-, Kubernetes-
(Dynamic-environments Kubernetes )
deploy: stage: deploy image: registry.gitlab.com/gitlab-examples/kubernetes-deploy script: - ./configureCluster.sh $KUBE_CA_PEM_FILE $KUBE_URL $KUBE_TOKEN - kubectl create ns $NAMESPACE - kubectl create secret -n $NAMESPACE docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_REGISTRY_USER" --docker-password="$CI_REGISTRY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" - mkdir .generated - echo "$CI_BUILD_REF_NAME-$CI_BUILD_REF" - sed -e "s/TAG/$CI_BUILD_REF_NAME-$CI_BUILD_REF/g" templates/deals.yaml | tee ".generated/deals.yaml" - kubectl apply --namespace $NAMESPACE -f .generated/deals.yaml - kubectl apply --namespace $NAMESPACE -f templates/my-sock-shop.yaml environment: name: test-for-ci
5.4
. , , . , 500 , , . , CI- (
Jest ,
AVA Mocha ) , . CI- (!), . , CLI , , .
. — , .
5.5
. , . 10 ? CI- npm-
license check plagiarism check ( ), , , Stackoveflow .
. , , .
.

5.6
. , Express, .
npm audit ,
snyk ( ). CI .
. . .
: NPM Audit

5.7
. package-lock.json Yarn npm ( ): .
npm install
npm update
, . , — . , package.json
ncu .
, . :
- CI , , npm outdated npm-check-updates (ncu). .
- , pull request' .
: ? , ( ,
eslint-scope ). « »:
latest , , (, 1.3.1, — 1.3.8).
. , .
5.8 CI-, Node
. , Node . , Node.
- . , Jenkins .
- Docker.
- , . . smoke-, (, , ) .
- , , , , , .
- , . , -. - ( ).
- . .
- , , .
- (, Docker-).
- , .
node_modules
.
. , .
5.9 : CI-, Node
. , , . Node, CI . , MySQL, Postgres. CI- «», MySQl, Postgres Node. , - (, ). CI, , .
. - ?
: Travis ( CI) Node.
language: node_js node_js: - "7" - "6" - "5" - "4" install: - npm install script: - npm run test