JavaScript Unit Testavimas

Naudojant Jest testing karkasą

Kodėl reikia testavimo ?

Vienetų testavimas (Unit Testing) yra labai svarbus programinės įrangos kūrimo procese dėl kelių pagrindinių priežasčių:

  • Klaidos aptikimas ankstyvame etape
  • Lengvesnis kodo keitimas ir refaktorinimas
  • Dokumentacija
  • Greitas grįžtamasis ryšys
     

Vienetų testavimas yra esminis siekiant kokybiško, patikimo ir lengvai palaikomo kodo. Jis padeda greitai aptikti klaidas, saugiai refaktorizuoti kodą, užtikrina gerą dokumentaciją ir modulinį dizainą bei suteikia greitą grįžtamąjį ryšį apie kodo būklę.

 

Kas yra Jest?

Jest yra populiari testavimo biblioteka, sukurta ir palaikoma „Facebook“. Ji daugiausia naudojama JavaScript ir React aplikacijų testavimui. Jest yra „all-in-one“ testavimo sprendimas, kuris apima testavimo platformą, mokinius (mocks), „assertions“ ir padeda rašyti patikimus ir našius testus.

 

Pagrindiniai Jest testų tipai

Vienetų testavimas (Unit Testing)

  • Testuoja atskirus modulius ar funkcijas izoliuotai nuo kitų kodo dalių.
  • Pavyzdžiui, testuojant funkciją, kuri sudeda du skaičius, tikrinama ar funkcija grąžina teisingą sumą.
// sum.js
function sum(a, b) {
    return a + b;
}
module.exports = sum;

// sum.test.js
const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).toBe(3);
});

Integracinis testavimas (Integration Testing)

  • Testuoja, kaip skirtingi programinės įrangos komponentai veikia kartu.
  • Pavyzdžiui, tikrinama, ar funkcija, skaitanti duomenis iš duomenų bazės ir apdorojanti juos, veikia teisingai.
// database.js
const fetchData = () => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve('data from database');
        }, 100);
    });
};

module.exports = fetchData;

// processData.js
const fetchData = require('./database');

async function processData() {
    const data = await fetchData();
    return `Processed: ${data}`;
}

module.exports = processData;

// processData.test.js
const processData = require('./processData');

test('process data from database', async () => {
    const result = await processData();
    expect(result).toBe('Processed: data from database');
});

Galutinio vartotojo testavimas (End-to-End Testing)

  • Testuoja visą sistemą nuo pradžios iki galo, siekiant užtikrinti, kad viskas veikia kartu kaip tikimasi.
  • Dažniausiai naudojamos specializuotos priemonės, tokios kaip „Cypress“ arba „Puppeteer“, bet Jest taip pat gali būti naudojamas kai kurioms E2E testavimo užduotims.
// using Puppeteer with Jest
const puppeteer = require('puppeteer');

test('should display "Hello World!" on page', async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('http://localhost:3000');
    const text = await page.$eval('h1', el => el.textContent);
    expect(text).toBe('Hello World!');
    await browser.close();
});

Kaip paleisti Jest testus

Įdiekite Jest:

npm install --save-dev jest

Sukonfigūruokite package.json:

{
    "scripts": {
        "test": "jest"
    }
}

Paleiskite testus:

npm test

Kitos Jest galimybės

  • Mock`ai (Mocking): Leidžia simuliuoti funkcijas ar modulius, siekiant izoliuoti testuojamą kodą.
  • Snapshot testavimas (Snapshot Testing): Leidžia išsaugoti komponentų vaizdą ir palyginti jį su būsimais vykdymo metu gautais rezultatais.
  • Coverage report`ai (Code Coverage): Generuoja ataskaitas apie tai, kiek kodo buvo patikrinta testais.
  • Naudojant Jest, galima efektyviai užtikrinti, kad kodas veiktų taip, kaip tikimasi, ir išvengti regresijos klaidų, įtraukiant vienetinius, integracinius ir galutinio vartotojo testus.

Rašome testą

test(string: ‘this is the description of the test’, () => {
    //This is your test method body
    .
    **some logic**
    .
    expect(actual).someMatcher(expected);
});

https://jestjs.io/docs/en/using-matchers
https://jestjs.io/docs/en/expect

Rašome testą

Testavimo tipai

  • BDD - Behavior-Driven Development
  • TDD - Test-Driven Development

React komponento testavimas

import { Link } from "react-router-dom"
const Nav = ()=>{
    return(
        <nav className="navbar navbar-expand-lg navbar-dark bg-dark">
        <div className="container px-lg-5">
            <a className="navbar-brand" href="#!">Demo projektas</a>
            <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span className="navbar-toggler-icon"></span></button>
            <div className="collapse navbar-collapse" id="navbarSupportedContent">
                <ul className="navbar-nav ms-auto mb-2 mb-lg-0">
                    <li className="nav-item"><Link className="nav-link" to="/">Pradinis</Link></li>
                    <li className="nav-item"><Link className="nav-link" to="/about">Apie</Link></li>
                </ul>
            </div>
        </div>
    </nav>
    )
}

export default Nav

Komponentas:

React komponento testavimas

// Nav.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { MemoryRouter } from 'react-router-dom';
import Nav from './Nav';

test('renders the Nav component with links', () => {
  // Render the component within a MemoryRouter
  render(
    <MemoryRouter>
      <Nav />
    </MemoryRouter>
  );

  // Check that the brand text is rendered
  expect(screen.getByText('Demo projektas')).toBeInTheDocument();

  // Check that the 'Pradinis' link is rendered
  expect(screen.getByText('Pradinis')).toBeInTheDocument();

  // Check that the 'Apie' link is rendered
  expect(screen.getByText('Apie')).toBeInTheDocument();
});

Testas:

Api serviso testavimas

// app.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello, World!');
});

app.get('/about', (req, res) => {
  res.send('About Page');
});

app.listen(port, () => {
  console.log(`App listening at http://localhost:${port}`);
});

module.exports = app;

Api servisas:

Api serviso testavimas

// app.test.js
const request = require('supertest');
const app = require('./app');

describe('GET /', () => {
  it('should return Hello, World!', async () => {
    const res = await request(app).get('/');
    expect(res.statusCode).toEqual(200);
    expect(res.text).toEqual('Hello, World!');
  });
});

describe('GET /about', () => {
  it('should return About Page', async () => {
    const res = await request(app).get('/about');
    expect(res.statusCode).toEqual(200);
    expect(res.text).toEqual('About Page');
  });
});

Testas: 

deck

By Martynas Kašelionis