paint-brush
Жасмин: руководство для начинающих по чистым функциям и базовым тестамк@marcinwosinek
200 чтения

Жасмин: руководство для начинающих по чистым функциям и базовым тестам

к Marcin Wosinek6m2024/02/11
Read on Terminal Reader

Слишком долго; Читать

Чистые функции — идеальный случай для модульного тестирования. Для данного входного сигнала мы всегда ожидаем одного и того же результата — никакого внутреннего состояния при этом не требуется. Давайте рассмотрим несколько примеров и несколько простых тестов, которые проверяют, работают ли методы должным образом.
featured image - Жасмин: руководство для начинающих по чистым функциям и базовым тестам
Marcin Wosinek HackerNoon profile picture

Чистые функции — идеальный случай для модульного тестирования. Для данного входного сигнала мы всегда ожидаем одного и того же результата — никакого внутреннего состояния при этом не требуется. Давайте рассмотрим несколько примеров и несколько простых тестов, которые проверяют, работают ли методы должным образом.

Жасмин

Jasmine — это среда модульного тестирования для JavaScript. Он может запускать тесты как в Node.js, так и в браузере. Он используется в среде Angular и особенно популярен в проектах на его основе. Это хороший выбор для проектов Vanilla JS, а также проектов, основанных на других платформах.

Тестирование счастливого пути

Тестирование счастливого пути — это когда мы тестируем метод с входными данными, которые, как ожидается, будут работать нормально. Аргументы действительны и находятся в разумных пределах. Эти тесты проверяют, правильно ли метод выполняет свою работу — тестовые примеры должны быть простыми примерами того, как метод объясняется в его документации.


Примеры псевдокодов:

  • expect(add(2, 2)).toBe(4) ,


  • expect(concatenate(“Lorem”, “Ipsum”)).toBe(“LoremIpsum”)


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

Методы

Давайте рассмотрим несколько простых методов: простые операции, которые могут нам понадобиться в некоторых реальных приложениях.


Все реализации сильно упрощены — все методы будут некрасиво ломаться, если только мы предоставим им параметры, немного отличающиеся от ожидаемых. Код далек от надежности.

приветствовать

Метод, который приветствует пользователя именем и фамилией:

 export function greet(name, surname) { return `Hello ${name} ${surname}!`; }

короткая дата

shortDate — это метод форматирования, который принимает объект даты и возвращает его в виде короткой строки. Код:

 export function shortDate(date) { return date.toISOString().substring(0, 10); }

многоточие

ellipsis принимает длинную текстовую строку и необязательный параметр длины, а затем обрезает строку, чтобы она соответствовала пределу:

 export function ellipsis(text, length = 50) { if (text.length > length) { return text.substring(0, length) + "…"; } return text; }

переводить

Метод, который предоставляет переведенные строковые значения для пары key и lang . Это упрощенная реализация того, что можно заменить более продвинутыми библиотеками перевода.

 export function translate(key, lang = "en") { switch (lang) { case "en": switch (key) { case "hello": return "Hello!"; } case "pl": switch (key) { case "hello": return "Cześć!"; } } }

применитьскидку

Метод применения процентной скидки к цене. Такая наивная реализация может показаться излишним, но позже, когда мы начнем исследовать крайние случаи, все станет намного интереснее.

 export function applyDiscount(price, discountPercentage) { return price - (price * discountPercentage) / 100; }

рассчитать цену

Он рассчитывает общую цену при покупке нескольких единиц по заданной цене. Это также усложнится после добавления интересных крайних случаев.

 export function calculatePrice(unitPrice, quantity) { return unitPrice * quantity; }

Полный JS-код

Полный код JS, src/main.js :

 export function greet(name, surname) { return `Hello ${name} ${surname}!`; } export function shortDate(date) { return date.toISOString().substring(0, 10); } export function ellipsis(text, length = 50) { if (text.length > length) { return text.substring(0, length) + "…"; } return text; } export function translate(key, lang = "en") { switch (lang) { case "en": switch (key) { case "hello": return "Hello!"; } case "pl": switch (key) { case "hello": return "Cześć!"; } } } export function applyDiscount(price, discountPercentage) { return price - (price * discountPercentage) / 100; } export function calculatePrice(unitPrice, quantity) { return unitPrice * quantity; }

Добавление жасминовых тестов

Чтобы добавить Jasmine, начнем с преобразования папки в пакет npm:

 $ npm init -y Wrote to …/package.json: …


Затем мы можем установить пакет Jasmine:

 $ npm install --save-dev jasmine added 42 packages, and audited 43 packages in 2s 13 packages are looking for funding run `npm fund` for details found 0 vulnerabilities


Затем мы можем генерировать папки и файлы, используемые Jasmine:

 $ npx jasmine init (no output)


Эта команда генерирует следующее:

  • spec/ — папка, в которую мы можем поместить файлы *.spec.js с тестом, и


  • spec/support/jasmine.json — файл с конфигом Jasmine.

Модульные тесты

В следующих модульных тестах я концентрируюсь только на счастливом пути — я проверяю, соответствует ли результат ожидаемому для разумных входных данных. Тест не требует пояснений, поэтому давайте взглянем на них:

 import { greet, shortDate, ellipsis, translate, applyDiscount, calculatePrice, } from "../src/main.js"; describe("main", () => { describe("greet", () => { it("should greet by name and surname", () => { expect(greet("Lorem", "Ipsum")).toEqual("Hello Lorem Ipsum!"); }); }); describe("shortDate", () => { it("should format correclty date", () => { const date = new Date("2023-11-02"); expect(shortDate(date)).toEqual("2023-11-02"); }); }); describe("shortDate", () => { it("should shorten long text at 50 chars", () => { expect( ellipsis( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a faucibus massa." ) ).toEqual("Lorem ipsum dolor sit amet, consectetur adipiscing…"); }); it("should leave short text unchanged", () => { expect(ellipsis("Lorem ipsum sin dolor")).toEqual( "Lorem ipsum sin dolor" ); }); it("should shorten to custom length", () => { expect(ellipsis("Lorem ipsum sin dolor", 10)).toEqual("Lorem ipsu…"); }); }); describe("translate", () => { it("should translate to supported langauges", () => { expect(translate("hello", "en")).toEqual("Hello!"); expect(translate("hello", "pl")).toEqual("Cześć!"); }); }); describe("applyDiscount", () => { it("should lower the price accordingly", () => { expect(applyDiscount(120, 25)).toEqual(90); expect(applyDiscount(8, 50)).toEqual(4); }); }); describe("calculatePrice", () => { it("should find a price of many products", () => { expect(calculatePrice(4, 3)).toEqual(12); expect(calculatePrice(9, 0.5)).toEqual(4.5); }); }); });

( spec/main.spec.js )

Запуск тестов

Чтобы запустить тесты, мы можем добавить в package.json следующий скрипт:

 .. "scripts": { "test": "jasmine" }, …


После этого npm run test запускает наши тесты:

 $ npm run test > [email protected] test > jasmine Randomized with seed 76873 Started ........ 8 specs, 0 failures Finished in 0.004 seconds Randomized with seed 76873 (jasmine --random=true --seed=76873)

Краткое содержание

В этом посте мы рассмотрели простой пример JS-кода и то, как его можно охватить с помощью модульных тестов. Полный пример кода вы можете найти на GitHub .


Также опубликовано здесь