From d38b654d8b8ce219bba794c68e12704511b79e9a Mon Sep 17 00:00:00 2001 From: Kohei Watanabe Date: Tue, 19 Dec 2023 16:50:59 +0900 Subject: [PATCH] create test --- package-lock.json | 38 +++++ package.json | 6 +- src/SUMMARY.md | 8 + src/issues.md | 3 + src/test/basic.md | 48 ++++++ src/test/getting-started.md | 111 ++++++++++++++ src/test/getting-started/hello.test.js | 7 + src/test/index.md | 19 +++ src/test/practices.md | 164 +++++++++++++++++++++ src/test/practices/isLeapYear.js | 6 + src/test/practices/step0.test.js | 8 + src/test/practices/step1.test.js | 19 +++ src/test/practices/step2.test.js | 23 +++ src/test/preparation.md | 17 +++ src/test/references.md | 34 +++++ src/test/writing-style.md | 15 ++ src/test/writing-style/aaa-pattern.test.js | 13 ++ templates/basic/main.js | 1 + templates/basic/notToBe.test.js | 6 + templates/basic/package.json | 11 ++ templates/basic/toBe.test.js | 6 + templates/basic/toEqual.test.js | 8 + templates/mock/main.js | 1 + templates/mock/mock.test.js | 14 ++ templates/mock/package.json | 11 ++ templates/promise/main.js | 1 + templates/promise/package.json | 11 ++ templates/promise/promise.test.js | 9 ++ templates/scope/main.js | 1 + templates/scope/package.json | 11 ++ templates/scope/scope.test.js | 34 +++++ templates/template/main.js | 1 + templates/template/package.json | 11 ++ templates/template/sum.js | 5 + templates/template/sum.test.js | 7 + 35 files changed, 687 insertions(+), 1 deletion(-) create mode 100644 src/issues.md create mode 100644 src/test/basic.md create mode 100644 src/test/getting-started.md create mode 100644 src/test/getting-started/hello.test.js create mode 100644 src/test/index.md create mode 100644 src/test/practices.md create mode 100644 src/test/practices/isLeapYear.js create mode 100644 src/test/practices/step0.test.js create mode 100644 src/test/practices/step1.test.js create mode 100644 src/test/practices/step2.test.js create mode 100644 src/test/preparation.md create mode 100644 src/test/references.md create mode 100644 src/test/writing-style.md create mode 100644 src/test/writing-style/aaa-pattern.test.js create mode 100644 templates/basic/main.js create mode 100644 templates/basic/notToBe.test.js create mode 100644 templates/basic/package.json create mode 100644 templates/basic/toBe.test.js create mode 100644 templates/basic/toEqual.test.js create mode 100644 templates/mock/main.js create mode 100644 templates/mock/mock.test.js create mode 100644 templates/mock/package.json create mode 100644 templates/promise/main.js create mode 100644 templates/promise/package.json create mode 100644 templates/promise/promise.test.js create mode 100644 templates/scope/main.js create mode 100644 templates/scope/package.json create mode 100644 templates/scope/scope.test.js create mode 100644 templates/template/main.js create mode 100644 templates/template/package.json create mode 100644 templates/template/sum.js create mode 100644 templates/template/sum.test.js diff --git a/package-lock.json b/package-lock.json index cbafaac..98d25a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "nodejs-hands-on", "version": "1.0.0", "license": "CC0-1.0", + "workspaces": [ + "templates/*" + ], "devDependencies": { "markdown-link-check": "^3.11.2", "prettier": "^3.0.0" @@ -19,6 +22,10 @@ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, + "node_modules/basic": { + "resolved": "templates/basic", + "link": true + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -326,6 +333,10 @@ "node": ">= 12" } }, + "node_modules/mock": { + "resolved": "templates/mock", + "link": true + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -409,6 +420,10 @@ "node": ">=0.4.0" } }, + "node_modules/promise": { + "resolved": "templates/promise", + "link": true + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -429,6 +444,29 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", "dev": true + }, + "node_modules/scope": { + "resolved": "templates/scope", + "link": true + }, + "node_modules/template": { + "resolved": "templates/template", + "link": true + }, + "templates/basic": { + "version": "1.0.0" + }, + "templates/mock": { + "version": "1.0.0" + }, + "templates/promise": { + "version": "1.0.0" + }, + "templates/scope": { + "version": "1.0.0" + }, + "templates/template": { + "version": "1.0.0" } } } diff --git a/package.json b/package.json index d4c7f0c..70893a7 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,13 @@ "private": true, "author": "Kohei Watanabe ", "license": "CC0-1.0", + "type": "module", + "workspaces": [ + "templates/*" + ], "scripts": { "prepare": "git config core.hooksPath .githooks", - "test": "find src -name '*.md' -exec markdown-link-check {} +", + "test": "find src -name '*.md' -exec markdown-link-check {} + && node --test src && npm test --workspaces", "format": "prettier --write ." }, "devDependencies": { diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 612ccad..8d37443 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -6,3 +6,11 @@ - [VSCodeのインストール](installing-vscode.md) - [VSCodeの拡張機能](vscode-extensions.md) - [VSCodeでのNode.jsのデバッグ](debugging-nodejs-in-vscode.md) +- [Test Runnerではじめるテスト](test/index.md) + - [事前準備](test/preparation.md) + - [はじめてのテスト](test/getting-started.md) + - [基本的な機能](test/basic.md) + - [テストの実践 ――「うるう年」問題](test/practices.md) + - [テストの作法](test/writing-style.md) + - [参考文献・動画](test/references.md) +- [質問・提案・問題の報告](issues.md) diff --git a/src/issues.md b/src/issues.md new file mode 100644 index 0000000..45e669c --- /dev/null +++ b/src/issues.md @@ -0,0 +1,3 @@ +# 質問・提案・問題の報告 + +もし何か気になることがあれば、[GitHub Issues](https://github.com/kou029w/nodejs-hands-on/issues/new) からお気軽にお寄せください。 diff --git a/src/test/basic.md b/src/test/basic.md new file mode 100644 index 0000000..5bb2350 --- /dev/null +++ b/src/test/basic.md @@ -0,0 +1,48 @@ +# 基本的な機能 + +Node.jsのテストランナーの機能について説明します。 + +## テストファイルの検出 + +デフォルトで下記のパターンに一致するすべてのファイルをテストファイルとして検出します[^running-tests-from-the-command-line]。 + +- `**/*.test.?(c|m)js` +- `**/*-test.?(c|m)js` +- `**/*_test.?(c|m)js` +- `**/test-*.?(c|m)js` +- `**/test.?(c|m)js` +- `**/test/**/*.?(c|m)js` + +[^running-tests-from-the-command-line]: + +## テストの自動監視 + +`--watch` オプションを指定することで、テストファイルの変更を自動で監視します。 + +``` +node --test --watch +``` + +終了するにはキーボードの `Ctrl` + `C``Ctrl`キーを押しながら`C` を押します。 + +## プロジェクトでのテストコマンドの設定 + +この設定を行うと、`npm test` コマンドでテストを実行できるようになります。 + +`package.json` の `scripts` プロパティの中を下記のように変更します。 + +```json +{ + "scripts": { + "test": "node --test" + } +} +``` + +NPMコマンドでのテストの実行: + +```bash +npm test +``` + +`node --test` コマンドの実行と同様のテスト結果が得られます。 diff --git a/src/test/getting-started.md b/src/test/getting-started.md new file mode 100644 index 0000000..dc4ba10 --- /dev/null +++ b/src/test/getting-started.md @@ -0,0 +1,111 @@ +# はじめてのテスト + +テストランナーは、`node --test` コマンドを使用することで実行できます。 + +```bash +node --test +``` + +しかし、まだテストが1件も存在しません。 + +```console +$ node --test +ℹ tests 0 +ℹ suites 0 +ℹ pass 0 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1.92388 +``` + +実際にテストを作成し、実行していきましょう。 + +## ECMAScriptモジュール + +ECMAScriptモジュール (ESM) とは、JavaScriptをモジュールとして再利用できるようにするための仕組みです。 + +Node.jsでESMを取り扱えるようにするためには `package.json` ファイルに `"type": "module"` プロパティを加えます。 + +```json +{ + "type": "module" +} +``` + +このように書き加えると、プロジェクトの `.js` ファイルはESMとして取り扱われます。 + +## テストファイルの作成 + +次のファイルを作成します。 + +```js +{{#include getting-started/hello.test.js}} +``` + +この作成した `hello.test.js` は、`node --test` コマンドを実行するときにテストとして実行されるようになります。 + +```console +$ node --test +✔ 1と2の合計は3です (0.546922ms) +ℹ tests 1 +ℹ suites 0 +ℹ pass 1 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 65.244086 +``` + +問題なく実行できましたか? + +``` +✔ 1と2の合計は3です (0.546922ms) +``` + +画面に表示されたこの部分は「テスト "1と2の合計は3です" が実行され、そのテストは合格しました ✅」ということを意味しています。 + +このようにしてNode.jsで簡単にテストを行うことができます。 + +## はじめてのテストのコードの説明 + +テストのコードについてより詳しく説明します。 + +はじめてのテストのコード: + +```js +{{#include getting-started/hello.test.js}} +``` + +このコードは、「1と2の合計は3です」というテストを意味します。 +式 `1 + 2` が、 `3` と等しいことを検証するテストです。 + +このコードでは下記の機能が使われています。 + +`test()` 関数 + +テストを宣言するための関数です。 + +- 第一引数には、このテストの説明を人間が読める形式で記述します +- 第二引数には、テストの本体を記述します + +`assert.strictEqual()` 関数 + +引数に与えた値を検証します。 + +`assert.strictEqual(<検査される値>, <期待する値>)` + +「検査される値」と「期待する値」の同一性を検証します。 + +最初の行は `import` 文によって `node:assert` と `node:test` を指定しています。 + +```js +{{#include getting-started/hello.test.js:2:3}} +``` + +これらがNode.jsのテストランナーの実行に必要となります。 + +このコードは基本的な機能を確認するための極めて単純なテストですが、テスト環境自体の検証を行うことでもあります。 +テスト環境の検証は、テストを行う上で最初に確認しておく重要なポイントです。 diff --git a/src/test/getting-started/hello.test.js b/src/test/getting-started/hello.test.js new file mode 100644 index 0000000..d3e3d1c --- /dev/null +++ b/src/test/getting-started/hello.test.js @@ -0,0 +1,7 @@ +// hello.test.js +import assert from "node:assert"; +import test from "node:test"; + +test("1と2の合計は3です", () => { + assert.strictEqual(1 + 2, 3); +}); diff --git a/src/test/index.md b/src/test/index.md new file mode 100644 index 0000000..75241e7 --- /dev/null +++ b/src/test/index.md @@ -0,0 +1,19 @@ +# Test Runnerではじめるテスト + +Node.jsに組み込まれた新しいテストランナーを使ってテストを行う入門ガイドです。 +Node.jsでどうやってテストするんだろう?という疑問に答えます。 +テストを行っていくための最初の一歩になればと思います。 + + + +それでは、さっそく学んでいきましょう! diff --git a/src/test/practices.md b/src/test/practices.md new file mode 100644 index 0000000..59ed138 --- /dev/null +++ b/src/test/practices.md @@ -0,0 +1,164 @@ +# テストの実践 ――「うるう年」問題 + +ここでは「うるう年」を判定するモジュールを作成します。 +「うるう年」の判定は、通常広く使われている `date-fns` などのNPMパッケージを使用することが多いですが、ここではテストを学ぶためにあえて自分で実装します。 +設計して、テストを書き、コードを書くという一連のステップでより実践的なテストとの付き合い方を学びましょう。 + +## ECMAScriptモジュール + +ECMAScriptモジュール (ESM) とは、JavaScriptをモジュールとして再利用できるようにするための仕組みです。 + +Node.jsでESMを取り扱えるようにするためには `package.json` ファイルに `"type": "module"` プロパティを加えます。 + +```json +{ + "type": "module" +} +``` + +このように書き加えると、プロジェクトの `.js` ファイルはESMとして取り扱われます。 + +## 目標の決定 + +まず「何を作るか」明らかにしましょう。 +何を作るか曖昧なまま、ただ無為にソフトウェア開発を進めるとムダを生む恐れがあります。 +ムダを生まないためにできるだけ「何を作るか」を明確にしておきましょう。 + +「うるう年」を判定するということは、「西暦年号がうるう年ならば true を返し、そうでなければ false を返す関数」ということと決めます。 + +「うるう年」とは何であるかは、ここでは日本の法令を参考にして決めます。 +日本の法令上の取り扱いは、明治時代に制定された「閏年ニ関スル件」によって決められています。 + +> 神武天皇即位紀元年数ノ四ヲ以テ整除シ得ヘキ年ヲ閏年トス但シ紀元年数ヨリ六百六十ヲ減シテ百ヲ以テ整除シ得ヘキモノノ中更ニ四ヲ以テ商ヲ整除シ得サル年ハ平年トス +> +> ―― [https://elaws.e-gov.go.jp/document?lawid=131IO0000000090](https://elaws.e-gov.go.jp/document?lawid=131IO0000000090) + +「神武天皇即位紀元」は、通常の西暦年号でいう紀元前660年を元年とした暦を意味します。したがって「紀元年数ヨリ六百六十ヲ減シテ」とあるのは通常の西暦年号を意味します。 +端的に言うと「グレゴリオ暦法に基づいています」ということを意味します。 +このままだと大変読みにくいですね。 +書き換えると下記のようになります。 + +> 西暦年号が4で割り切れる年はうるう年。ただし、西暦年号が100で割り切れる年のうち、100で割った商が4で割り切れない年はうるう年ではない。 + +これを「うるう年」とします。整理するとこうなります。 + +- 西暦年号が4で割り切れる年はうるう年 + - たとえば、西暦2024年、2028年、2032年は4で割り切れるので、うるう年です。 +- 西暦年号が4で割り切れない年はうるう年でない + - たとえば、西暦2021年、2022年、2023年は4で割り切れないので、うるう年ではありません。 +- ただし、西暦年号が100で割り切れる年はうるう年でない + - たとえば、西暦2100年、2200年、2300年は100で割り切れるので、うるう年ではありません。 +- ただし、西暦年号が400で割り切れる年はうるう年 + - たとえば、西暦2000年、2400年、2800年は400で割り切れるので、うるう年です。 + +これで「何を作るか」ということが明らかになりました。 +それでは、順番にテストとコードを書いていきましょう。 + +## 「西暦年号が4で割り切れる年はうるう年」 + +ファイル `isLeapYear.test.js` を作成します。 +「何を作るか」ということを忘れないようにコメントに転載します。 + +```js +// isLeapYear.test.js +/** TODO: +西暦年号が4で割り切れる年はうるう年 + たとえば、西暦2024年、2028年、2032年は4で割り切れるので、うるう年です。 +西暦年号が4で割り切れない年はうるう年でない + たとえば、西暦2021年、2022年、2023年は4で割り切れないので、うるう年ではありません。 +ただし、西暦年号が100で割り切れる年はうるう年でない + たとえば、西暦2100年、2200年、2300年は100で割り切れるので、うるう年ではありません。 +ただし、西暦年号が400で割り切れる年はうるう年 + たとえば、西暦2000年、2400年、2800年は400で割り切れるので、うるう年です。 +*/ +``` + +うるう年であることを判定するので `isLeapYear` という名前に決めました。 +この名前のモジュールと関数を作成することに決めます。 + +テストを書いていきましょう。 + +```js +{{#include practices/step0.test.js:1:3}} +{{#include practices/step0.test.js:5:}} +``` + +これをテストし、失敗することを確認します。 +この失敗は、テスト環境自体の検証を行うことでもあります。 + +NPMコマンドでのテストの実行: + +```bash +npm test +``` + +テストの自動監視: + +```bash +node --test --watch +``` + +テスト結果: + +```console +✖ 西暦年号が4で割り切れる年はうるう年 +``` + +失敗しますね。 +この失敗によって、次の2点を実証できました。 + +- 目標の「西暦年号が4で割り切れる年はうるう年」というテストが実行されること +- 未実装のコードが**意図せず合格しない ❌** ということ + +テスト環境の検証は、テストを行う上での重要なポイントです。 + +それでは、関数を実装していきましょう。 +最初からすべての実装を書こうとせず、小さい変更のみで済ませるのがポイントです。 + +```js +{{#include practices/isLeapYear.js}} +``` + +ファイルを作成したら、テスト側で `import` 文によって実装した関数を読み込みます。 + +```js +{{#include practices/step0.test.js}} +``` + +テストを実行します。 + +テスト結果: + +```console +✔ 西暦年号が4で割り切れる年はうるう年 +``` + +これでテストは合格 ✅ しました。 +念の為、西暦2024年のケースだけでなくほかのケースもテストしてみましょう。 + +「西暦年号が4で割り切れる年はうるう年」という目標を達成したと判断したら、コメントからは消しておきます。 + +```js +{{#include practices/step1.test.js}} +``` + +次の目標「西暦年号が4で割り切れない年はうるう年でない」に進めていきます。 + +テストを書き、実行します。 + +必要に応じて実装を修正します。 + +これらのテストも問題なく合格するようになれば、「西暦年号が4で割り切れない年はうるう年でない」という目標も達成したと判断して、コメントから消しておきます。 + +```js +{{#include practices/step2.test.js}} +``` + +## 続きの課題 + +残りの目標に関しても同様に進めていきましょう。 + +- ただし、西暦年号が100で割り切れる年はうるう年でない + - たとえば、西暦2100年、2200年、2300年は100で割り切れるので、うるう年ではありません。 +- ただし、西暦年号が400で割り切れる年はうるう年 + - たとえば、西暦2000年、2400年、2800年は400で割り切れるので、うるう年です。 diff --git a/src/test/practices/isLeapYear.js b/src/test/practices/isLeapYear.js new file mode 100644 index 0000000..8a1e686 --- /dev/null +++ b/src/test/practices/isLeapYear.js @@ -0,0 +1,6 @@ +// isLeapYear.js +function isLeapYear(year) { + return year % 4 === 0; +} + +export default isLeapYear; diff --git a/src/test/practices/step0.test.js b/src/test/practices/step0.test.js new file mode 100644 index 0000000..6fe59ea --- /dev/null +++ b/src/test/practices/step0.test.js @@ -0,0 +1,8 @@ +// isLeapYear.test.js +import assert from "node:assert"; +import test from "node:test"; +import isLeapYear from "./isLeapYear.js"; + +test("西暦年号が4で割り切れる年はうるう年", () => { + assert.strictEqual(isLeapYear(2024), true); +}); diff --git a/src/test/practices/step1.test.js b/src/test/practices/step1.test.js new file mode 100644 index 0000000..4cacd8d --- /dev/null +++ b/src/test/practices/step1.test.js @@ -0,0 +1,19 @@ +// isLeapYear.test.js +import assert from "node:assert"; +import test from "node:test"; +import isLeapYear from "./isLeapYear.js"; + +test("西暦年号が4で割り切れる年はうるう年", () => { + assert.strictEqual(isLeapYear(2024), true); + assert.strictEqual(isLeapYear(2028), true); + assert.strictEqual(isLeapYear(2032), true); +}); + +/** TODO: +西暦年号が4で割り切れない年はうるう年でない + たとえば、西暦2021年、2022年、2023年は4で割り切れないので、うるう年ではありません。 +ただし、西暦年号が100で割り切れる年はうるう年でない + たとえば、西暦2100年、2200年、2300年は100で割り切れるので、うるう年ではありません。 +ただし、西暦年号が400で割り切れる年はうるう年 + たとえば、西暦2000年、2400年、2800年は400で割り切れるので、うるう年です。 +*/ diff --git a/src/test/practices/step2.test.js b/src/test/practices/step2.test.js new file mode 100644 index 0000000..dd2ba51 --- /dev/null +++ b/src/test/practices/step2.test.js @@ -0,0 +1,23 @@ +// isLeapYear.test.js +import assert from "node:assert"; +import test from "node:test"; +import isLeapYear from "./isLeapYear.js"; + +test("西暦年号が4で割り切れる年はうるう年", () => { + assert.strictEqual(isLeapYear(2024), true); + assert.strictEqual(isLeapYear(2028), true); + assert.strictEqual(isLeapYear(2032), true); +}); + +test("西暦年号が4で割り切れない年はうるう年でない", () => { + assert.strictEqual(isLeapYear(2021), false); + assert.strictEqual(isLeapYear(2022), false); + assert.strictEqual(isLeapYear(2023), false); +}); + +/** TODO: +ただし、西暦年号が100で割り切れる年はうるう年でない + たとえば、西暦2100年、2200年、2300年は100で割り切れるので、うるう年ではありません。 +ただし、西暦年号が400で割り切れる年はうるう年 + たとえば、西暦2000年、2400年、2800年は400で割り切れるので、うるう年です。 +*/ diff --git a/src/test/preparation.md b/src/test/preparation.md new file mode 100644 index 0000000..460ec2b --- /dev/null +++ b/src/test/preparation.md @@ -0,0 +1,17 @@ +# 事前準備 + +あらかじめNode.jsの実行環境を構築してからはじめます。 + +## StackBlitzではじめる + +次のリンクにアクセスすると、StackBlitzで新しいNode.jsの実行環境を構築できます。 + +[![Edit on StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/fork/node?view=editor) + +StackBlitzではじめる場合は、以降の準備は不要です。 + +## ローカル環境ではじめる + +ローカル環境にNode.jsの実行環境を構築する場合、まずはじめにNode.jsをインストールします。 +インストール方法は[Node\.jsのインストール \- Node\.jsを使う](../installing-nodejs.md)をご参照ください。 +プロジェクトの作成方法は[package.jsonファイル - Node.jsを使う](../package-json.md)をご参照ください。 diff --git a/src/test/references.md b/src/test/references.md new file mode 100644 index 0000000..0b3d95d --- /dev/null +++ b/src/test/references.md @@ -0,0 +1,34 @@ +# 参考文献・動画 + +## Node.js + +- [Node.js 公式ドキュメント](https://nodejs.org/api/test.html) + +## テスト駆動開発 + + + +[和田卓人 (2010)「TDD のこころ」](https://www.slideshare.net/t_wada/the-spirit-of-tdd) + +[和田卓人 (2020)「TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング」](https://www.youtube.com/watch?v=Q-FJ3XmFlT8) + + + +[安井力 (2021)「『テスト自動化とテスト駆動開発』講演動画」](https://www.youtube.com/watch?v=vrbMKbdV6xY) diff --git a/src/test/writing-style.md b/src/test/writing-style.md new file mode 100644 index 0000000..532bb5c --- /dev/null +++ b/src/test/writing-style.md @@ -0,0 +1,15 @@ +# テストの作法 + +テストを書くときの代表的な作法を紹介します。 + +## Arrange・Act・Assert (AAA) パターン + +テストを書くときの作法の1つです。 +準備 (Arrange)・実行 (Act)・検証 (Assert) というプロセスで分けて書きます。 +準備・実行・検証をそれぞれ分けて書いておくことで比較的読みやすいテストを書くことができます。 + +例: + +```js +{{#include writing-style/aaa-pattern.test.js}} +``` diff --git a/src/test/writing-style/aaa-pattern.test.js b/src/test/writing-style/aaa-pattern.test.js new file mode 100644 index 0000000..ee2c8ef --- /dev/null +++ b/src/test/writing-style/aaa-pattern.test.js @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import test from "node:test"; + +test("正しくJSONをパースできる", () => { + // 準備 + const json = `{ "name": "Claude Monet", "birth": "1840" }`; + + // 実行 + const parsed = JSON.parse(json); + + // 検証 + assert.deepStrictEqual(parsed, { name: "Claude Monet", birth: "1840" }); +}); diff --git a/templates/basic/main.js b/templates/basic/main.js new file mode 100644 index 0000000..5b8781d --- /dev/null +++ b/templates/basic/main.js @@ -0,0 +1 @@ +// toBe.test.js, toEqual.test.js, notToBe.test.js をご参照ください diff --git a/templates/basic/notToBe.test.js b/templates/basic/notToBe.test.js new file mode 100644 index 0000000..a38d775 --- /dev/null +++ b/templates/basic/notToBe.test.js @@ -0,0 +1,6 @@ +import assert from "node:assert"; +import test from "node:test"; + +test("2と2の和は5ではない", () => { + assert.notStrictEqual(2 + 2, 5); +}); diff --git a/templates/basic/package.json b/templates/basic/package.json new file mode 100644 index 0000000..bcbeeb0 --- /dev/null +++ b/templates/basic/package.json @@ -0,0 +1,11 @@ +{ + "name": "basic", + "version": "1.0.0", + "private": true, + "main": "main.js", + "type": "module", + "scripts": { + "test": "node --test", + "watch": "node --test --watch" + } +} diff --git a/templates/basic/toBe.test.js b/templates/basic/toBe.test.js new file mode 100644 index 0000000..bee021d --- /dev/null +++ b/templates/basic/toBe.test.js @@ -0,0 +1,6 @@ +import assert from "node:assert"; +import test from "node:test"; + +test("2と2の和は4", () => { + assert.strictEqual(2 + 2, 4); +}); diff --git a/templates/basic/toEqual.test.js b/templates/basic/toEqual.test.js new file mode 100644 index 0000000..0eca6a7 --- /dev/null +++ b/templates/basic/toEqual.test.js @@ -0,0 +1,8 @@ +import assert from "node:assert"; +import test from "node:test"; + +test("Object.assign()でプロパティを代入できる", () => { + const data = { name: "Claude Monet" }; + Object.assign(data, { birth: "1840" }); + assert.deepStrictEqual(data, { name: "Claude Monet", birth: "1840" }); +}); diff --git a/templates/mock/main.js b/templates/mock/main.js new file mode 100644 index 0000000..e8417c8 --- /dev/null +++ b/templates/mock/main.js @@ -0,0 +1 @@ +// mock.test.js をご参照ください diff --git a/templates/mock/mock.test.js b/templates/mock/mock.test.js new file mode 100644 index 0000000..b9e96c9 --- /dev/null +++ b/templates/mock/mock.test.js @@ -0,0 +1,14 @@ +import assert from "node:assert"; +import test from "node:test"; + +const mockCallback = test.mock.fn(); + +["い", "ろ", "は"].forEach(mockCallback); + +test("関数は3回呼ばれます", () => { + assert.strictEqual(mockCallback.mock.calls.length, 3); +}); + +test("最初の呼び出しのときの第1引数は「い」です", () => { + assert.strictEqual(mockCallback.mock.calls[0].arguments[0], "い"); +}); diff --git a/templates/mock/package.json b/templates/mock/package.json new file mode 100644 index 0000000..f0021c0 --- /dev/null +++ b/templates/mock/package.json @@ -0,0 +1,11 @@ +{ + "name": "mock", + "version": "1.0.0", + "private": true, + "main": "main.js", + "type": "module", + "scripts": { + "test": "node --test", + "watch": "node --test --watch" + } +} diff --git a/templates/promise/main.js b/templates/promise/main.js new file mode 100644 index 0000000..9bce027 --- /dev/null +++ b/templates/promise/main.js @@ -0,0 +1 @@ +// promise.test.js をご参照ください diff --git a/templates/promise/package.json b/templates/promise/package.json new file mode 100644 index 0000000..45039bc --- /dev/null +++ b/templates/promise/package.json @@ -0,0 +1,11 @@ +{ + "name": "promise", + "version": "1.0.0", + "private": true, + "main": "main.js", + "type": "module", + "scripts": { + "test": "node --test", + "watch": "node --test --watch" + } +} diff --git a/templates/promise/promise.test.js b/templates/promise/promise.test.js new file mode 100644 index 0000000..5588281 --- /dev/null +++ b/templates/promise/promise.test.js @@ -0,0 +1,9 @@ +import assert from "node:assert"; +import test from "node:test"; + +const fetchData = () => Promise.resolve(42); + +test("データは42", async () => { + const data = await fetchData(); + assert.strictEqual(data, 42); +}); diff --git a/templates/scope/main.js b/templates/scope/main.js new file mode 100644 index 0000000..6e7a2d9 --- /dev/null +++ b/templates/scope/main.js @@ -0,0 +1 @@ +// scope.test.js をご参照ください diff --git a/templates/scope/package.json b/templates/scope/package.json new file mode 100644 index 0000000..60fd0cd --- /dev/null +++ b/templates/scope/package.json @@ -0,0 +1,11 @@ +{ + "name": "scope", + "version": "1.0.0", + "private": true, + "main": "main.js", + "type": "module", + "scripts": { + "test": "node --test", + "watch": "node --test --watch" + } +} diff --git a/templates/scope/scope.test.js b/templates/scope/scope.test.js new file mode 100644 index 0000000..1727c8e --- /dev/null +++ b/templates/scope/scope.test.js @@ -0,0 +1,34 @@ +import assert from "node:assert"; +import { after, afterEach, before, beforeEach, describe, it } from "node:test"; + +/* + * 実行順序: + * トップ - before → グループ1 - before + * → トップ - beforeEach → グループ1 - beforeEach + * → グループ1 - test 1 + * → トップ - afterEach → グループ1 - afterEach + * → トップ - beforeEach → グループ1 - beforeEach + * → グループ1 - test 2 + * → トップ - afterEach → グループ1 - afterEach + * → グループ1 - after → トップ - after + */ + +before(() => console.log("トップ - before")); +after(() => console.log("トップ - after")); +beforeEach(() => console.log("トップ - beforeEach")); +afterEach(() => console.log("トップ - afterEach")); + +describe("グループ1", () => { + before(() => console.log("グループ1 - before")); + after(() => console.log("グループ1 - after")); + beforeEach(() => console.log("グループ1 - beforeEach")); + afterEach(() => console.log("グループ1 - afterEach")); + + it("グループ1 - test 1", () => { + // ... + }); + + it("グループ1 - test 2", () => { + // ... + }); +}); diff --git a/templates/template/main.js b/templates/template/main.js new file mode 100644 index 0000000..17e8360 --- /dev/null +++ b/templates/template/main.js @@ -0,0 +1 @@ +// https://kou029w.github.io/nodejs-hands-on/test/ をご参照ください diff --git a/templates/template/package.json b/templates/template/package.json new file mode 100644 index 0000000..d2109bb --- /dev/null +++ b/templates/template/package.json @@ -0,0 +1,11 @@ +{ + "name": "template", + "version": "1.0.0", + "private": true, + "main": "main.js", + "type": "module", + "scripts": { + "test": "node --test", + "watch": "node --test --watch" + } +} diff --git a/templates/template/sum.js b/templates/template/sum.js new file mode 100644 index 0000000..e4739d5 --- /dev/null +++ b/templates/template/sum.js @@ -0,0 +1,5 @@ +function sum(a, b) { + return a + b; +} + +export default sum; diff --git a/templates/template/sum.test.js b/templates/template/sum.test.js new file mode 100644 index 0000000..03c2f9c --- /dev/null +++ b/templates/template/sum.test.js @@ -0,0 +1,7 @@ +import assert from "node:assert"; +import test from "node:test"; +import sum from "./sum.js"; + +test("1と2の合計は3です", () => { + assert.strictEqual(sum(1, 2), 3); +});