diff --git a/readme-jp.md b/readme-jp.md
new file mode 100644
index 0000000..b0a46fe
--- /dev/null
+++ b/readme-jp.md
@@ -0,0 +1,1998 @@
+
+
+
+
+# 👇 このガイドを読むとテストスキルが向上する理由
+
+
+
+## 📗 非常にわかりやすく、網羅的な46以上のベストプラクティス
+
+これは JavaScript & Node.js の信頼性のためのA-Zなガイドです。
+本ガイドは、沢山の素晴らしいブログ記事、書籍などの世にある様々なツールから内容をキュレーションし、要約して作られています。
+
+## 🚢 基礎なんて10000マイル以上置いてきぼりにするアドバンスドな内容
+
+基礎はもちろんのこと、多くのアドバンスドなトピック(本番環境でのテスト・ミューテーションテスト・property-basedテスト・戦略的でプロフェッショナルなツールについてなど)まで学べる旅に出ましょう!
+このガイドを隅々まで読みこめば、あなたのテストスキルは並のレベルを大きく凌駕することでしょう。
+
+## 🌐 フロントエンド、バックエンド、CI、その他なんでもフルスタックに
+
+まずは、どんなアプリケーションにとっても根幹となる普遍的なテストの習慣を理解するところから始めましょう。
+そして、フロントエンド/UI、バックエンド、CI、あるいはなんならその全てでも、自分の興味のある分野を探求していきましょう。
+
+
+
+### 著者: Yoni Goldberg について
+
+- JavaScript & Node.js のコンサルタントです
+- 📗 [Testing Node.js & JavaScript From A To Z](https://www.testjavascript.com) - [10時間以上の動画](https://www.testjavascript.com)、14種類のテスト、40以上のベストプラクティスを取り扱った、分かりやすいオンラインコースです
+- [Twitterはこちら](https://twitter.com/goldbergyoni/)
+
+
+
+### 翻訳 - 自分の言語で読んでください
+
+- 🇨🇳[中国語](readme-zh-CN.md) - [Yves yao](https://github.com/yvesyao)さんの貢献
+- 🇰🇷[韓国語](readme.kr.md) - [Rain Byun](https://github.com/ragubyun)さんの貢献
+- 🇵🇱[ポーランド語](readme-pl.md) - [Michal Biesiada](https://github.com/mbiesiad)さんの貢献
+- 🇪🇸[スペイン語](readme-es.md) - [Miguel G. Sanguino](https://github.com/sanguino)さんの貢献
+- 🇧🇷[ポルトガル語](readme-pt-br.md) - [Iago Angelim Costa Cavalcante](https://github.com/iagocavalcante)さん、[Douglas Mariano Valero](https://github.com/DouglasMV)さん、[koooge](https://github.com/koooge)さんの貢献
+
+- 自分の言語に翻訳したいですか? issueをぜひ立ててください 💜
+
+
+
+## `目次`
+
+#### [`Section 0: 黄金律`](#section-0️⃣-the-golden-rule)
+
+他をインスパイアするたったひとつのアドバイス(1発の特別な弾丸)
+
+#### [`Section 1: テスト解剖図`](#section-1-the-test-anatomy-1)
+
+綺麗なテストを構築するための土台 (12発の弾丸)
+
+#### [`Section 2: バックエンド`](#section-2️⃣-backend-testing)
+
+バックエンドおよびマイクロサービスのテストを効果的に書く(8発の弾丸)
+
+#### [`Section 3: フロントエンド`](#section-3️⃣-frontend-testing)
+
+コンポーネントテストやE2Eテストなどを含むWeb UIのテストを書く(11発の弾丸)
+
+#### [`Section 4: テストの有効性を計測する`](#section-4️⃣-measuring-test-effectiveness)
+
+監視員を監視する - テスト品質を測る (4発の弾丸)
+
+#### [`Section 5: 継続的インテグレーション`](#section-5️⃣-ci-and-other-quality-measures)
+
+JSの世界におけるCIのガイドライン (9発の弾丸)
+
+
+
+# Section 0️⃣: 黄金律
+
+
+
+## ⚪️ 0 黄金律: リーンなテストのためのデザイン
+
+:white_check_mark: **Do:**
+テストコードは本番コードとは違います - 非常にシンプルで、短く、抽象さを排除し、フラットで、リーンで、書きたくなるようなものにしましょう。誰でも一目見て意図がすぐに伝わるようなテストを心がけましょう。
+
+私たちの頭はいつもメインの本番コードのことでいっぱいなので、余計にややこしいものを追加するような「脳内のスペース」なんてありません。もしも追加で難しいコードを我々のちっぽけな脳に押し込もうなんてしようものなら、チームを遅滞させますし、それはそもそもテストを書きたかった理由と逆行していて本末転倒です。実際のところ、これが多くのチームがテストを諦めてしまう理由です。
+
+テストとは、ある別のことのための機会だと捉えましょう。それは、一緒に協業して楽しいような、友好的で笑顔に満ち溢れたアシスタントであり、小さな投資で大きなリターンをもたらすものなのです。
+科学的に人間には2つの脳のシステムがあります: システム1は、たとえばガラガラの道路を車を運転するような努力のいらない活動のために使われ、システム2は、たとえば数式を解くような複雑で意識的な操作のために使われます。
+システム1で処理できるようなテストをデザインしましょう。テストコードと向き合う時には、まるでHTML文書を編集するかのような気楽さを感じられるべきであって、2X(17 × 24)という数式を解く時のようであってはいけません。
+
+その達成のためには、テクニック、ツール、費用対効果が高いテスト対象を選択的に取捨選択するとよいでしょう。必要なものだけをテストし、敏捷性を保つことを心がけましょう。時には、信頼性を敏捷性と簡潔さと天秤にかけ、いくつかのテストを捨てることも有効です。
+
+
+
+ここから先のアドバイスのほとんどは、この原則から派生したものです。
+
+### 準備はいいですか?
+
+
+
+# Section 1: テスト解剖図
+
+
+
+## ⚪ ️ 1.1 テスト名には3つの要点を含める
+
+:white_check_mark: **こうしましょう:** テストレポートとは、現在のアプリケーションの変更が要件を満たせているかどうかを伝えるものでなければなりません。その要件とはコードベースに詳しいとは限らない人たちにとってのものであり、それは、テスターやデプロイをするDevOpsエンジニアや2年後のあなたです。
+そのためには、テスト自体が要件レベルで話し、3つの要点を含んでいるとよいでしょう。
+
+(1) 何がテストされているのか? たとえば、ProductsService.addNewProduct というメソッド
+
+(2) どのような状況とシナリオを想定しているか? たとえば、 priceがメソッドに渡されなかった時
+
+(3) どんなテスト結果を予期しているか? たとえば、 新しいproductが承認されないこと
+
+
+
+❌ **さもなくば:** デプロイが失敗し、"Add product"という名前のテストが落ちています。これで何が不具合を起こしているか正確に分かると言えますか?
+
+
+
+**👇 Note:** それぞれの弾丸にはコード例がついていて、時にはイラストもあります。クリックして広げてください。
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: 3つの要点を満たしたテスト名
+
+
+
+```javascript
+//1. テスト対象のユニット
+describe('Products Service', function() {
+ describe('productを追加する', function() {
+ //2. シナリオ and 3. 期待する結果
+ it('priceが指定されていない時、 productのステータスが承認待ちであること', ()=> {
+ const newProduct = new ProductService().add(...);
+ expect(newProduct.status).to.equal('pendingApproval');
+ });
+ });
+});
+
+```
+
+
+
+### :clap: 正しい例: 3つの要点を満たしたテスト名
+
+
+
+
+© クレジット & もっと読む
+ 1. Roy Osherove - Naming standards for unit tests
+
+
+## ⚪ ️ 1.2 AAAパターンでテストを構成する
+
+:white_check_mark: **こうしましょう:** Arrange(準備する), Act(動かす), Assert(確認する)という3つの工程でテストを構成しましょう。こうすることで、コードを読む人がテストの方針を理解するために脳内CPUを費やさずに済みます。
+
+1つ目のA - Arrange(準備する): テストがシミュレートしたい状況をセットアップするためのコードです。これには、テストしたい対象をインスタンス化する、DBレコードを追加する、特定のオブジェクトをモック/スタブすることなどが含まれます。
+
+2つ目のA - Act(動かす): テスト対象を動かします。 大抵は1行で済みます。
+
+3つ目のA - Assert(確認する): 返り値が期待している結果となっているかどうかを確認します。大抵は1行で済みます。
+
+
+
+❌ **さもなくば:** メインのコードを理解するのに何時間もかかってしまうばかりか、1日のタスクの中で本来は最も簡単であるはずのテストを書くという行為で脳がくたくたになってしまいます。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: AAAパターンで構成されたテスト
+
+ 
+
+```javascript
+describe("Customer classifier", () => {
+ test("カスタマーが500$費やした時, プレミアムとして識別されること", () => {
+ //Arrange(準備する)
+ const customerToClassify = { spent: 505, joined: new Date(), id: 1 };
+ const DBStub = sinon.stub(dataAccess, "getCustomer").reply({ id: 1, classification: "regular" });
+
+ //Act(動かす)
+ const receivedClassification = customerClassifier.classifyCustomer(customerToClassify);
+
+ //Assert(確認する)
+ expect(receivedClassification).toMatch("premium");
+ });
+});
+```
+
+
+
+### :thumbsdown: アンチパターン例: 区切りがなく、ひとかたまりで、分かりにくい
+
+```javascript
+test("プレミアムとして識別されること", () => {
+ 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 プロダクト由来の言葉で期待する振る舞いを記述する: BDDスタイルのアサーションを使う
+
+:white_check_mark: **こうしましょう:** 宣言的なスタイルでテストを書くことは、読者に少しも脳内CPUを使わせずに概観を掴ませる助けとなります。沢山の条件ロジックを含むような命令的なコードを書くと、読者は脳内CPUを沢山使うことを強制されてしまいます。
+なので、宣言的なBDDスタイルで、 `expect` や `should` などを用い、お手製を避けつつ、人間的な言葉で期待する結果を書きましょう。
+もしも、ChaiやJestが欲しいアサーションメソッドをもっておらず、そしてその欲しいアサーションメソッドが何度も使いうるものであれば、[Jestのマッチャーを拡張すること](https://jestjs.io/docs/en/expect#expectextendmatchers)や[カスタムChaiプラグイン](https://www.chaijs.com/guide/plugins/)を書くことを検討してみてください。
+
+
+❌ **さもなくば:** チームがテストを書かなくなり、面倒なテストを.skip()で飛ばすようになります。
+
+
+
+✏ コード例
+
+ 
+
+### :thumbsdown: アンチパターン例: 読者がテストの方針を知るために、命令的なコードをそれなりの量確認しなければならない
+
+```javascript
+test("アドミンを取得する時、 アドミンのみが取得結果に含まれること", () => {
+ //"admin1"、 "admin2" というアドミンと、"user1"というユーザーを追加してあると仮定する
+ const allAdmins = getUsers({ adminOnly: true });
+
+ let admin1Found,
+ adming2Found = false;
+
+ allAdmins.forEach(aSingleUser => {
+ if (aSingleUser === "user1") {
+ assert.notEqual(aSingleUser, "user1", "A user was found and not admin");
+ }
+ if (aSingleUser === "admin1") {
+ admin1Found = true;
+ }
+ if (aSingleUser === "admin2") {
+ admin2Found = true;
+ }
+ });
+
+ if (!admin1Found || !admin2Found) {
+ throw new Error("Not all admins were returned");
+ }
+});
+```
+
+
+
+### :clap: 正しい例: 宣言的なテストを俯瞰するのは容易いことです
+
+```javascript
+it("アドミンを取得する時、 アドミンのみが取得結果に含まれること", () => {
+ // 2人アドミンを追加してあると仮定する
+ const allAdmins = getUsers({ adminOnly: true });
+
+ expect(allAdmins)
+ .to.include.ordered.members(["admin1", "admin2"])
+ .but.not.include.ordered.members(["user1"]);
+});
+```
+
+
+
+## ⚪ ️ 1.4 ブラックボックステストを守る: パブリックメソッドのみをテストする
+
+:white_check_mark: **こうしましょう:** 内部実装をテストしても大きなオーバーヘッドの割に、何も得られません。もしコードやAPIが正しい結果を返しているのなら、3時間もかけて"どのように"それが達成されたかをテストし、更にそのような壊れやすいテストをメンテしていく必要がありますか?
+公開されている振る舞いがテストされている時は、常に内部実装も暗黙的にテストされていて、そのテストが壊れる時というのは何か特定の問題があった時だけです(たとえば、出力が間違っているなど)。
+このようなアプローチは`behavioral testing`と呼ばれます。
+逆に、内部実装をテストする場合(ホワイトボックス的アプローチ) - フォーカスがコンポーネントの出力から核心的な詳細に移ります。小さなリファクタリングによって、たとえ出力結果が問題なかったとしても、テストが壊れるかもしれません。- これはメンテナンスコストを著しく向上させてしまいます。
+
+
+
+❌ **さもなくば:** テストが[オオカミ少年](https://ja.wikipedia.org/wiki/%E5%98%98%E3%82%92%E3%81%A4%E3%81%8F%E5%AD%90%E4%BE%9B)になります: (例えば、プライベート変数の名前が変わったことでテストが壊れたなどの理由で)嘘の叫びをあげます。開発者たちがCIの通知を無視し続けてある日本当のバグが無視されてしまうようになるのも、全く驚くことではありません。
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: 特に理由もなく内部実装をテストしている
+
+
+
+```javascript
+class ProductService {
+ // このメソッドは内部でしか使われていない
+ // このメソッド名を変更するとテストが壊れる
+ calculateVATAdd(priceWithoutVAT) {
+ return { finalPrice: priceWithoutVAT * 1.2 };
+ // 上記の返り値の形やキー名を変えるとテストが壊れる
+ }
+ //public method
+ getPrice(productId) {
+ const desiredProduct = DB.getProduct(productId);
+ finalPrice = this.calculateVATAdd(desiredProduct.price).finalPrice;
+ return finalPrice;
+ }
+}
+
+it("ホワイトボックステスト: 内部メソッドが0 vatを受け取る時, 0を返す", async () => {
+ // ユーザーがVATを計算できるようにしなければいけない要件はなく、最終金額が示せれば良い。それにも関わらず、クラス内部をテストすることに固執してしまっている。
+ expect(new ProductService().calculateVATAdd(0).finalPrice).to.equal(0);
+});
+```
+
+
+
+## ⚪ ️ ️1.5 正しいテストダブルを選択する: スタブやスパイの代わりにモックを使わない
+
+:white_check_mark: **こうしましょう:** テストダブルはアプリケーションの内部に結合しているため必要悪ですが、時には大きな価値をもたらします。 ([テストダブルって何のことか忘れてしまった人はこちらを読みましょう: モック vs スタブ vs スパイ](https://martinfowler.com/articles/mocksArentStubs.html)).
+
+テストダブルを使う前に簡単な自問をしましょう: 私がテストしようとしている機能は仕様書に書いてある、あるいは今後書かれうることか?もし違うなら、それはホワイトボックステストになってしまっている可能性があります。
+
+たとえば、もし決済サービスが落ちた時にどんな風にアプリケーションが振る舞うのかテストしたい時、決済サービスをスタブして'No Response'を返却させることでテスト対象が正しい値を返しているか確認することでしょう。これは特定のシナリオ下におけるアプリケーションの振る舞い、応答、結果をチェックします。あるいは、決済サービスが落ちている時にメールが送信されることをスパイを使って確認することでしょう。 - これも仕様書におそらく書かれていることの振る舞い確認です。("決済に失敗したらメールを送信する")
+一方で、決済サービスをモックしてそれが正しいJavaScriptの型で呼び出されていることを確認する場合 - アプリケーションの機能とは関係のない内部のことにテストがフォーカスしてしまい、頻繁に更新しなければならないでしょう。
+
+
+
+❌ **さもなくば:** どんなリファクタリングをするにも、コード上で使われている全てのモックを探して更新することが必要になってしまいます。すると、テストは頼りがいのある親友ではなく、重荷になってしまいます。
+
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: モックの関心が内部実装にある
+
+
+
+```javascript
+it("有効なプロダクトが削除される時, データアクセス用のDALが正しいプロダクトと正しいコンフィグで1度だけ呼ばれること", async () => {
+ //既にプロダクトを追加してあるとする
+ const dataAccessMock = sinon.mock(DAL);
+ //う〜ん、よくないですね: 内部実装をテストすることがゴールになってしまっていて、ただの副作用ではなくなってしまっています。
+ dataAccessMock
+ .expects("deleteProduct")
+ .once()
+ .withArgs(DBConfig, theProductWeJustAdded, true, false);
+ new ProductService().deletePrice(theProductWeJustAdded);
+ dataAccessMock.verify();
+});
+```
+
+
+
+### :clap:正しいコード例: スパイの関心が要件をテストすることにあり、副作用は結果として内部実装に触れている
+
+```javascript
+it("有効なプロダクトが削除される時, メールが送信されること", async () => {
+ //既にプロダクトを追加してあるとする
+ const spy = sinon.spy(Emailer.prototype, "sendEmail");
+ new ProductService().deletePrice(theProductWeJustAdded);
+ //う〜ん、OK: これも内部実装じゃないのかって? そうですね、でもメールを送信するという要件をテストする上での副作用としてです
+ expect(spy.calledOnce).to.be.true;
+});
+```
+
+
+
+## 📗 これらのプラクティスを動画で学びたいですか?
+
+### 私のオンラインコースをチェックしてみてください [Testing Node.js & JavaScript From A To Z](https://www.testjavascript.com)
+
+
+
+## ⚪ ️1.6 "foo"ではなく、リアルな入力データを使う
+
+:white_check_mark: **こうしましょう:** 時にプロダクションのバグは予期せぬ非常に限定的な入力値によってもたらされます - テストの入力値がリアルであるほど、バグを早期に発見できる可能性が高まります。[Faker](https://www.npmjs.com/package/faker)のような専用のライブラリを使うことで、擬似的にリアルで、プロダクションの様々な状態に似せたデータを生成しましょう。たとえば、そういうライブラリを使うとリアルっぽい電話番号、ユーザー名、クレジットカード情報、会社名、あるいは'lorem ipsum'テキストまで生成できます。fakerのデータをランダムにしてテスト対象ユニットを拡張するようなテストを作ることもできますし(通常のテストに加えてです、代わりにではなく)、あるいは実際のプロダクション環境からデータをインポートすることもできます。もっと高いレベルをみたいですか?次の弾丸をみてください(property-basedテスト)
+
+
+
+❌ **さもなくば:**
+"Foo"のような人工的な入力値を使っていると、開発時のテストでは誤ってグリーンになってしまうかもしれませんが、本番環境でハッカーが“@3e2ddsf . ##’ 1 fdsfds . fds432 AAAA”のような薄汚い文字列を渡してきたら、レッドになってしまうかもしれません。
+
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: 人工的なデータのせいでテストスイートが通ってしまう
+
+
+
+```javascript
+const addProduct = (name, price) => {
+ const productNameRegexNoSpace = /^\S*$/; //空白文字列を許容しない
+
+ if (!productNameRegexNoSpace.test(name)) return false; //入力値が簡易的なせいで、このパスには到達しない
+
+ //なにかここにロジックがあるとする
+ return true;
+};
+
+test("ダメな例: 有効なプロパティでproductを追加する時、確認に成功する", async () => {
+ //"Foo"という文字列が全てのテストで使われ、永遠にfalseな結果を引き起こさない
+ const addProductResult = addProduct("Foo", 5);
+ expect(addProductResult).toBe(true);
+ //誤った成功: 空白の入った長い文字列で試さなかったので成功してしまった
+});
+```
+
+
+
+### :clap: 正しい例: ランダムにリアルな入力値を使う
+
+```javascript
+it("良い例: 有効なproductを追加する時、確認に成功する", async () => {
+ const addProductResult = addProduct(faker.commerce.productName(), faker.random.number());
+ //生成されたランダムな入力値: {'Sleek Cotton Computer', 85481}
+ expect(addProductResult).to.be.true;
+ //ランダムな入力値のおかげで、予期していなかったコードパスに到達してテストが失敗した。
+ //バグを早期発見できた!
+});
+```
+
+
+
+## ⚪ ️ 1.7 Property-basedテストで多様な入力値の組み合わせをテストする
+
+:white_check_mark: **こうしましょう:** 開発者は往々にしてわずかな入力値のパターンでテストをしてしまいがちです。入力値のフォーマットが現実のデータに近い時ですら([’fooを使うな’](https://github.com/goldbergyoni/javascript-testing-best-practices#-%EF%B8%8F16-dont-foo-use-realistic-input-data)の項を読んでください)、開発者は method(‘’, true, 1), method(“string” , false , 0) のような限られた入力値の組合せしかカバーしません。
+
+ しかし本番環境では、5個のパラメーターを持つAPIは何千もの組合せで呼び出されますし、その中の1つがプロセスを落としてしまうかもしれません。([Fuzz Testingを読んでください](https://en.wikipedia.org/wiki/Fuzzing))。
+ もし、1個のテストで1000種もの入力値を自動で試し、どの入力値が正しいレスポンスを返せなかったかを把握できる、と言ったらどうですか?
+ Property-basedテストという技術はまさにそれをやってくれます: ありえる全ての入力値のパターンをテスト対象に流し込むことで、バグを発見する機運を高めてくれるのです。
+たとえば、addNewProduct(id, name, isDiscount) というメソッドがあるとしましょう。このメソッドを使うライブラリは、(1, “iPhone”, false), (2, “Galaxy”, true) のような、(number, string, boolean)のあらゆる組合せで呼び出します。
+[js-verify](https://github.com/jsverify/jsverify) や [testcheck](https://github.com/leebyron/testcheck-js) (こちらの方がドキュメントが断然良いです)のようなライブラリを使うと、MochaやJestなどお好みのテストランナーライブラリでproperty-basedテストを実行することができます。
+Update: Nicolas Dubienさんが下記のコメントで[fast-checkを見てみてください](https://github.com/dubzzz/fast-check#readme)と提案してくれましたが、こちらのライブラリはさらにフィーチャーを提供していて、アクティブにメンテナンスされているようです。
+
+
+❌ **さもなくば:** ちゃんと動くコードパスしか網羅しないテスト入力値を無意識で選択してしまいます。残念ながらこれでは、バグを表出させるための相棒であるテストの効率を下げてしまいます。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: "fast-check"を使って多様な入力値の組み合わせをテスト
+
+
+
+```javascript
+import fc from "fast-check";
+
+describe("Product service", () => {
+ describe("Adding new", () => {
+ //これはランダムなプロパティで100回走る
+ it("有効な範囲内でランダムなプロパティでproductを追加する時、常に成功すること", () =>
+ fc.assert(
+ fc.property(fc.integer(), fc.string(), (id, name) => {
+ expect(addNewProduct(id, name).status).toEqual("approved");
+ })
+ ));
+ });
+});
+```
+
+
+
+## ⚪ ️ 1.8 必要に応じて、短くインラインのスナップショットを使用
+
+:white_check_mark: **こうしましょう:** [スナップショットテスト](https://jestjs.io/docs/en/snapshot-testing)が必要な場合、短く集中したスナップショット(3〜7行程度)を使用し、テストの一部としてインラインで含めること([Inline Snapshot](https://jestjs.io/docs/en/snapshot-testing#inline-snapshots))が推奨されます。外部ファイルに保存しないことで、テストは自己説明的で壊れにくくなります。
+
+一方で、「クラシックスナップショット」のチュートリアルやツールは、大きなファイル(例:コンポーネントのレンダリングマークアップやAPIのJSON結果)を外部に保存し、テスト実行時に受け取った結果と保存されたバージョンを比較することを推奨しています。しかし、これにより、テストが1000行や3000個のデータ値に暗黙的に結び付けられ、テスト作成者がそれを読んで理解することができなくなります。なぜこれが問題なのでしょうか? その理由は多岐にわたり、スナップショットが無効になるのに1行の変更で十分で、これは頻繁に発生します。具体的には、スペース、コメント、CSS/HTMLの小さな変更ごとに起こり得ます。このような場合、テスト名からエラーの手がかりを得ることは難しく、単に1000行が変更されなかったかをチェックするだけになります。また、テスト作成者が確認も検証もできない長文ドキュメントを望ましい真実として受け入れるように促します。これらはすべて、焦点が定まらず、過剰な目標を達成しようとする不透明で過度なテストの症状です。
+
+なお、スキーマを確認し、データを確認しない場合(フィールドに焦点を当て、値を抽出する)や、受け取るドキュメントがほとんど変更されない場合など、長い外部スナップショットが受け入れられるケースも少しだけあります。
+
+
+❌ **さもなくば:** UIテストが失敗します。コードは正しいように見え、画面は完璧にレンダリングされているのに、何が起こったのでしょうか? スナップショットテストは、元のドキュメントと現在受け取ったものとの差異を発見しました—マークダウンにスペースが1つ追加されていただけでした...
+
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: 目に見えない2000行のコードにテストを結び付ける
+
+
+
+```javascript
+it("TestJavaScript.com is renderd correctly", () => {
+ //Arrange(準備する)
+
+ //Act(動かす)
+ const receivedPage = renderer
+ .create(
+
+### :clap: 正しい例: 期待値が明確で集中している
+
+```javascript
+it("When visiting TestJavaScript.com home page, a menu is displayed", () => {
+ //Arrange(準備する)
+
+ //Act(動かす)
+ const receivedPage = renderer
+ .create(
+
+`);
+});
+```
+
+
+
+## ⚪ ️ 1.9 必要なコードのみをコピーする
+
+:white_check_mark: **こうしましょう:** テスト結果に影響を与える必要な詳細はすべて含めますが、それ以上は含めません。例えば、100行の入力JSONを処理するテストを考えてみましょう。これを毎回テストに貼り付けるのは手間です。これを外部に抽出して `transferFactory.getJSON()` とすると、テストが曖昧になってしまいます — データがなければ、テスト結果とその原因を関連付けるのが難しくなります(「なぜ400ステータスを返すべきなのか?」)。古典的な書籍「x-unitパターン」では、このパターンを「謎のゲスト」と呼んでいます — 何か見えないものがテスト結果に影響を与えていますが、正確には何が影響を与えたのか分かりません。繰り返し使われる長い部分を外部に抽出し、テストに重要な具体的な詳細を明示的に示すことで、改善できます。上記の例を使うと、テストは重要な部分を強調するパラメーターを渡すことができます:`transferFactory.getJSON({sender: undefined})`。この例では、読者はすぐに「senderフィールドが空であることが、テストがバリデーションエラーやその他の適切な結果を期待する理由である」と推測すべきです。
+
+
+❌ **さもなくば:** 500行のJSONをコピーすることは、テストを維持不可能で読みにくくします。すべてを外部に移動すると、理解しにくい曖昧なテストが生まれます
+
+
+
+✏ コード例
+
+
+
+
+### :thumbsdown: アンチパターン例: テストの失敗が不明確で、原因が外部にあり、大きなJSON内に隠れている
+
+
+
+```javascript
+test("クレジットがない場合、転送は拒否される", async() => {
+ //Arrange(準備する)
+ const transferRequest = testHelpers.factorMoneyTransfer() //200行のJSONが返ってくる;
+ const transferServiceUnderTest = new TransferService();
+
+ //Act(動かす)
+ const transferResponse = await transferServiceUnderTest.transfer(transferRequest);
+
+ //Assert(確認する)
+ expect(transferResponse.status).toBe(409);// でもなぜ失敗を期待するのか: テスト内ではすべてが完璧に有効に見える 🤔
+ });
+```
+
+
+
+### :clap: 正しい例: テスト結果の原因を強調する
+
+```javascript
+test("クレジットがない場合、転送は拒否される", async() => {
+ //Arrange(準備する)
+ const transferRequest = testHelpers.factorMoneyTransfer({userCredit:100, transferAmount:200}) // 明らかにクレジットが不足している
+ const transferServiceUnderTest = new TransferService({disallowOvercharge:true});
+
+ //Act(動かす)
+ const transferResponse = await transferServiceUnderTest.transfer(transferRequest);
+
+ //Assert(確認する)
+ expect(transferResponse.status).toBe(409); // ユーザーにクレジットがない場合、明らかに失敗するべき
+ });
+```
+
+
+
+## ⚪ ️ 1.10 エラーをキャッチせず、エラーを期待する
+
+:white_check_mark: **こうしましょう:** ある入力がエラーを引き起こすことをアサートしようとするとき、try-catch-finallyを使用してcatch句が実行されたことを確認するのは正しいように見えるかもしれません。しかし、その結果はシンプルなテストの意図や結果の期待を隠してしまう、冗長で不格好なテストケースになります(以下の例参照)。
+
+よりエレガントな代替手段は、専用のChaiアサーションを1行で使用することです:expect(method).to.throw(またはJestではexpect(method).toThrow())。また、例外がエラータイプを示すプロパティを含むことを確認することが絶対に必要です。さもないと、単なる一般的なエラーを渡すだけでは、アプリケーションはユーザーに失望させるメッセージを表示する以外に多くのことができません。
+
+
+
+❌ **さもなくば:** テストレポート(例: CIレポート)から何が問題だったのかを推測するのが難しくなります。
+
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: try-catchでエラーの存在をアサートしようとする冗長なテストケース
+
+
+
+```javascript
+it("商品名がない場合、エラー400をスローする", async () => {
+ let errorWeExceptFor = null;
+ try {
+ const result = await addNewProduct({});
+ } catch (error) {
+ expect(error.code).to.equal("InvalidInput");
+ errorWeExceptFor = error;
+ }
+ expect(errorWeExceptFor).not.to.be.null;
+ // このアサーションが失敗した場合、テスト結果/レポートには
+ // 値がnullであることしか表示されず、例外が見つからないことについては言及されません
+});
+```
+
+
+
+### :clap: 正しい例: QAや技術的なPMでも簡単に理解できる人間が読めるexpect
+
+```javascript
+it("商品名がない場合、エラー400をスローする", async () => {
+ await expect(addNewProduct({}))
+ .to.eventually.throw(AppError)
+ .with.property("code", "InvalidInput");
+});
+```
+
+
+
+## ⚪ ️ 1.11 テストにタグを付ける
+
+:white_check_mark: **こうしましょう:** 異なるテストは異なるシナリオで実行する必要があります。例えば、クイックなスモークテストやI/Oレスなテストは、開発者がファイルを保存またはコミットしたときに実行し、フルなエンドツーエンドテストは通常、プルリクエストが提出されたときに実行されます。これを実現するためには、#cold #api #sanity などのキーワードでテストにタグを付け、テストハーネスでgrepを使って必要なサブセットを呼び出すことができます。例えば、Mochaでsanityテストグループのみを呼び出す方法は以下の通りです:mocha — grep ‘sanity’
+
+
+
+❌ **さもなくば:** 開発者が小さな変更を加えるたびに、データベースクエリを数十回実行するテストも含めてすべてのテストを実行するのは非常に遅くなり、開発者がテストを実行するのを避ける原因となります。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: ‘#cold-test’としてテストにタグを付けることで、テストランナーは高速なテストのみを実行できるようになります(Cold === I/Oを行わない迅速なテストで、開発者が入力している間でも頻繁に実行できます)
+
+
+
+```javascript
+//このテストは高速で(DBを使用しない)、それに応じてタグ付けしています
+//これでユーザーやCIは頻繁に実行できます
+describe("Order service", function() {
+ describe("新しい注文の追加 #cold-test #sanity", function() {
+ test("シナリオ - 通貨が指定されていない。期待 - デフォルト通貨を使用 #sanity", function() {
+ //コードロジックここに
+ });
+ });
+});
+```
+
+
+
+## ⚪ ️ 1.12 テストを少なくとも2つのレベルで分類する
+
+:white_check_mark: **こうしましょう:** テストスイートにある程度の構造を適用し、偶然訪れる人がテストの要件(テストは最高のドキュメント)やテストされているさまざまなシナリオを簡単に理解できるようにします。この方法の一般的なものは、テストの前に少なくとも2つの'describe'ブロックを配置することです。1つ目はテスト対象のユニットの名前、2つ目はシナリオやカスタムカテゴリーなどの追加の分類レベルです(以下のコード例とスクリーンショットを参照)。これにより、テストレポートが大幅に改善されます:読者はテストのカテゴリーを簡単に推測し、希望するセクションに深入りして失敗したテストと相関させることができます。さらに、多くのテストを含むスイートのコードを開発者がナビゲートするのがずっと簡単になります。テストスイートの構造に関して、[given-when-then](https://github.com/searls/jasmine-given) や [RITE](https://github.com/ericelliott/riteway) などの複数の代替構造を検討することができます。
+
+
+
+❌ **さもなくば:** フラットで長いテストのリストを見たとき、長いテキストをざっと読んで主要なシナリオを結論し、失敗したテストの共通点を相関させる必要があります。例えば、100のテストのうち7つが失敗した場合、フラットなリストでは失敗したテストのテキストを読み、どのように関連しているかを確認しなければなりません。しかし、階層的なレポートでは、すべてが同じフローやカテゴリの下にあり、原因をすばやく推測できます。少なくともどこが根本的な失敗の原因かを推測することができます。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: テスト対象ユニットとシナリオでスイートを構造化すると、以下のような便利なレポートが得られます
+
+
+
+```javascript
+// テスト対象ユニット
+describe("Transfer service", () => {
+ // シナリオ
+ describe("When no credit", () => {
+ // 期待値
+ test("Then the response status should decline", () => {});
+
+ // 期待値
+ test("Then it should send email to admin", () => {});
+ });
+});
+```
+
+
+
+
+
+### :thumbsdown: アンチパターン例: テストのフラットなリストは、読者がユーザーストーリーを特定し、失敗したテストを関連付けるのを難しくする
+
+
+
+```javascript
+test("レスポンスステータスが拒否されるべき", () => {});
+
+test("それが管理者にメールを送信するべき", () => {});
+
+test("新しい転送レコードが作成されないべき", () => {});
+```
+
+
+
+
+
+
+
+## ⚪ ️1.13 その他の一般的な良いテスト習慣
+
+:white_check_mark: **こうしましょう:** この投稿は、Node JSに関連した、または少なくともNode JSを例に挙げて説明できるテストに関するアドバイスに焦点を当てています。ただし、この項目では、Nodeに関連しないいくつかのよく知られたアドバイスをまとめています。
+
+[TDDの原則](https://www.sm-cloud.com/book-review-test-driven-development-by-example-a-tldr/)を学び、実践する — これは多くの人にとって非常に価値がありますが、自分のスタイルに合わない場合でも気にしないでください、あなたが唯一の人ではありません。コードの前にテストを書くことを検討し、[レッド・グリーン・リファクタリングスタイル](https://blog.cleancoder.com/uncle-bob/2014/12/17/TheCyclesOfTDD.html)を採用し、各テストが正確に1つのことをチェックするようにしましょう。バグを見つけた場合は、それを修正する前にそのバグを将来検出できるテストを書き、少なくとも1回はテストを失敗させた後に成功するようにしましょう。モジュールを始めるときは、最初にテストを満たすための簡単でシンプルなコードを書き、その後、徐々にリファクタリングして本番用の品質に仕上げていきます。環境(パス、OSなど)への依存は避けましょう。
+
+
+❌ **さもなくば:** 数十年にわたって集められた知恵の宝石を見逃すことになります
+
+
+
+# Section 2️⃣: バックエンドテスティング
+
+## ⚪️ 2.1 あなたのテストポートフォリオを豊かにする:Unit testsとピラミッドを超えて
+
+:white_check_mark: **こうしましょう:** [testing pyramid](https://martinfowler.com/bliki/TestPyramid.html)は10年以上前のものですが、3つのテストタイプを提案し、多くの開発者のテスト戦略に影響を与える素晴らしく関連性の高いモデルです。同時に、testing pyramidの影に隠れた輝かしい新しいテスト手法がいくつも登場しました。過去10年に見られた(Microservices、cloud、serverless)といった劇的な変化を考えると、一つの古いモデルが*全て*のアプリケーションタイプに適合することが可能なのでしょうか?テストの世界は新しいテスト手法を歓迎すべきではないでしょうか?
+
+誤解しないでください。2019年においても、testing pyramid、TDD、unit testsは依然として強力な手法であり、多くのアプリケーションにとって最適な選択でしょう。しかし、他のどんなモデルと同様に、その有用性にもかかわらず、[時には間違っているに違いありません](https://en.wikipedia.org/wiki/All_models_are_wrong)。例えば、Kafka/RabbitMQのようなメッセージバスに多くのイベントを取り込むIoTアプリケーションを考えてみましょう。これらはデータウェアハウスに流れ込み、最終的には分析用UIでクエリされます。ほとんどロジックがなく、統合が中心のアプリケーションに対して、テスト予算の50%をUnit testsの作成に費やすべきでしょうか?アプリケーションタイプの多様性が増すにつれて(bots、crypto、Alexa-skills)、testing pyramidが最適な適合ではないシナリオが見つかる可能性が高くなります。
+
+あなたのテストポートフォリオを豊かにし、より多くのテストタイプに精通する時です(次の箇条書きでいくつかのアイデアを提案します)。testing pyramidのようなマインドモデルを持ちながらも、直面している現実の問題にテストタイプを合わせましょう(「おい、APIが壊れている。consumer-driven contract testingを書こう!」)。リスク分析に基づいてポートフォリオを構築する投資家のようにテストを多様化しましょう—問題が発生し得る箇所を評価し、それらの潜在的なリスクを軽減するための予防策を適用します。
+
+注意点:ソフトウェアの世界におけるTDDに関する議論は典型的な偽の二分法を呈しています。あらゆる場所で使うべきだと説く人もいれば、悪魔だと考える人もいます。絶対的な言い方をする人は皆、間違っています :]
+
+
+
+❌ **さもなくば:** 驚くほどROIの高いツールを見逃すことになります。Fuzz、lint、mutationのようなものは10分で価値を提供できます
+
+✏ コード例
+
+
+
+### :clap: 正しい例: Cindy Sridharan は彼女の素晴らしい投稿『Testing Microservices — the same way』で豊富なテストポートフォリオを提案しています
+
+
+
+☺️例: [YouTube: “Beyond Unit Tests: 5 Shiny Node.JS Test Types (2018)” (Yoni Goldberg)](https://www.youtube.com/watch?v=-2zP494wdUY&feature=youtu.be)
+
+
+
+
+
+
+
+## ⚪ ️2.2 コンポーネントテストはあなたのベストな選択かもしれません
+
+:white_check_mark: **こうしましょう:** 各ユニットテストはアプリケーションのごく一部をカバーしており、全体をカバーするには高コストです。一方、エンドツーエンドテストは多くを簡単にカバーできますが、信頼性が低く、遅いです。なぜ、バランスの取れたアプローチを適用し、ユニットテストより大きく、エンドツーエンドテストより小さいテストを書くことを考えないのでしょうか?コンポーネントテストはテストの世界の隠れた名曲です — 彼らは両者の良いところを提供します。妥当なパフォーマンスとTDDパターンの適用可能性、そして現実的で素晴らしいカバレッジを提供します。
+
+コンポーネントテストはマイクロサービスの「単位」に焦点を当てており、APIに対して動作し、マイクロサービス自体に属するもの(例えば、実際のDB、もしくは少なくともそのDBのインメモリ版)をモックせず、他のマイクロサービスへの呼び出しなどの外部のものはスタブします。この方法により、デプロイするものをテストし、アプリを外部から内部へとアプローチし、合理的な時間で大きな自信を得ることができます。
+
+
+❌ **さもなくば:** ユニットテストを書くことに長い日々を費やし、システムのたった20%しかカバーできていないことが分かるかもしれません。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: SupertestはExpress APIへのインプロセスアプローチを可能にします(高速で多くの層をカバー)
+
+
+
+ allows approaching Express API in-process (fast and cover many layers)")
+
+
+
+## ⚪ ️2.3 コントラクトテストを使用して新リリースがAPIを壊さないことを保証する
+
+:white_check_mark: **こうしましょう:** あなたのマイクロサービスには複数のクライアントがあり、互換性の理由で複数のバージョンのサービスを実行しています(すべての人を満足させるため)。そこで、何かフィールドを変更しようとしたら「ドカン!」と、そのフィールドに依存している重要なクライアントが怒ってしまいました。これは統合の世界のジレンマです:サーバー側が複数のクライアントの期待をすべて考慮するのは非常に挑戦的であり、一方でクライアントはサーバーがリリース日を制御するため、テストを実行できません。[Consumer-driven contracts とフレームワークPACT](https://docs.pact.io/)は、非常に革新的なアプローチでこのプロセスを形式化するために生まれました。サーバーは自分自身のテスト計画を定義するのではなく、クライアントがサーバーのテストを定義します!PACTはクライアントの期待を記録し、共有場所「ブローカー」に配置することで、サーバーがPACTライブラリを使用して各ビルドで期待を引き出し、破れた契約 — 満たされないクライアントの期待 — を検出することができます。この方法により、すべてのサーバークライアントAPIの不一致がビルド/CIの早期に発見され、大きなフラストレーションを避けることができるかもしれません。
+
+
+❌ **さもなくば:** 他の選択肢は疲れる手動テストやデプロイの恐怖です。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例:
+
+
+
+
+
+
+
+## ⚪ ️2.4 ミドルウェアを単体でテストする
+
+:white_check_mark: **こうしましょう:** ミドルウェアテストを避ける人は多いですが、それはシステムの小さな部分であり、ライブのExpressサーバーを必要とするからです。これらの理由はどちらも間違っています — ミドルウェアは小さいですが、すべてまたはほとんどのリクエストに影響を与え、{req,res} JSオブジェクトを受け取る純関数として簡単にテストできます。ミドルウェア関数をテストするには、それを呼び出し、{req,res}オブジェクトとのやりとりをスパイ(例えば[Sinonを使用して](https://www.npmjs.com/package/sinon))して、関数が正しいアクションを実行したことを確認するだけでいいのです。[node-mock-http](https://www.npmjs.com/package/node-mocks-http)ライブラリは、{req,res}オブジェクトを因数分解し、それらの振る舞いをスパイすることさらに進みます。例えば、resオブジェクトに設定されたHTTPステータスが期待に合っているかをアサートできます(以下の例を参照)。
+
+
+❌ **さもなくば:** Expressミドルウェアのバグ === すべてまたはほとんどのリクエストのバグ
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: ネットワーク呼び出しを発行せず、Express全体を起動させずにミドルウェアを単体でテスト
+
+
+
+```javascript
+// テストしたいミドルウェア
+const unitUnderTest = require("./middleware");
+const httpMocks = require("node-mocks-http");
+// Jestの文法、Mochaのdescribe() & it()と同等
+test("認証ヘッダーなしのリクエストは、httpステータス403を返すべき", () => {
+ const request = httpMocks.createRequest({
+ method: "GET",
+ url: "/user/42",
+ headers: {
+ authentication: ""
+ }
+ });
+ const response = httpMocks.createResponse();
+ unitUnderTest(request, response);
+ expect(response.statusCode).toBe(403);
+});
+```
+
+
+
+## ⚪ ️2.5 静的解析ツールを使用して測定しリファクタリング
+
+:white_check_mark: **こうしましょう:** 静的解析ツールを使用することで、コードの品質を向上させ、コードを保守可能に保つための客観的な方法が提供されます。静的解析ツールをCIビルドに追加して、コードの悪臭を発見したときにビルドを中止することができます。通常のリンティングに対する主な売りのポイントは、複数のファイルの文脈で品質を検査する能力(例: 重複の検出)、高度な解析の実施(例: コードの複雑さ)そしてコードの問題の履歴と進捗の追跡です。使用できるツールの例として、[SonarQube](https://www.sonarqube.org/)(4,900以上の[stars](https://github.com/SonarSource/sonarqube))と[Code Climate](https://codeclimate.com/)(2,000以上の[stars](https://github.com/codeclimate/codeclimate))があります。
+
+クレジット: [Keith Holliday](https://github.com/TheHollidayInn)
+
+
+
+❌ **さもなくば:** 低品質のコードでは、バグとパフォーマンスが常に問題となり、どんな新しいライブラリや最先端の機能でも解決できません。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: 複雑なメソッドを識別できる商用ツールCodeClimate:
+
+
+
+
+
+
+
+## ⚪ ️2.6 Node関連のカオスへの準備を確認する
+
+:white_check_mark: **こうしましょう:** 奇妙なことに、ほとんどのソフトウェアテストはロジックとデータのみですが、最悪の出来事(そして本当に緩和が難しいもの)はインフラストラクチャの問題です。例えば、プロセスメモリが過負荷になったり、サーバー/プロセスがクラッシュしたり、APIの処理が50%遅くなったときに監視システムが認識するかどうかをテストしたことがありますか?これらの悪影響をテストして緩和するために — [カオスエンジニアリング](https://principlesofchaos.org/)はNetflixによって生み出されました。これは、混乱した問題に対するアプリの回復力をテストするための認識、フレームワーク、ツールを提供することを目的としています。例えば、その有名なツールの一つ、[カオスモンキー](https://github.com/Netflix/chaosmonkey)はサーバーをランダムに停止させることで、サービスがユーザーにサービスを提供し続け、単一のサーバーに依存しないことを確認します(また、Kubernetes版としてポッドを停止する[kube-monkey](https://github.com/asobti/kube-monkey)もあります)。これらのツールはすべてホスティング/プラットフォームレベルで機能しますが、純粋なNodeカオスをテストおよび生成したい場合はどうでしょうか。たとえば、Nodeプロセスが未処理のエラー、未処理のpromise拒否、1.7GBの最大許可メモリでのv8メモリ過負荷にどのように対処するか、またはイベントループが頻繁にブロックされるときにUXが満足な状態であるかどうかを確認する場合などを考慮するために、私は[node-chaos](https://github.com/i0natan/node-chaos-monkey)(アルファ版)を作成しました、これはNode関連のカオス的な行為をすべて提供します。
+
+
+❌ **さもなくば:** ここには逃げ場はありません、マーフィーの法則があなたのプロダクションを容赦なく襲撃します
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: Node-chaosはあらゆる種類のNode.jsのいたずらを生成し、アプリのカオスへの耐性をテストできます
+
+
+
+
+
+## ⚪ ️2.7 グローバルなテストフィクスチャとシードを避け、テストごとにデータを追加する
+
+:white_check_mark: **こうしましょう:** ゴールデンルール(箇条書き0)に従うと、各テストは独自のDB行セットを追加し、それに基づいて動作し、結合を防ぎ、テストフローについて簡単に理由づけできるようにすべきです。現実には、パフォーマンス向上のためにテスト前にDBにデータをシード(いわゆる「テストフィクスチャ」)を行うテスターにより、このルールはしばしば違反されます。確かにパフォーマンスは正当な懸念ですが(「コンポーネントテスト」の箇条書きを参照)、テストの複雑さは他の考慮事項を支配すべき辛い問題です。実践的には、各テストケースが必要なDBレコードを明示的に追加し、それらのレコードのみに基づいて動作します。もしパフォーマンスが重要な懸念となった場合は、データを変化させない一部のテストスイート(例: クエリ)のみをシードするという形でバランスの取れた妥協があるかもしれません。
+
+
+❌ **さもなくば:** いくつかのテストが失敗し、デプロイが中止され、私たちのチームは貴重な時間を費やすことになり、「バグがありますか?」と調査することになり、とても大変です。そして、「あぁ、2つのテストが同じシードデータを変化させていました」と気づくのです。
+
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: テストが独立しておらず、グローバルなフックに依存してグローバルなDBデータを供給
+
+
+
+```javascript
+before(async () => {
+ // サイトと管理者データをDBに追加します。データはどこですか?外部です。いくつかの外部jsonまたは移行フレームワーク
+ await DB.AddSeedDataFromJson('seed.json');
+});
+it("サイト名を更新すると、成功の確認を得る", async () => {
+ // サイト名 "portal" が存在することを知っている - シードファイルでそれを見た
+ const siteToUpdate = await SiteService.getSiteByName("Portal");
+ const updateNameResult = await SiteService.changeName(siteToUpdate, "newName");
+ expect(updateNameResult).to.be(true);
+});
+it("サイト名でクエリすると、正しいサイトを取得する", async () => {
+ // サイト名 "portal" が存在することを知っている - シードファイルでそれを見た
+ const siteToCheck = await SiteService.getSiteByName("Portal");
+ expect(siteToCheck.name).to.be.equal("Portal"); // 失敗!前のテストで名前が変更された :[
+});
+
+```
+
+
+
+### :clap: 正しい例: テスト内で実施し続けられ、各テストは独自のデータセットで動作
+
+```javascript
+it("サイト名を更新すると、成功の確認を得る", async () => {
+ // テストは新しいレコードを追加し、レコードに対してのみ動作する
+ const siteUnderTest = await SiteService.addSite({
+ name: "siteForUpdateTest"
+ });
+ const updateNameResult = await SiteService.changeName(siteUnderTest, "newName");
+ expect(updateNameResult).to.be(true);
+});
+```
+
+
+
+# Section 3️⃣: フロントエンドテスティング
+
+## ⚪ ️3.1 UIと機能を分離する
+
+:white_check_mark: **こうしましょう:** コンポーネントロジックのテストに集中するときは、UIの詳細がノイズになり得るため取り除くべきです。これにより、テストが純粋なデータに焦点を当てられます。実際には、マークアップからグラフィックの実装にあまり結びつかない抽象的な方法で必要なデータを抽出し、純粋なデータ(HTML/CSSのグラフィック詳細ではなく)のみをアサートし、遅延を引き起こすアニメーションを無効にします。UIの裏側(例: サービス、アクション、ストア)のみをテストしてレンダリングを避けたくなるかもしれませんが、これは現実と似ていない架空のテストとなり、正しいデータがUIに届いていないケースを明らかにしません。
+
+
+
+❌ **さもなくば:** テストの純粋な計算データは10msで準備ができるかもしれませんが、関係のないアニメーションによって全体のテストが500ms(100のテスト = 1分)になるかもしれません。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: UIの詳細を分離
+
+ 
+
+```javascript
+test("users-listにVIPのみを表示するフラグが設定されている場合、VIPメンバーのみを表示する", () => {
+ // Arrange
+ const allUsers = [{ id: 1, name: "Yoni Goldberg", vip: false }, { id: 2, name: "John Doe", vip: true }];
+
+ // Act
+ const { getAllByTestId } = render(
+
+### :thumbsdown: アンチパターン例: アサーションがUIの詳細とデータを混合
+
+```javascript
+test("users-listにVIPのみを表示するフラグが設定されている場合、VIPメンバーのみを表示する", () => {
+ // Arrange
+ const allUsers = [{ id: 1, name: "Yoni Goldberg", vip: false }, { id: 2, name: "John Doe", vip: true }];
+
+ // Act
+ const { getAllByTestId } = render(
+
+## ⚪ ️3.2 変更する可能性が低い属性に基づいてHTML要素をクエリする
+
+:white_check_mark: **こうしましょう:** CSSセレクターやフォームラベルのようにグラフィックの変更にも耐える可能性がある属性に基づいてHTML要素をクエリします。指定された要素にそのような属性がない場合、 'test-id-submit-button' のような専用のテスト属性を作成します。この方法だと、機能/ロジックテストは外観の変更によって壊れることがなくなるだけでなく、この要素と属性がテストで使用され、そのため削除されるべきではないことがチーム全体に明確になります。
+
+
+
+❌ **さもなくば:** 多くのコンポーネント、ロジック、サービスにわたるログイン機能をテストしたいとき、準備は完璧 — スタブ、スパイ、Ajaxコールが孤立しています。すべては完璧に見えます。しかしデザイナーがdivのCSSクラスを 'thick-border' から 'thin-border' に変更したためにテストが失敗します。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しいやり方の例: テスト用に専用の属性を使用して要素をクエリ
+
+
+
+```html
+// マークアップコード(Reactコンポーネントの一部)
+
+
+```
+
+```javascript
+// この例はreact-testing-libraryを使用しています
+test("Whenever no data is passed to metric, show 0 as default", () => {
+ // Arrange
+ const metricValue = undefined;
+
+ // Act
+ const { getByTestId } = render(
+
+## :thumbsdown: アンチパターン例: CSS属性に依存する
+
+```html
+
+{value}
+
+```
+
+```javascript
+// この例はenzymeを使用しています
+test("Whenever no data is passed, error metric shows zero", () => {
+ // ...
+
+ expect(wrapper.find("[className='d-flex-column']").text()).toBe("0");
+});
+```
+
+
+
+## ⚪ ️3.3 可能な限り、リアルで完全にレンダリングされたコンポーネントでテストする
+
+:white_check_mark: **こうしましょう:** サイズが適切である限り、ユーザーが行うようにコンポーネントを外からテストし、UIを完全にレンダリングし、それに対して操作を行い、レンダリングされたUIが期待通りに動作することをアサートします。すべての種類のモック、部分的および浅いレンダリングを避けます — このアプローチは、詳細の欠如によるバグの見落としや、テストが内部に干渉するためメンテナンスを難しくする可能性があります(「ブラックボックステストを好む」を参照)。もし子コンポーネントの一つが著しく動作を遅くしたり(例: アニメーション)、セットアップを複雑にしたりする場合は、明示的に偽のものに置き換えることを検討してください。
+
+それに加えて、注意を要する言葉の一つがあります:この技術は、適切なサイズの子コンポーネントをパックしている小規模/中規模のコンポーネントに対して機能します。あまりに多くの子を持つコンポーネントを完全にレンダリングすることは、テストの失敗(根本原因の分析)についての説明を困難にしすぎることがあり、あまりにも遅くなる可能性があります。そのような場合、その大きな親コンポーネントに対してはいくつかのテストを行い、その子に対しては多くのテストを行います。
+
+
+
+❌ **さもなくば:** コンポーネントのプライベートメソッドを呼び出し、その内部状態をチェックすることによって、コンポーネントの内部をつつくとき、コンポーネントの実装をリファクタリングするときにすべてのテストをリファクタリングする必要があります。このレベルのメンテナンスを行う能力がありますか?
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: 完全にレンダリングされたコンポーネントをリアルに扱う
+
+ 
+
+```javascript
+class Calendar extends React.Component {
+ static defaultProps = { showFilters: false };
+
+ render() {
+ return (
+
+
+## ⚪ ️3.4 スリープせず、フレームワークの組み込みサポートを使って非同期イベントを処理し、可能な限り高速化する
+
+:white_check_mark: **こうしましょう:** テスト対象のユニットの完了時間が不明である場合が多くあります(例: アニメーションが要素の出現を遅延させる)。その場合、スリープ(例: setTimeOut)を避け、ほとんどのプラットフォームが提供するより決定論的なメソッドを利用します。一部のライブラリでは操作を待つことが許可されています(例: [Cypress cy.request('url')](https://docs.cypress.io/guides/references/best-practices.html#Unnecessary-Waiting))。他は[@testing-library/dom メソッド wait(expect(element))](https://testing-library.com/docs/guide-disappearance)のように待機用のAPIを提供しています。よりエレガントな方法としては、APIのような遅いリソースをスタブ化し、レスポンスのタイミングが決定論的になったときにコンポーネントを明示的に再レンダリングすることもあります。外部コンポーネントがスリープする場合、[時計を急がせる](https://jestjs.io/docs/en/timer-mocks)ことが有用な場合もあります。スリープはテストを遅くしたり(短い時間を待つときの場合)危険にしたりするため避けるべきパターンです。スリープやポーリングが避けられず、テストフレームワークのサポートがない場合は、[wait-for-expect](https://www.npmjs.com/package/wait-for-expect)のようなnpmライブラリが半決定論的な解決策を提供するのに役立つことがあります。
+
+
+❌ **さもなくば:** 長時間スリープする場合、テストは桁違いに遅くなります。小さな数でスリープしようとすると、テスト対象のユニットがタイムリーに反応しなかった場合にテストが失敗します。つまり、フレーク性と悪いパフォーマンス間のトレードオフに帰結します。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: 非同期操作が完了するときにのみ解決するE2E API (Cypress)
+
+
+
+
+```javascript
+// Cypressを使用
+cy.get("#show-products").click(); // ナビゲート
+cy.wait("@products"); // ルートが表示されるのを待つ
+// この行はルートが準備完了のときにのみ実行されます
+```
+
+### :clap: 正しい例: DOM要素を待機するテストライブラリ
+
+```javascript
+// @testing-library/dom
+test("映画タイトルが表示される", async () => {
+ // 要素は初期状態では存在しない...
+
+ // 表示を待つ
+ await wait(() => {
+ expect(getByText("the lion king")).toBeInTheDocument();
+ });
+
+ //表示を待って要素を返す
+ const movie = await waitForElement(() => getByText("the lion king"));
+});
+```
+
+### :thumbsdown: アンチパターン例: 独自のスリープコード
+
+```javascript
+test("映画タイトルが表示される", async () => {
+ // 要素は初期状態では存在しない...
+
+ // 独自の待機ロジック(注意: 単純すぎ、タイムアウトなし)
+ const interval = setInterval(() => {
+ const found = getByText("the lion king");
+ if (found) {
+ clearInterval(interval);
+ expect(getByText("the lion king")).toBeInTheDocument();
+ }
+ }, 100);
+
+ // 出現を待って要素を返す
+ const movie = await waitForElement(() => getByText("the lion king"));
+});
+```
+
+
+
+## ⚪ ️3.5 コンテンツがネットワークを介してどのように配信されるかを観察する
+
+
+
+✅ **こうしましょう:** 実際のネットワーク下でのページロードが最適化されていることを保証するアクティブモニターを適用します。これには、ページロードが遅かったりミニファイされていないバンドルなど、UXに関する懸念が含まれます。インスペクションツールの市場は豊富で、[pingdom](https://www.pingdom.com/)やAWS CloudWatch、[gcp StackDriver](https://cloud.google.com/monitoring/uptime-checks/)などの基本的なツールは、サーバーが存続し、合理的なSLAの下で応答するかどうかを監視するために簡単に設定できます。これだけでは間違いが発生する可能性がある多くの状況を網羅できないため、フロントエンドに特化し、よりリッチな分析を行うツールを選ぶことが望ましいです(例: [lighthouse](https://developers.google.com/web/tools/lighthouse/)、[pagespeed](https://developers.google.com/speed/pagespeed/insights/))。焦点はUXに直接影響を与える症状や指標、例えばページロード時間、[意味のあるペイント](https://scotch.io/courses/10-web-performance-audit-tips-for-your-next-billion-users-in-2018/fmp-first-meaningful-paint)、[ページの対話可能になるまでの時間(TTI)](https://calibreapp.com/blog/time-to-interactive/)などに置くべきです。加えて、コンテンツが圧縮されているか、最初のバイトまでの時間、画像の最適化、合理的なDOMサイズの確保、SSLなどの技術的な原因を監視することも重要です。これらのリッチなモニターを開発中、CIの一部として、そして最も重要なのは、プロダクションのサーバー/CDNを24時間365日監視することが推奨されます。
+
+
+
+❌ **さもなくば:** UIの制作に多大な注意を払い、100%の機能テストが合格し、洗練されたバンドルを行ったにもかかわらず、CDNの誤設定によりUXがひどく遅いと気付くのは失望です。
+
+
+
+✏ コード例
+
+### :clap: 正しい例: Lighthouseページロード検査レポート
+
+
+
+
+
+## ⚪ ️3.6 バックエンドAPIのような不安定で遅いリソースをスタブ化する
+
+:white_check_mark: **こうしましょう:** メインストリームのテスト(E2Eテストではない)をコーディングする際には、バックエンドAPIのように責任と制御を超えたリソースを関与させるのは避け、代わりにスタブ(つまりテストダブル)を使用します。実際には、APIへの実際のネットワーク呼び出しの代わりに、[Sinon](https://sinonjs.org/)や[Test doubles](https://www.npmjs.com/package/testdouble)のようなテストダブルライブラリを使ってAPIのレスポンスをスタブ化します。主な利点はフレーク性を防ぐことです。テストやステージングAPIは高い安定性がないため、時々、コンポーネントがしっかり動作しているにもかかわらず、テストが失敗することがあります(プロダクション環境はテスト目的で設計されておらず、通常リクエストを制限しています)。これを行うことで、データが見つからなかった場合やAPIがエラーを投げた場合のような、コンポーネントの動作を駆動するべき様々なAPIの動作をシミュレートできます。加えて、ネットワーク呼び出しはテストを大幅に遅くします。
+
+
+
+❌ **さもなくば:** 平均的なテストは数ミリ秒以内に終了しますが、典型的なAPI呼び出しは100ms以上です。これにより、各テストは約20倍遅くなります。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: API呼び出しのスタブまたはインターセプト
+
+ 
+
+```javascript
+// テスト対象のユニット
+export default function ProductsList() {
+ const [products, setProducts] = useState(false);
+
+ const fetchProducts = async () => {
+ const products = await axios.get("api/products");
+ setProducts(products);
+ };
+
+ useEffect(() => {
+ fetchProducts();
+ }, []);
+
+ return products ?
+
+## ⚪ ️3.7 システム全体に及ぶエンドツーエンドテストはごく少数にする
+
+:white_check_mark: **こうしましょう:** エンドツーエンド(E2E)は通常、実際のブラウザを使ったUIのみのテストを意味しますが(3.6を参照)、他の人々にとっては実際のバックエンドを含むシステム全体に及ぶテストを意味します。後者のタイプのテストは非常に価値があり、フロントエンドとバックエンドの統合バグをカバーしているため、データスキーマの誤解によって起こる可能性のある問題を防ぎます。また、バックエンド間の統合問題を発見する効率的な方法であり(例: マイクロサービスAがマイクロサービスBに誤ったメッセージを送信する)、デプロイメントの失敗を検出するためにも利用できます。UIフレームワークの[Cypress](https://www.cypress.io/)や[Puppeteer](https://github.com/GoogleChrome/puppeteer)のように、バックエンドのE2Eテストのための親しみやすく成熟したフレームワークは存在しません。このようなテストの欠点は、多くのコンポーネントを持つ環境の構成に高コストがかかること、そして多くの場合その脆さです。50のマイクロサービスのうち1つでも失敗すれば、E2E全体が失敗してしまいます。そのため、この手法は控えめに使用し、1〜10種類程度に留めるべきです。それでも、少数のE2Eテストであっても、デプロイメントと統合の不具合を検出する能力は高いです。プロダクションに近いステージング環境でこれらを実行することが推奨されます。
+
+
+
+❌ **さもなくば:** UIが自機能のテストに多大な投資をしても、バックエンドが返したペイロード(UIが扱うべきデータスキーマ)が期待とは大きく異なることに気付くのが非常に遅れるかもしれません。
+
+
+
+## ⚪ ️3.8 ログイン認証情報を再利用してE2Eテストを高速化する
+
+:white_check_mark: **こうしましょう:** 実際のバックエンドを含むE2Eテストで、API呼び出しに有効なユーザートークンが必要な場合、毎回ユーザーを作成してログインさせるようなレベルまでテストを分離するのは得策ではありません。代わりに、テスト実行開始前に一度だけログインし(before-allフックで)、トークンをローカルストレージに保存し、リクエスト間で再利用します。これはテストの基本原則の1つ、リソースの結合なしにテストを自律的に保つというものを違反しているように見えますが、E2Eテストでは性能が重要であり、個々のテストを開始する前に1〜3のAPIリクエストを生成することは、実行時間に大きな悪影響を与えるかもしれません。資格情報を再利用することは、テストが同じユーザーレコードで動作することを意味しません。ユーザーレコードに依存する(例: ユーザーの支払い履歴をテスト)場合は、それらのレコードをテストの一部として生成し、他のテストと共有しないようにしてください。また、バックエンドが偽装できることを忘れないでください。テストがフロントエンドに集中している場合は、それを分離してバックエンドAPIのスタブ化を検討する方が良い場合もあります([3.6節](https://github.com/goldbergyoni/javascript-testing-best-practices#-%EF%B8%8F-36-stub-flaky-and-slow-resources-like-backend-apis)を参照)。
+
+
+
+❌ **さもなくば:** 200のテストケースがあり、ログインに100msかかると仮定すると、ログインを繰り返すだけで合計20秒かかります。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: before-allでログインし、before-eachではしない
+
+
+
+```javascript
+let authenticationToken;
+
+// すべてのテストが実行される前に行われる
+before(() => {
+ cy.request('POST', 'http://localhost:3000/login', {
+ username: Cypress.env('username'),
+ password: Cypress.env('password'),
+ })
+ .its('body')
+ .then((responseFromLogin) => {
+ authenticationToken = responseFromLogin.token;
+ })
+})
+
+// 各テストが実行される前に行われる
+beforeEach(setUser => () {
+ cy.visit('/home', {
+ onBeforeLoad (win) {
+ win.localStorage.setItem('token', JSON.stringify(authenticationToken))
+ },
+ })
+})
+
+```
+
+
+
+## ⚪ ️3.9 サイトマップを巡回するだけのE2Eスモークテストを一つ持つ
+
+:white_check_mark: **こうしましょう:** 本番モニタリングや開発時の正常性チェックのために、すべてのページ、または大部分のサイトページを訪れ、何も壊れていないことを確認する単一のE2Eテストを実行します。このタイプのテストは、執筆と保守が非常に簡単でありながら、機能的、ネットワーク的、およびデプロイメントの問題を含むあらゆる種類の障害を検出できるため、非常に高い投資対効果をもたらします。他のスモークおよび正常性チェックのスタイルは信頼性や網羅性が劣ります。オペレーションチームの一部はホームページだけをpingする(本番環境)、または多くの統合テストを実行する開発者は、パッケージングやブラウザの問題を発見しないことがあります。もちろん、スモークテストは機能テストの代替ではなく、単に素早い問題検出を目指すものです。
+
+
+
+❌ **さもなくば:** すべてが完璧に見えるかもしれません、すべてのテストが通過し、本番のヘルスチェックも良好ですが、Paymentコンポーネントにはパッケージングの問題があり、/Paymentルートだけがレンダリングされない状況があります。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: すべてのページを巡るスモークテスト
+
+
+
+```javascript
+it("全ページでスモークテストを行うとき、すべて正常にロードされるべきである", () => {
+ // Cypressを使って示していますが、任意のE2Eスイートで簡単に実装できます
+ cy.visit("https://mysite.com/home");
+ cy.contains("Home");
+ cy.contains("https://mysite.com/Login");
+ cy.contains("Login");
+ cy.contains("https://mysite.com/About");
+ cy.contains("About");
+});
+```
+
+
+
+## ⚪ ️3.10 テストをライブ共同作業ドキュメントとして公開する
+
+:white_check_mark: **こうしましょう:** アプリの信頼性を向上させるだけでなく、テストはもう1つの魅力的な機会を提供します。それは、ライブのアプリドキュメントとして機能することです。テストは本質的に、技術的でなく製品/UXの言語で表現されるため、適切なツールを使用することで、開発者と顧客すべての仲間を大きく一致させるコミュニケーションアーティファクトとして役立つことができます。例えば、いくつかのフレームワークでは、人間が読みやすい言語を使ってフローと期待値(つまりテスト計画)を表現でき、製品管理者を含むあらゆるステークホルダーがテストを読み、承認し、協力できるので、テストはライブの要件ドキュメントになります。この手法は「受入テスト」とも呼ばれ、顧客が平易な言葉で受け入れ基準を定義できるようにします。これは[BDD(振る舞い駆動開発)](https://en.wikipedia.org/wiki/Behavior-driven_development)の最も純粋な形です。これを可能にする人気のフレームワークの1つが[Cucumber(JavaScript用のバージョンあり)](https://github.com/cucumber/cucumber-js)です。以下の例をご覧ください。もう1つの関連した機会として、[StoryBook](https://storybook.js.org/)は、UIコンポーネントをグラフィックカタログとして公開し、それぞれのコンポーネントの様々な状態をたどりながら、その見た目やその状態をトリガーする方法を提示することができます。これにより、製品の担当者にもアピールすることができ、主にそのコンポーネントを消費する開発者のためのライブドキュメントとして役立ちます。
+
+❌ **さもなくば:** テストにトップリソースを投資した後、この投資を活用して大きな価値を得られないのは、ただの悲劇です。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: cucumber-jsを用いて人間の言葉でテストを記述する
+
+
+
+```javascript
+// collaborateを使ったテストは、このように説明することができる。
+
+Feature: Twitter new tweet
+
+ I want to tweet something in Twitter
+
+ @focus
+ Scenario: Tweeting from the home page
+ Given I open Twitter home
+ Given I click on "New tweet" button
+ Given I type "Hello followers!" in the textbox
+ Given I click on "Submit" button
+ Then I see message "Tweet saved"
+
+```
+
+### :clap: 正しい例: Storybookを使用してコンポーネント、その様々な状態と入力を視覚化する
+
+
+
+
+
+
+
+## ⚪ ️3.11 自動化ツールで視覚的な問題を検出する
+
+:white_check_mark: **こうしましょう:** 変更がある場合にUIのスクリーンショットをキャプチャし、コンテンツの重なりや崩れといった視覚的な問題を検出するための自動化ツールをセットアップしましょう。これにより、正しいデータが用意されるだけでなく、ユーザーがそれを便利に見ることができるようになります。この手法は広く採用されているわけではありませんが、私たちのテストの思考法は機能テストに傾いているのに対し、視覚的な要素がユーザー体験であり、様々なデバイスタイプの存在によりいくつかの厄介なUIバグを見過ごすのは非常に簡単です。無料のツールでも基本を提供できます。つまり、人間の目による検査のためにスクリーンショットを生成・保存するということです。このアプローチは小規模なアプリには十分かもしれませんが、人間の労力を要求するあらゆる手動テストと同様に欠点があります。一方で、UIの問題を自動的に検出するのは非常に難しいため、この分野では'Visual Regression'が登場します。これは、古いUIと最新の変更を比較して違いを検出することでこのパズルを解決します。いくつかのOSS/無料ツールが基本的な機能を提供することができます(例: [wraith](https://github.com/BBC-News/wraith), [PhantomCSS](https://github.com/HuddleEng/PhantomCSS))が、セットアップにかなりの時間がかかるかもしれません。商用のツール(例: [Applitools](https://applitools.com/), [Percy.io](https://percy.io/))はさらに一歩進んで、インストールをスムーズにし、管理UI、アラート、'視覚的ノイズ'(例: 広告、アニメーション)を排除するスマートキャプチャー、問題を引き起こしたDOM/CSSの変更の根本原因分析といった高度な機能を搭載しています。
+
+
+
+❌ **さもなくば:** 素晴らしいコンテンツを表示し(100%のテストが合格)、瞬時にロードされるが、コンテンツエリアの半分が隠れているコンテンツページはどれほど良いでしょうか?
+
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: 提供され方が悪い典型的な視覚的回帰
+
+
+
+
+
+### :clap: 正しい例: wraithを設定してUIスナップショットをキャプチャし比較する
+
+
+
+```
+# 必要なだけドメインを追加します。キーがラベルとして機能します
+
+domains:
+ english: "http://www.mysite.com"
+
+# 以下にスクリーンの幅を入力します。いくつかの例を示します
+
+screen_widths:
+ - 600
+ - 768
+ - 1024
+ - 1280
+
+# 以下にページのURLパスを入力します。いくつかの例を示します
+paths:
+ about:
+ path: /about
+ selector: '.about'
+ subscribe:
+ path: /subscribe
+ selector: '.subscribe'
+```
+
+### :clap: 正しい例: Applitoolsを使用してスナップショットの比較やその他の高度な機能を利用する
+
+ 
+
+```javascript
+import * as todoPage from "../page-objects/todo-page";
+
+describe("visual validation", () => {
+ before(() => todoPage.navigate());
+ beforeEach(() => cy.eyesOpen({ appName: "TAU TodoMVC" }));
+ afterEach(() => cy.eyesClose());
+
+ it("should look good", () => {
+ cy.eyesCheckWindow("empty todo list"); // 空のToDoリストを確認
+ todoPage.addTodo("Clean room");
+ todoPage.addTodo("Learn javascript");
+ cy.eyesCheckWindow("two todos"); // 2つのToDoを確認
+ todoPage.toggleTodo(0);
+ cy.eyesCheckWindow("mark as completed"); // 完了としてマークをチェック
+ });
+});
+```
+
+
+
+# Section 4️⃣: テストの効果測定
+
+
+
+## ⚪ ️4.1 十分なカバレッジを確保して自信を持つ、〜80%が幸運な数字のよう
+
+:white_check_mark: **こうしましょう:** テストの目的は速く動くための十分な自信を得ることです。もちろん、より多くのコードがテストされればチームはより自信を持てます。カバレッジは、テストによってどれだけのコード行(およびブランチ、ステートメントなど)が到達されているかを測る指標です。では、どの程度が十分でしょうか?10–30%はビルドの正確性について判断するには明らかに低すぎ、逆に100%は非常に高価で、重大な経路からコードの珍しい隅に関心が移る可能性があります。長い答えとしては、多くの要因、例えばアプリケーションの種類によります。次世代のAirbus A380を構築するなら100%は必須ですが、漫画の画像サイトでは50%でさえ多すぎるかもしれません。ほとんどのテスト愛好家は、適切なカバレッジ閾値がコンテキストに依存すると主張しますが、多くの人が80%という数値を一般的なルールとして言及しています([Fowler: "上位の80または90%"](https://martinfowler.com/bliki/TestCoverage.html))、これはおそらくほとんどのアプリケーションを満足させるでしょう。
+
+実装のヒント: 継続的インテグレーション(CI)にカバレッジ閾値を設定し、これに準拠しないビルドを停止するように設定するかもしれません([Jestリンク](https://jestjs.io/docs/en/configuration.html#collectcoverage-boolean))。コンポーネントごとに閾値を設定することも可能です(下記のコード例を参照)。加えて、新しくコミットされたコードがカバレッジを減少している場合の検出を検討してください。これにより開発者はテストコードの量を増やすか、少なくとも維持するよう促されます。とは言え、カバレッジは一つの指標であり、定量的に基づいたもので、テストの堅牢性を伝えるには不十分です。そして、次の箇条書きで示すように、誤魔化されることもあります。
+
+
+
+❌ **さもなくば:** 自信と数字は密接な関係があり、システムのほとんどをテストしたと本当に知ることがなければ、恐怖が生まれ、その恐怖はあなたを遅くします。
+
+
+
+✏ コード例
+
+
+
+### :clap: 例: 典型的なカバレッジレポート
+
+
+
+
+
+### :clap: 正しい例: コンポーネントごとにカバレッジを設定する(Jestを使用)
+
+
+
+")
+
+
+
+## ⚪ ️4.2 カバレッジレポートを検査して未テストの領域やその他の異常を検出する
+
+:white_check_mark: **こうしましょう:** 一部の問題は見落とされ、伝統的なツールを使って見つけるのが非常に難しいです。これらは本当にバグではなく、重大な影響を及ぼす可能性のある驚くべきアプリケーションの挙動です。例えば、あるコードエリアがまったく呼び出されないか、ほとんど呼び出されないことがあります — ‘PricingCalculator’クラスが常に製品価格を設定していると思っていたのに、実際には一度も呼び出されていない、ということがあります。DBには10000の製品があり、多くの販売があるのに… コードカバレッジレポートはアプリケーションがあなたの思う通りに動作しているかどうかを理解するのに役立ちます。それ以外にも、どの種類のコードがテストされていないかを強調表示することができます — コードの80%がテストされたという情報では、重要な部分がカバーされているかはわかりません。レポートの生成は簡単です — カバレッジ追跡を付けて本番環境またはテスト中にアプリを実行し、各コードエリアがどのくらいの頻度で呼び出されるかを強調したカラフルなレポートを確認します。これに目を通す時間を取れば、いくつかの重要な発見をするかもしれません。
+
+
+
+❌ **さもなくば:** コードのどの部分がテストされていないかわからなければ、問題がどこから来る可能性があるかわかりません。
+
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: このカバレッジレポートの何が問題なのでしょうか?
+
+実際の事例に基づき、QAでアプリケーションの使用を追跡し、興味深いログインパターンを発見しました(ヒント: ログイン失敗の回数が不相応で、何かが明らかにおかしい。最終的には、あるフロントエンドのバグがバックエンドのログインAPIを繰り返し叩いていたことが判明しました)
+
+
+
+
+
+## ⚪ ️4.3 ミューテーションテストを使用して論理的カバレッジを測定する
+
+:white_check_mark: **こうしましょう:** 伝統的なカバレッジ指標はしばしば誤解を招きます。100%のコードカバレッジを示していても、関数がひとつも、正しい応答を返していない可能性があります。どうしてでしょう?それはテストがどのコード行を訪れたかを測定するだけで、実際にテストが何かを検証したかどうか — 正しい応答を確認したかを確認していないからです。ビジネスで旅行してパスポートのスタンプを見せる人のように — これはどんな仕事をしたかを証明しているわけではなく、単にいくつかの空港やホテルを訪れたことを示しているに過ぎません。
+
+ミューテーションベースのテストは、単に訪問しただけでなく、実際にテストされたコードの量を測定することによって助けになります。[Stryker](https://stryker-mutator.io/)はJavaScriptのミューテーションテスト用ライブラリで、実装は非常にスマートです:
+
+(1) コードを意図的に変更し、「バグを植え付ける」。例えば、コード `newOrder.price===0` を `newOrder.price!=0` に変える。この「バグ」を変異(mutations)と呼びます。
+
+(2) テストを実行し、すべて成功したら問題があります — テストはバグを発見するという目的を果たさなかったことを意味し、この変異は生き残ったことになります。テストが失敗したなら素晴らしい、変異は駆逐されました。
+
+すべてまたはほとんどのミューテーションが駆逐されたことを知っていることは、伝統的なカバレッジよりもはるかに高い信頼を与え、セットアップ時間は同様です。
+
+
+
+❌ **さもなくば:** 85%のカバレッジが、あなたのテストがコードの85%でバグを検出することを意味すると思い込まされます。
+
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターンの例: 100%のカバレッジ、0%のテスト
+
+
+
+```javascript
+function addNewOrder(newOrder) {
+ logger.log(`Adding new order ${newOrder}`);
+ DB.save(newOrder);
+ Mailer.sendMail(newOrder.assignee, `A new order was placed ${newOrder}`);
+
+ return { approved: true };
+}
+
+it("Test addNewOrder, don't use such test names", () => {
+ addNewOrder({ assignee: "John@mailer.com", price: 120 });
+}); //100%のコードカバレッジを引き起こしますが、何もチェックしていません
+```
+
+
+
+### :clap: 正しい例: 変異テストのためのツール、Strykerレポートは、テストされていないコードの量(変異)を検出し、カウントします
+
+を検出し、カウントします")
+
+
+
+## ⚪ ️4.4 テストリンターでテストコードの問題を防ぐ
+
+:white_check_mark: **こうしましょう:** ESLintプラグインのセットは、テストコードのパターンを検査して問題を発見するために特別に構築されました。例えば、[eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha)は、テストがグローバルレベル(describe()ステートメントの子ではない)で書かれている場合や、テストが[スキップ](https://mochajs.org/#inclusive-tests)されている場合に警告を出します。これにより、すべてのテストが通っているという誤った認識が生じる可能性があります。同様に、[eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest)は、テストに全くアサーションがない場合(何もチェックしていない)に警告を出すことができます。
+
+
+
+❌ **さもなくば:** 90%のコードカバレッジと100%のグリーンテストを見ると、顔が大きな笑顔に包まれますが、多くのテストが何もアサーションしておらず、多くのテストスイートがスキップされていることに気付くまでのことです。幸運を祈ることに、あなたがこの誤った認識に基づいて何もデプロイしていなかったことを。
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: エラーだらけのテストケース、幸いにもすべてリンターが検出
+
+```javascript
+describe("Too short description", () => {
+ const userToken = userService.getDefaultToken() // *エラー:no-setup-in-describe、代わりにフックを(慎重に)使用してください
+ it("Some description", () => {});//* エラー: valid-test-description. "Should"という単語を含む + 少なくとも5語
+});
+
+it.skip("Test name", () => {// *エラー:no-skipped-tests, エラー:error:no-global-tests. テストはdescribeまたはスイートの下にのみ配置
+ expect("somevalue"); // エラー:no-assert
+});
+
+it("Test name", () => {*//エラー:no-identical-title. テストにユニークなタイトルを割り当ててください
+});
+```
+
+
+
+# Section 5️⃣: CI 及びその他の品質基準
+
+
+
+## ⚪ ️ 5.1 リンターを充実させ、リントに問題がある時はビルドを止める
+
+:white_check_mark: **こうしましょう:** リンターはフリーランチです。5分のセットアップで、コードを守る自動操縦装置を無料で手に入れることができ、重要な問題をキャッチすることができます。 リンティングが装飾のためのものだった時代はもう終わりました。現在ではリンターは、正しくスローされないことによって情報が失われてしまうエラーのような深刻な問題を検知することができます。 [ESLint standard](https://www.npmjs.com/package/eslint-plugin-standard) や [Airbnb style](https://www.npmjs.com/package/eslint-config-airbnb) のような基本的なルールセットに加え、[eslint-plugin-chai-expect](https://www.npmjs.com/package/eslint-plugin-chai-expect) はアサーションのないテストを、[eslint-plugin-promise](https://www.npmjs.com/package/eslint-plugin-promise?activeTab=readme) は resolve しない promise を、[eslint-plugin-security](https://www.npmjs.com/package/eslint-plugin-security?activeTab=readme) は DOS 攻撃に使われる可能性のある正規表現を、[eslint-plugin-you-dont-need-lodash-underscore](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore) は Lodash の`_.map(…)`ような V8 コアメソッドの一部であるユーティリティーライブラリメソッドをコードが使用している場合に警告することができます。
+
+
+❌ **さもなくば:** 雨の日に、本番環境がクラッシュし続けているのに、ログにはエラーのスタックトレースが表示されていない場合を考えてみましょう。何が起こったのでしょうか?あなたのコードが誤ってエラーではないオブジェクトを投げてしまい、スタックトレースが失われたのです。そんなことが起こった日には、壁に頭を打ち付けたくなりますよね。5分間のリンターのセットアップでこのタイポを検出し、あなたの一日を救うことができます。
+
+
+
+✏ コード例
+
+
+
+### :thumbsdown: アンチパターン例: 間違ったエラーオブジェクトが誤ってスローされ、このエラーのスタックトレースは表示されません。幸運なことに、ESLint は次の本番環境でのバグをキャッチします。
+
+
+
+
+
+## ⚪ ️ 5.2 ローカルでの開発者とCIのフィードバックループを短くする
+
+:white_check_mark: **こうしましょう:** テスト、リンティング、脆弱性チェックなどの品質検査がピカイチのCIを使っていますか? 開発者がパイプラインをローカルで実行し即座にフィードバックを得られるようにして、[フィードバックループ](https://www.gocd.org/2016/03/15/are-you-ready-for-continuous-delivery-part-2-feedback-loops/) を短くしましょう。なぜか? 効率的なテストプロセスは、多くの反復的なループを構成しているからです。(1)トライアウト -> (2)フィードバック -> (3)リファクタリング。フィードバックが早ければ早いほど、開発者はモジュールごとに改善の反復回数が増え、結果を完璧にすることができます。逆に、フィードバックが遅くなると、1日にできる改善の反復回数が少なくなり、チームはすでに別のトピック/タスク/モジュールに進んでしまい、そのモジュールを改善する気にならないかもしれません。
+
+実際に、いくつかのCIベンダー(例:[CircleCI local CLI](https://circleci.com/docs/2.0/local-cli/)) は、パイプラインをローカルで実行することができます。[wallaby](https://wallabyjs.com/) のようないくつかの商用ツールは、開発者のプロトタイプとして非常に価値のあるテスト用のインサイトを提供しています。または、すべての品質チェックのコマンド(例:テスト、リント、脆弱性チェック)を実行するnpmスクリプトをpackage.jsonに追加するだけでも構いません。並列化のために [concurrently](https://www.npmjs.com/package/concurrently) のようなツールを使用し、ツールの1つが失敗した場合でも0以外の終了コードを返すようにしましょう。開発者は「npm run quality」などのコマンドを実行するだけで、即座にフィードバックを得ることができます。githookを使って品質チェックに失敗したときにコミットを中止することも検討してみましょう([husky](https://github.com/typicode/husky) が使えます)。
+
+
+❌ **さもなくば:** 品質チェックの結果がコードの翌日に出るようでは、テストは開発の一部ではなく、後付の形式的な成果物になってしまいます。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: コード品質のチェックを行うnpmスクリプトは、手動または開発者が新しいコードをプッシュしようとしているときに自動ですべて並行して実行されます。
+
+```javascript
+"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 本番環境のミラーでのe2eテストの実施
+
+:white_check_mark: **こうしましょう:** エンドツーエンド (e2e) テスティングは、すべてのCIパイプラインの主な課題です - 本番環境と同一の一時的な環境を、関連するすべてのクラウド・サービスと一緒にその場で作成するのは面倒でコストがかかります。最適な妥協案を見つけるのがあなたの仕事です: [Docker-compose](https://serverless.com/) は、1つのプレーンなテキストファイルを使用して、同一のコンテナで隔離されたdocker環境を作ることができますが、裏側の技術(例: ネットワークやデプロイメントモデル)は、実際の本番環境とは異なります。[`AWS Local`](https://github.com/localstack/localstack) と組み合わせることで、実際のAWSサービスのスタブを利用することができます。サーバーレスにした場合は、[serverless](https://serverless.com/) や [AWS SAM](https://docs.aws.amazon.com/lambda/latest/dg/serverless_app.html) などの複数のフレームワークにより、FaaSコードのローカル起動が可能になります。
+
+巨大なKubernetesのエコシステムでは、多くの新しいツールが頻繁に発表されていますが、ローカルおよびCI-ミラーリングのための標準的で便利なツールはまだ公式化されていません。1つのアプローチとして [Minikube](https://kubernetes.io/docs/setup/minikube/) や [MicroK8s](https://microk8s.io/) などのツールを使って`最小化されたKubernetes`を実行する方法があります。これらのツールは本物に似ていますが、オーバーヘッドが少ないのが特徴です。 他のアプローチとしては、リモートの`実際のKubernetes`上でテストする方法があります。いくつかのCIプロバイダー(例:[Codefresh](https://codefresh.io/)) はKubernetes環境とネイティブに統合されており、実際のKubernetes上でCIパイプラインを簡単に実行できます。他のプロバイダーはリモートのKubernetesに対してカスタムスクリプトを実行できます。
+
+
+❌ **さもなくば:** 本番環境とテスト環境で異なるテクノロジーを使用すると、2つのデプロイメントモデルを維持する必要があり、開発者と運用チームが分離されてしまいます。
+
+
+
+✏ コード例
+
+
+
+### :clap: 例: CIパイプライン上でその場でKubernetesクラスタを生成する ([出典: Dynamic-environments Kubernetes](https://container-solutions.com/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 テスト実行を並列化する
+
+:white_check_mark: **こうしましょう:** 正しい方法で行えば、テストは24時間365日ほぼ即座にフィードバックを提供してくれる友人です。 しかし、実践的には、1つのスレッドで500のCPUバウンドのユニットテストを実行するには時間がかかりすぎます。 幸いなことに、最新のテストランナーやCIプラットフォーム([Jest](https://github.com/facebook/jest) や [AVA](https://github.com/avajs/ava) 、[Mocha extensions](https://github.com/yandex/mocha-parallel-tests) のような)では、テストを複数のプロセスに並列化し、フィードバックまでの時間を大幅に改善することができます。CIベンダーの中には、テストをコンテナ間(!)で並列化するものもあり、これによりフィードバックループがさらに短縮されます。ローカルで複数のプロセスを使用しても、クラウドのCLIで複数のマシンを使用しても、それぞれが異なるプロセスで実行される可能性があるため、並列化によってテストを自律的に維持する必要があります。
+
+❌ **さもなくば:** 新しいコードをプッシュしてから1時間後にテストの結果が出るのでは、その頃には既に次の機能のコーディングをしているでしょうから、テストの効果を半減させてしまいます。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例: テストの並列化により、Mocha parallelとJestは従来のMochaを簡単に凌駕しました ([出典: JavaScript Test-Runners Benchmark](https://medium.com/dailyjs/javascript-test-runners-benchmark-3a78d4117b4))
+
+")
+
+
+
+## ⚪ ️5.5 ライセンスチェックと盗用チェックで法的問題を回避しよう
+
+:white_check_mark: **こうしましょう:** ライセンスや盗用の問題は、おそらく今は主な関心事ではないでしょうが、10分でこの項目を満たせるとしたらどうでしょう? [license check](https://www.npmjs.com/package/license-checker) や [plagiarism check](https://www.npmjs.com/package/plagiarism-checker) (商用利用可能な無料プラン)などのnpmパッケージは、CIパイプラインに簡単に組み込むことができ、制限付きライセンスの依存関係や、Stack Overflowからコピーペーストされたコードなど、明らかに著作権に違反しているコードを検査することができます。
+
+❌ **さもなくば:** 意図せずに不適切なライセンスのパッケージを使用したり、商用コードをコピーペーストしたりして、法的な問題が発生する可能性があります。
+
+
+
+✏ コード例
+
+
+
+### :clap: 正しい例:
+
+```javascript
+// license-checker をローカル又はCI環境にインストールしてください
+npm install -g license-checker
+
+// すべてのライセンスをスキャンし、未承認のライセンスを見つけた場合は0以外の終了コードで失敗するようにします。CI環境では、この失敗をキャッチして、ビルドを停止する必要があります。
+license-checker --summary --failOn BSD
+
+```
+
+
+
+
+
+
+
+## ⚪ ️5.6 脆弱性のある依存関係を常に検査する
+
+:white_check_mark: **こうしましょう:** Expressなどの最も信頼できる依存関係であっても、既知の脆弱性があります。これは、[npm audit](https://docs.npmjs.com/getting-started/running-a-security-audit) のようなコミュニティツールや、[snyk](https://snyk.io/) (無料のコミュニティバージョンもあります)のような商用ツールを使えば、簡単に解決できます。これらのツールは、ビルドのたびにCIから起動することができます。
+
+❌ **さもなくば:** 専用のツールを使わずにコードを脆弱性から守るには、新たな脅威に関するオンラインの情報を常にチェックする必要があります。非常に面倒です。
+
+
+
+✏ コード例
+
+
+
+### :clap: 例: NPM Audit の結果
+
+
+
+
+
+## ⚪ ️5.7 依存関係のアップデートを自動化する
+
+:white_check_mark: **こうしましょう:** Yarnとnpmのpackage-lock.jsonの導入は、深刻な課題をもたらしました(地獄への道は善意で敷かれています) - 標準では、パッケージはもはや更新されません。‘npm install’ と ‘npm update’ で何度もデプロイを繰り返すチームでも、新しいアップデートは得られません。その結果、依存パッケージのバージョンは良くても標準以下になり、最悪の場合は脆弱なコードになります。現在、チームは手動でpackage.jsonを更新するために開発者の善意と記憶力に頼っていたり、[ncu]((https://www.npmjs.com/package/npm-check-updates)) のようなツールを手動で使用しています。 より確実な方法は、最も信頼性の高い依存関係のバージョンを取得するプロセスを自動化することですが、まだ銀の弾丸のような解決策はありません。ただ、可能性のある自動化の道は2つあります:
+
+(1) CIで、[‘npm outdated’](https://docs.npmjs.com/cli/outdated) や‘npm-check-updates (ncu)’などのツールを使って、古い依存関係を持つビルドを失敗させます。これにより、開発者に依存関係の更新を強制することができます。
+
+(2) コードをスキャンして、依存関係を更新したプルリクエストを自動的に作成する商用ツールを使用します。残る一つの興味深い問題は、依存関係の更新ポリシーをどうするかということです。- パッチごとに更新するとオーバーヘッドが大きくなりすぎますし、メジャーリリース直後に更新すると不安定なバージョンになってしまう可能性もあるでしょう(多くのパッケージがリリース後数日で脆弱性が発見されています。[eslint-scopeのインシデント](https://nodesource.com/blog/a-high-level-post-mortem-of-the-eslint-scope-security-incident/) をみてください)。
+
+効率的なアップデートポリシーでは、いくつかの「権利確定期間」を設けることができます - ローカルが古くなったと判断する前に、コードを@latestよりもしばらく遅れたバージョンになるようにします(例:ローカルバージョンは1.3.1、リポジトリバージョンは1.3.8)。
+
+
+❌ **さもなくば:** 作成者によってリスクがあると明示的にタグ付けされたパッケージがプロダクションで実行されます。
+
+
+
+✏ コード例
+
+
+
+### :clap: 例: [ncu](https://www.npmjs.com/package/npm-check-updates) は手動またはCIパイプライン上で、コードがどの程度最新バージョンから遅れているかを検出するために使用できます。
+
+
+
+
+
+## ⚪ ️ 5.8 その他、Nodeに関連のないCIのTips
+
+:white_check_mark: **こうしましょう:** この記事は、Node JSに関連するか、少なくともNode JSで例示できるテストのアドバイスに焦点を当てています。ですがこの項目では、Nodeに関連しないけれどよく知られているCIのTipsをいくつかまとめて紹介します。
+
+
language: node_js+
node_js:
- "7"
- "6"
- "5"
- "4"
install:
- npm install
script:
- npm run test
Scott Davis 🖋 |
+ Adrien REDON 🖋 |
+ Stefano Magni 🖋 |
+ Yeoh Joer 🖋 |
+ Jhonny Moreira 🖋 |
+ Ian Germann 🖋 |
+ Hafez 🖋 |
+
Ruxandra Fediuc 🖋 |
+ Jack 🖋 |
+ Peter Carrero 🖋 |
+ Huhgawz 🖋 |
+ Haakon Borch 🖋 |
+ Jaime Mendoza 🖋 |
+ Cameron Dunford 🖋 |
+
John Gee 🖋 |
+ Aurelijus Rožėnas 🖋 |
+ Aaron 🖋 |
+ Tom Nagle 🖋 |
+ Yves yao 🖋 |
+ Userbit 🖋 |
+ Glaucia Lemos 🚧 |
+
koooge 🖋 |
+ Michal 🖋 |
+ roywalker 🖋 |
+ dangen 🖋 |
+ biesiadamich 🖋 |
+ Yanlin Jiang 🖋 |
+ sanguino 🖋 |
+
Morgan 🖋 |
+ Lukas Bischof ⚠️ 🖋 |
+ JuanMa Ruiz 🖋 |
+ Luís Ângelo Rodrigues Jr. 🖋 |
+ José Fernández 🖋 |
+ Alejandro Gutierrez Barcenilla 🖋 |
+ Jason 🖋 |
+
Otavio Araujo ⚠️ 🖋 |
+ Alex Ivanov 🖋 |
+ Yiqiao Xu 🖋 |
+