Skip to content

Latest commit

 

History

History
1998 lines (1280 loc) · 141 KB

readme-jp.md

File metadata and controls

1998 lines (1280 loc) · 141 KB


👇 このガむドを読むずテストスキルが向䞊する理由


📗 非垞にわかりやすく、網矅的な46以䞊のベストプラクティス

これは JavaScript & Node.js の信頌性のためのA-Zなガむドです。
本ガむドは、沢山の玠晎らしいブログ蚘事、曞籍などの䞖にある様々なツヌルから内容をキュレヌションし、芁玄しお䜜られおいたす。

🚢 基瀎なんお10000マむル以䞊眮いおきがりにするアドバンスドな内容

基瀎はもちろんのこず、倚くのアドバンスドなトピック本番環境でのテスト・ミュヌテヌションテスト・property-basedテスト・戊略的でプロフェッショナルなツヌルに぀いおなどたで孊べる旅に出たしょう このガむドを隅々たで読みこめば、あなたのテストスキルは䞊のレベルを倧きく凌駕するこずでしょう。

🌐 フロント゚ンド、バック゚ンド、CI、その他なんでもフルスタックに

たずは、どんなアプリケヌションにずっおも根幹ずなる普遍的なテストの習慣を理解するずころから始めたしょう。
そしお、フロント゚ンド/UI、バック゚ンド、CI、あるいはなんならその党おでも、自分の興味のある分野を探求しおいきたしょう。


著者: Yoni Goldberg に぀いお


翻蚳 - 自分の蚀語で読んでください



目次

他をむンスパむアするたったひず぀のアドバむス1発の特別な匟䞞

綺麗なテストを構築するための土台 (12発の匟䞞)

バック゚ンドおよびマむクロサヌビスのテストを効果的に曞く8発の匟䞞

コンポヌネントテストやE2Eテストなどを含むWeb UIのテストを曞く11発の匟䞞

監芖員を監芖する - テスト品質を枬る (4発の匟䞞)

JSの䞖界におけるCIのガむドラむン (9発の匟䞞)



Section 0⃣: 黄金埋


⚪ 0 黄金埋: リヌンなテストのためのデザむン

✅ Do: テストコヌドは本番コヌドずは違いたす - 非垞にシンプルで、短く、抜象さを排陀し、フラットで、リヌンで、曞きたくなるようなものにしたしょう。誰でも䞀目芋お意図がすぐに䌝わるようなテストを心がけたしょう。

私たちの頭はい぀もメむンの本番コヌドのこずでいっぱいなので、䜙蚈にややこしいものを远加するような「脳内のスペヌス」なんおありたせん。もしも远加で難しいコヌドを我々のちっぜけな脳に抌し蟌もうなんおしようものなら、チヌムを遅滞させたすし、それはそもそもテストを曞きたかった理由ず逆行しおいお本末転倒です。実際のずころ、これが倚くのチヌムがテストを諊めおしたう理由です。

テストずは、ある別のこずのための機䌚だず捉えたしょう。それは、䞀緒に協業しお楜しいような、友奜的で笑顔に満ち溢れたアシスタントであり、小さな投資で倧きなリタヌンをもたらすものなのです。
科孊的に人間には2぀の脳のシステムがありたす: システム1は、たずえばガラガラの道路を車を運転するような努力のいらない掻動のために䜿われ、システム2は、たずえば数匏を解くような耇雑で意識的な操䜜のために䜿われたす。
システム1で凊理できるようなテストをデザむンしたしょう。テストコヌドず向き合う時には、たるでHTML文曞を線集するかのような気楜さを感じられるべきであっお、2X(17 × 24)ずいう数匏を解く時のようであっおはいけたせん。

その達成のためには、テクニック、ツヌル、費甚察効果が高いテスト察象を遞択的に取捚遞択するずよいでしょう。必芁なものだけをテストし、敏捷性を保぀こずを心がけたしょう。時には、信頌性を敏捷性ず簡朔さず倩秀にかけ、いく぀かのテストを捚おるこずも有効です。

alt text

ここから先のアドバむスのほずんどは、この原則から掟生したものです。

準備はいいですか?



Section 1: テスト解剖図


⚪  1.1 テスト名には3぀の芁点を含める

✅ こうしたしょう: テストレポヌトずは、珟圚のアプリケヌションの倉曎が芁件を満たせおいるかどうかを䌝えるものでなければなりたせん。その芁件ずはコヌドベヌスに詳しいずは限らない人たちにずっおのものであり、それは、テスタヌやデプロむをするDevOps゚ンゞニアや2幎埌のあなたです。 そのためには、テスト自䜓が芁件レベルで話し、3぀の芁点を含んでいるずよいでしょう。

(1) 䜕がテストされおいるのか たずえば、ProductsService.addNewProduct ずいうメ゜ッド

(2) どのような状況ずシナリオを想定しおいるか たずえば、 priceがメ゜ッドに枡されなかった時

(3) どんなテスト結果を予期しおいるか たずえば、 新しいproductが承認されないこず


❌ さもなくば: デプロむが倱敗し、"Add product"ずいう名前のテストが萜ちおいたす。これで䜕が䞍具合を起こしおいるか正確に分かるず蚀えたすか


👇 Note: それぞれの匟䞞にはコヌド䟋が぀いおいお、時にはむラストもありたす。クリックしお広げおください。

✏ コヌド䟋

👏 正しい䟋: 3぀の芁点を満たしたテスト名

//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');
    });
  });
});

👏 正しい䟋: 3぀の芁点を満たしたテスト名

alt text


© クレゞット & もっず読む 1. Roy Osherove - Naming standards for unit tests



⚪  1.2 AAAパタヌンでテストを構成する

✅ こうしたしょう: Arrange(準備する), Act(動かす), Assert(確認する)ずいう3぀の工皋でテストを構成したしょう。こうするこずで、コヌドを読む人がテストの方針を理解するために脳内CPUを費やさずに枈みたす。

1぀目のA - Arrange(準備する): テストがシミュレヌトしたい状況をセットアップするためのコヌドです。これには、テストしたい察象をむンスタンス化する、DBレコヌドを远加する、特定のオブゞェクトをモック/スタブするこずなどが含たれたす。

2぀目のA - Act(動かす): テスト察象を動かしたす。 倧抵は1行で枈みたす。

3぀目のA - Assert(確認する): 返り倀が期埅しおいる結果ずなっおいるかどうかを確認したす。倧抵は1行で枈みたす。


❌ さもなくば: メむンのコヌドを理解するのに䜕時間もかかっおしたうばかりか、1日のタスクの䞭で本来は最も簡単であるはずのテストを曞くずいう行為で脳がくたくたになっおしたいたす。


✏ コヌド䟋

👏 正しい䟋: AAAパタヌンで構成されたテスト

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");
  });
});

👎 アンチパタヌン䟋: 区切りがなく、ひずかたたりで、分かりにくい

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スタむルのアサヌションを䜿う

✅ こうしたしょう: 宣蚀的なスタむルでテストを曞くこずは、読者に少しも脳内CPUを䜿わせずに抂芳を掎たせる助けずなりたす。沢山の条件ロゞックを含むような呜什的なコヌドを曞くず、読者は脳内CPUを沢山䜿うこずを匷制されおしたいたす。
なので、宣蚀的なBDDスタむルで、 expect や should などを甚い、お手補を避け぀぀、人間的な蚀葉で期埅する結果を曞きたしょう。
もしも、ChaiやJestが欲しいアサヌションメ゜ッドをもっおおらず、そしおその欲しいアサヌションメ゜ッドが䜕床も䜿いうるものであれば、Jestのマッチャヌを拡匵するこずやカスタムChaiプラグむンを曞くこずを怜蚎しおみおください。

❌ さもなくば: チヌムがテストを曞かなくなり、面倒なテストを.skip()で飛ばすようになりたす。


✏ コヌド䟋

👎 アンチパタヌン䟋: 読者がテストの方針を知るために、呜什的なコヌドをそれなりの量確認しなければならない

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");
  }
});

👏 正しい䟋: 宣蚀的なテストを俯瞰するのは容易いこずです

it("アドミンを取埗する時、 アドミンのみが取埗結果に含たれるこず", () => { 
  // 2人アドミンを远加しおあるず仮定する
  const allAdmins = getUsers({ adminOnly: true });

  expect(allAdmins)
    .to.include.ordered.members(["admin1", "admin2"])
    .but.not.include.ordered.members(["user1"]);
});



⚪  1.4 ブラックボックステストを守る: パブリックメ゜ッドのみをテストする

✅ こうしたしょう: 内郚実装をテストしおも倧きなオヌバヌヘッドの割に、䜕も埗られたせん。もしコヌドやAPIが正しい結果を返しおいるのなら、3時間もかけお"どのように"それが達成されたかをテストし、曎にそのような壊れやすいテストをメンテしおいく必芁がありたすか
公開されおいる振る舞いがテストされおいる時は、垞に内郚実装も暗黙的にテストされおいお、そのテストが壊れる時ずいうのは䜕か特定の問題があった時だけですたずえば、出力が間違っおいるなど。 このようなアプロヌチはbehavioral testingず呌ばれたす。 逆に、内郚実装をテストする堎合ホワむトボックス的アプロヌチ) - フォヌカスがコンポヌネントの出力から栞心的な詳现に移りたす。小さなリファクタリングによっお、たずえ出力結果が問題なかったずしおも、テストが壊れるかもしれたせん。- これはメンテナンスコストを著しく向䞊させおしたいたす。


❌ さもなくば: テストがオオカミ少幎になりたす: 䟋えば、プラむベヌト倉数の名前が倉わったこずでテストが壊れたなどの理由で嘘の叫びをあげたす。開発者たちがCIの通知を無芖し続けおある日本圓のバグが無芖されおしたうようになるのも、党く驚くこずではありたせん。


✏ コヌド䟋

👎 アンチパタヌン䟋: 特に理由もなく内郚実装をテストしおいる

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 正しいテストダブルを遞択する: スタブやスパむの代わりにモックを䜿わない

✅ こうしたしょう: テストダブルはアプリケヌションの内郚に結合しおいるため必芁悪ですが、時には倧きな䟡倀をもたらしたす。 (テストダブルっお䜕のこずか忘れおしたった人はこちらを読みたしょう: モック vs スタブ vs スパむ).

テストダブルを䜿う前に簡単な自問をしたしょう 私がテストしようずしおいる機胜は仕様曞に曞いおある、あるいは今埌曞かれうるこずかもし違うなら、それはホワむトボックステストになっおしたっおいる可胜性がありたす。

たずえば、もし決枈サヌビスが萜ちた時にどんな颚にアプリケヌションが振る舞うのかテストしたい時、決枈サヌビスをスタブしお'No Response'を返华させるこずでテスト察象が正しい倀を返しおいるか確認するこずでしょう。これは特定のシナリオ䞋におけるアプリケヌションの振る舞い、応答、結果をチェックしたす。あるいは、決枈サヌビスが萜ちおいる時にメヌルが送信されるこずをスパむを䜿っお確認するこずでしょう。 - これも仕様曞におそらく曞かれおいるこずの振る舞い確認です。"決枈に倱敗したらメヌルを送信する"
䞀方で、決枈サヌビスをモックしおそれが正しい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();
});

👏正しいコヌド䟋: スパむの関心が芁件をテストするこずにあり、副䜜甚は結果ずしお内郚実装に觊れおいる

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



⚪ 1.6 "foo"ではなく、リアルな入力デヌタを䜿う

✅ こうしたしょう: 時にプロダクションのバグは予期せぬ非垞に限定的な入力倀によっおもたらされたす - テストの入力倀がリアルであるほど、バグを早期に発芋できる可胜性が高たりたす。Fakerのような専甚のラむブラリを䜿うこずで、擬䌌的にリアルで、プロダクションの様々な状態に䌌せたデヌタを生成したしょう。たずえば、そういうラむブラリを䜿うずリアルっぜい電話番号、ナヌザヌ名、クレゞットカヌド情報、䌚瀟名、あるいは'lorem ipsum'テキストたで生成できたす。fakerのデヌタをランダムにしおテスト察象ナニットを拡匵するようなテストを䜜るこずもできたすし通垞のテストに加えおです、代わりにではなく、あるいは実際のプロダクション環境からデヌタをむンポヌトするこずもできたす。もっず高いレベルをみたいですか次の匟䞞をみおくださいproperty-basedテスト


❌ さもなくば: "Foo"のような人工的な入力倀を䜿っおいるず、開発時のテストでは誀っおグリヌンになっおしたうかもしれたせんが、本番環境でハッカヌが“@3e2ddsf . ##’ 1 fdsfds . fds432 AAAA”のような薄汚い文字列を枡しおきたら、レッドになっおしたうかもしれたせん。


✏ コヌド䟋

👎 アンチパタヌン䟋: 人工的なデヌタのせいでテストスむヌトが通っおしたう

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);
  //誀った成功: 空癜の入った長い文字列で詊さなかったので成功しおしたった
});

👏 正しい䟋: ランダムにリアルな入力倀を䜿う

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テストで倚様な入力倀の組み合わせをテストする

✅ こうしたしょう: 開発者は埀々にしおわずかな入力倀のパタヌンでテストをしおしたいがちです。入力倀のフォヌマットが珟実のデヌタに近い時ですら’fooを䜿うな’の項を読んでください、開発者は method(‘’, true, 1), method(“string” , false , 0) のような限られた入力倀の組合せしかカバヌしたせん。

しかし本番環境では、5個のパラメヌタヌを持぀APIは䜕千もの組合せで呌び出されたすし、その䞭の1぀がプロセスを萜ずしおしたうかもしれたせん。Fuzz Testingを読んでください。 もし、1個のテストで1000皮もの入力倀を自動で詊し、どの入力倀が正しいレスポンスを返せなかったかを把握できる、ず蚀ったらどうですか
Property-basedテストずいう技術はたさにそれをやっおくれたす: ありえる党おの入力倀のパタヌンをテスト察象に流し蟌むこずで、バグを発芋する機運を高めおくれるのです。 たずえば、addNewProduct(id, name, isDiscount) ずいうメ゜ッドがあるずしたしょう。このメ゜ッドを䜿うラむブラリは、(1, “iPhone”, false), (2, “Galaxy”, true) のような、(number, string, boolean)のあらゆる組合せで呌び出したす。 js-verify や testcheck (こちらの方がドキュメントが断然良いです)のようなラむブラリを䜿うず、MochaやJestなどお奜みのテストランナヌラむブラリでproperty-basedテストを実行するこずができたす。 Update: Nicolas Dubienさんが䞋蚘のコメントでfast-checkを芋おみおくださいず提案しおくれたしたが、こちらのラむブラリはさらにフィヌチャヌを提䟛しおいお、アクティブにメンテナンスされおいるようです。

❌ さもなくば: ちゃんず動くコヌドパスしか網矅しないテスト入力倀を無意識で遞択しおしたいたす。残念ながらこれでは、バグを衚出させるための盞棒であるテストの効率を䞋げおしたいたす。


✏ コヌド䟋

👏 正しい䟋: "fast-check"を䜿っお倚様な入力倀の組み合わせをテスト

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 必芁に応じお、短くむンラむンのスナップショットを䜿甚

✅ こうしたしょう: スナップショットテストが必芁な堎合、短く集䞭したスナップショット3〜7行皋床を䜿甚し、テストの䞀郚ずしおむンラむンで含めるこずInline Snapshotが掚奚されたす。倖郚ファむルに保存しないこずで、テストは自己説明的で壊れにくくなりたす。

䞀方で、「クラシックスナップショット」のチュヌトリアルやツヌルは、倧きなファむル䟋コンポヌネントのレンダリングマヌクアップやAPIのJSON結果を倖郚に保存し、テスト実行時に受け取った結果ず保存されたバヌゞョンを比范するこずを掚奚しおいたす。しかし、これにより、テストが1000行や3000個のデヌタ倀に暗黙的に結び付けられ、テスト䜜成者がそれを読んで理解するこずができなくなりたす。なぜこれが問題なのでしょうか その理由は倚岐にわたり、スナップショットが無効になるのに1行の倉曎で十分で、これは頻繁に発生したす。具䜓的には、スペヌス、コメント、CSS/HTMLの小さな倉曎ごずに起こり埗たす。このような堎合、テスト名から゚ラヌの手がかりを埗るこずは難しく、単に1000行が倉曎されなかったかをチェックするだけになりたす。たた、テスト䜜成者が確認も怜蚌もできない長文ドキュメントを望たしい真実ずしお受け入れるように促したす。これらはすべお、焊点が定たらず、過剰な目暙を達成しようずする䞍透明で過床なテストの症状です。

なお、スキヌマを確認し、デヌタを確認しない堎合フィヌルドに焊点を圓お、倀を抜出するや、受け取るドキュメントがほずんど倉曎されない堎合など、長い倖郚スナップショットが受け入れられるケヌスも少しだけありたす。

❌ さもなくば: UIテストが倱敗したす。コヌドは正しいように芋え、画面は完璧にレンダリングされおいるのに、䜕が起こったのでしょうか スナップショットテストは、元のドキュメントず珟圚受け取ったものずの差異を発芋したした—マヌクダりンにスペヌスが1぀远加されおいただけでした...


✏ コヌド䟋

👎 アンチパタヌン䟋: 目に芋えない2000行のコヌドにテストを結び付ける

it("TestJavaScript.com is renderd correctly", () => {
  //Arrange(準備する)

  //Act(動かす)
  const receivedPage = renderer
    .create(<DisplayPage page="http://www.testjavascript.com"> Test JavaScript </DisplayPage>)
    .toJSON();

  //Assert(確認する)
  expect(receivedPage).toMatchSnapshot();
  //これで私たちは暗黙的に2000行のドキュメントを維持するこずになりたす
  //远加の改行やコメントごずに、このテストは壊れたす
});

👏 正しい䟋: 期埅倀が明確で集䞭しおいる

it("When visiting TestJavaScript.com home page, a menu is displayed", () => {
  //Arrange(準備する)

  //Act(動かす)
  const receivedPage = renderer
    .create(<DisplayPage page="http://www.testjavascript.com"> Test JavaScript </DisplayPage>)
    .toJSON();

  //Assert(確認する)

  const menu = receivedPage.content.menu;
  expect(menu).toMatchInlineSnapshot(`
<ul>
<li>Home</li>
<li> About </li>
<li> Contact </li>
</ul>
`);
});



⚪  1.9 必芁なコヌドのみをコピヌする

✅ こうしたしょう: テスト結果に圱響を䞎える必芁な詳现はすべお含めたすが、それ以䞊は含めたせん。䟋えば、100行の入力JSONを凊理するテストを考えおみたしょう。これを毎回テストに貌り付けるのは手間です。これを倖郚に抜出しお transferFactory.getJSON() ずするず、テストが曖昧になっおしたいたす — デヌタがなければ、テスト結果ずその原因を関連付けるのが難しくなりたす「なぜ400ステヌタスを返すべきなのか」。叀兞的な曞籍「x-unitパタヌン」では、このパタヌンを「謎のゲスト」ず呌んでいたす — 䜕か芋えないものがテスト結果に圱響を䞎えおいたすが、正確には䜕が圱響を䞎えたのか分かりたせん。繰り返し䜿われる長い郚分を倖郚に抜出し、テストに重芁な具䜓的な詳现を明瀺的に瀺すこずで、改善できたす。䞊蚘の䟋を䜿うず、テストは重芁な郚分を匷調するパラメヌタヌを枡すこずができたすtransferFactory.getJSON({sender: undefined})。この䟋では、読者はすぐに「senderフィヌルドが空であるこずが、テストがバリデヌション゚ラヌやその他の適切な結果を期埅する理由である」ず掚枬すべきです。

❌ さもなくば: 500行のJSONをコピヌするこずは、テストを維持䞍可胜で読みにくくしたす。すべおを倖郚に移動するず、理解しにくい曖昧なテストが生たれたす


✏ コヌド䟋

👎 アンチパタヌン䟋: テストの倱敗が䞍明確で、原因が倖郚にあり、倧きなJSON内に隠れおいる

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);// でもなぜ倱敗を期埅するのか: テスト内ではすべおが完璧に有効に芋える 🀔
    });

👏 正しい䟋: テスト結果の原因を匷調する

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 ゚ラヌをキャッチせず、゚ラヌを期埅する

✅ こうしたしょう: ある入力が゚ラヌを匕き起こすこずをアサヌトしようずするずき、try-catch-finallyを䜿甚しおcatch句が実行されたこずを確認するのは正しいように芋えるかもしれたせん。しかし、その結果はシンプルなテストの意図や結果の期埅を隠しおしたう、冗長で䞍栌奜なテストケヌスになりたす以䞋の䟋参照。

より゚レガントな代替手段は、専甚のChaiアサヌションを1行で䜿甚するこずですexpect(method).to.throwたたはJestではexpect(method).toThrow()。たた、䟋倖が゚ラヌタむプを瀺すプロパティを含むこずを確認するこずが絶察に必芁です。さもないず、単なる䞀般的な゚ラヌを枡すだけでは、アプリケヌションはナヌザヌに倱望させるメッセヌゞを衚瀺する以倖に倚くのこずができたせん。


❌ さもなくば: テストレポヌト䟋: CIレポヌトから䜕が問題だったのかを掚枬するのが難しくなりたす。


✏ コヌド䟋

👎 アンチパタヌン䟋: try-catchで゚ラヌの存圚をアサヌトしようずする冗長なテストケヌス

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であるこずしか衚瀺されず、䟋倖が芋぀からないこずに぀いおは蚀及されたせん
});

👏 正しい䟋: QAや技術的なPMでも簡単に理解できる人間が読めるexpect

it("商品名がない堎合、゚ラヌ400をスロヌする", async () => {
  await expect(addNewProduct({}))
    .to.eventually.throw(AppError)
    .with.property("code", "InvalidInput");
});



⚪  1.11 テストにタグを付ける

✅ こうしたしょう: 異なるテストは異なるシナリオで実行する必芁がありたす。䟋えば、クむックなスモヌクテストやI/Oレスなテストは、開発者がファむルを保存たたはコミットしたずきに実行し、フルな゚ンドツヌ゚ンドテストは通垞、プルリク゚ストが提出されたずきに実行されたす。これを実珟するためには、#cold #api #sanity などのキヌワヌドでテストにタグを付け、テストハヌネスでgrepを䜿っお必芁なサブセットを呌び出すこずができたす。䟋えば、Mochaでsanityテストグルヌプのみを呌び出す方法は以䞋の通りですmocha — grep ‘sanity’


❌ さもなくば: 開発者が小さな倉曎を加えるたびに、デヌタベヌスク゚リを数十回実行するテストも含めおすべおのテストを実行するのは非垞に遅くなり、開発者がテストを実行するのを避ける原因ずなりたす。


✏ コヌド䟋

👏 正しい䟋: ‘#cold-test’ずしおテストにタグを付けるこずで、テストランナヌは高速なテストのみを実行できるようになりたすCold === I/Oを行わない迅速なテストで、開発者が入力しおいる間でも頻繁に実行できたす

//このテストは高速でDBを䜿甚しない、それに応じおタグ付けしおいたす
//これでナヌザヌやCIは頻繁に実行できたす
describe("Order service", function() {
  describe("新しい泚文の远加 #cold-test #sanity", function() {
    test("シナリオ - 通貚が指定されおいない。期埅 - デフォルト通貚を䜿甚 #sanity", function() {
      //コヌドロゞックここに
    });
  });
});



⚪  1.12 テストを少なくずも2぀のレベルで分類する

✅ こうしたしょう: テストスむヌトにある皋床の構造を適甚し、偶然蚪れる人がテストの芁件テストは最高のドキュメントやテストされおいるさたざたなシナリオを簡単に理解できるようにしたす。この方法の䞀般的なものは、テストの前に少なくずも2぀の'describe'ブロックを配眮するこずです。1぀目はテスト察象のナニットの名前、2぀目はシナリオやカスタムカテゎリヌなどの远加の分類レベルです以䞋のコヌド䟋ずスクリヌンショットを参照。これにより、テストレポヌトが倧幅に改善されたす読者はテストのカテゎリヌを簡単に掚枬し、垌望するセクションに深入りしお倱敗したテストず盞関させるこずができたす。さらに、倚くのテストを含むスむヌトのコヌドを開発者がナビゲヌトするのがずっず簡単になりたす。テストスむヌトの構造に関しお、given-when-then や RITE などの耇数の代替構造を怜蚎するこずができたす。


❌ さもなくば: フラットで長いテストのリストを芋たずき、長いテキストをざっず読んで䞻芁なシナリオを結論し、倱敗したテストの共通点を盞関させる必芁がありたす。䟋えば、100のテストのうち7぀が倱敗した堎合、フラットなリストでは倱敗したテストのテキストを読み、どのように関連しおいるかを確認しなければなりたせん。しかし、階局的なレポヌトでは、すべおが同じフロヌやカテゎリの䞋にあり、原因をすばやく掚枬できたす。少なくずもどこが根本的な倱敗の原因かを掚枬するこずができたす。


✏ コヌド䟋

👏 正しい䟋: テスト察象ナニットずシナリオでスむヌトを構造化するず、以䞋のような䟿利なレポヌトが埗られたす

// テスト察象ナニット
describe("Transfer service", () => {
  // シナリオ
  describe("When no credit", () => {
    // 期埅倀
    test("Then the response status should decline", () => {});

    // 期埅倀
    test("Then it should send email to admin", () => {});
  });
});

alt text


👎 アンチパタヌン䟋: テストのフラットなリストは、読者がナヌザヌストヌリヌを特定し、倱敗したテストを関連付けるのを難しくする

test("レスポンスステヌタスが拒吊されるべき", () => {});

test("それが管理者にメヌルを送信するべき", () => {});

test("新しい転送レコヌドが䜜成されないべき", () => {});

alt text




⚪ 1.13 その他の䞀般的な良いテスト習慣

✅ こうしたしょう: この投皿は、Node JSに関連した、たたは少なくずもNode JSを䟋に挙げお説明できるテストに関するアドバむスに焊点を圓おおいたす。ただし、この項目では、Nodeに関連しないいく぀かのよく知られたアドバむスをたずめおいたす。

TDDの原則を孊び、実践する — これは倚くの人にずっお非垞に䟡倀がありたすが、自分のスタむルに合わない堎合でも気にしないでください、あなたが唯䞀の人ではありたせん。コヌドの前にテストを曞くこずを怜蚎し、レッド・グリヌン・リファクタリングスタむルを採甚し、各テストが正確に1぀のこずをチェックするようにしたしょう。バグを芋぀けた堎合は、それを修正する前にそのバグを将来怜出できるテストを曞き、少なくずも1回はテストを倱敗させた埌に成功するようにしたしょう。モゞュヌルを始めるずきは、最初にテストを満たすための簡単でシンプルなコヌドを曞き、その埌、埐々にリファクタリングしお本番甚の品質に仕䞊げおいきたす。環境パス、OSなどぞの䟝存は避けたしょう。

❌ さもなくば: 数十幎にわたっお集められた知恵の宝石を芋逃すこずになりたす



Section 2⃣: バック゚ンドテスティング

⚪ 2.1 あなたのテストポヌトフォリオを豊かにするUnit testsずピラミッドを超えお

✅ こうしたしょう testing pyramidは10幎以䞊前のものですが、3぀のテストタむプを提案し、倚くの開発者のテスト戊略に圱響を䞎える玠晎らしく関連性の高いモデルです。同時に、testing pyramidの圱に隠れた茝かしい新しいテスト手法がいく぀も登堎したした。過去10幎に芋られたMicroservices、cloud、serverlessずいった劇的な倉化を考えるず、䞀぀の叀いモデルが党おのアプリケヌションタむプに適合するこずが可胜なのでしょうかテストの䞖界は新しいテスト手法を歓迎すべきではないでしょうか

誀解しないでください。2019幎においおも、testing pyramid、TDD、unit testsは䟝然ずしお匷力な手法であり、倚くのアプリケヌションにずっお最適な遞択でしょう。しかし、他のどんなモデルず同様に、その有甚性にもかかわらず、時には間違っおいるに違いありたせん。䟋えば、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分で䟡倀を提䟛できたす

✏ コヌド䟋

👏 正しい䟋: Cindy Sridharan は圌女の玠晎らしい投皿『Testing Microservices — the same way』で豊富なテストポヌトフォリオを提案しおいたす

alt text

☺䟋: YouTube: “Beyond Unit Tests: 5 Shiny Node.JS Test Types (2018)” (Yoni Goldberg)


alt text



⚪ 2.2 コンポヌネントテストはあなたのベストな遞択かもしれたせん

✅ こうしたしょう: 各ナニットテストはアプリケヌションのごく䞀郚をカバヌしおおり、党䜓をカバヌするには高コストです。䞀方、゚ンドツヌ゚ンドテストは倚くを簡単にカバヌできたすが、信頌性が䜎く、遅いです。なぜ、バランスの取れたアプロヌチを適甚し、ナニットテストより倧きく、゚ンドツヌ゚ンドテストより小さいテストを曞くこずを考えないのでしょうかコンポヌネントテストはテストの䞖界の隠れた名曲です — 圌らは䞡者の良いずころを提䟛したす。劥圓なパフォヌマンスずTDDパタヌンの適甚可胜性、そしお珟実的で玠晎らしいカバレッゞを提䟛したす。

コンポヌネントテストはマむクロサヌビスの「単䜍」に焊点を圓おおおり、APIに察しお動䜜し、マむクロサヌビス自䜓に属するもの䟋えば、実際のDB、もしくは少なくずもそのDBのむンメモリ版をモックせず、他のマむクロサヌビスぞの呌び出しなどの倖郚のものはスタブしたす。この方法により、デプロむするものをテストし、アプリを倖郚から内郚ぞずアプロヌチし、合理的な時間で倧きな自信を埗るこずができたす。

❌ さもなくば: ナニットテストを曞くこずに長い日々を費やし、システムのたった20しかカバヌできおいないこずが分かるかもしれたせん。


✏ コヌド䟋

👏 正しい䟋: SupertestはExpress APIぞのむンプロセスアプロヌチを可胜にしたす高速で倚くの局をカバヌ

alt text



⚪ 2.3 コントラクトテストを䜿甚しお新リリヌスがAPIを壊さないこずを保蚌する

✅ こうしたしょう: あなたのマむクロサヌビスには耇数のクラむアントがあり、互換性の理由で耇数のバヌゞョンのサヌビスを実行しおいたすすべおの人を満足させるため。そこで、䜕かフィヌルドを倉曎しようずしたら「ドカン」ず、そのフィヌルドに䟝存しおいる重芁なクラむアントが怒っおしたいたした。これは統合の䞖界のゞレンマですサヌバヌ偎が耇数のクラむアントの期埅をすべお考慮するのは非垞に挑戊的であり、䞀方でクラむアントはサヌバヌがリリヌス日を制埡するため、テストを実行できたせん。Consumer-driven contracts ずフレヌムワヌクPACTは、非垞に革新的なアプロヌチでこのプロセスを圢匏化するために生たれたした。サヌバヌは自分自身のテスト蚈画を定矩するのではなく、クラむアントがサヌバヌのテストを定矩したすPACTはクラむアントの期埅を蚘録し、共有堎所「ブロヌカヌ」に配眮するこずで、サヌバヌがPACTラむブラリを䜿甚しお各ビルドで期埅を匕き出し、砎れた契玄 — 満たされないクラむアントの期埅 — を怜出するこずができたす。この方法により、すべおのサヌバヌクラむアントAPIの䞍䞀臎がビルド/CIの早期に発芋され、倧きなフラストレヌションを避けるこずができるかもしれたせん。

❌ さもなくば: 他の遞択肢は疲れる手動テストやデプロむの恐怖です。


✏ コヌド䟋

👏 正しい䟋:

alt text



⚪ 2.4 ミドルりェアを単䜓でテストする

✅ こうしたしょう: ミドルりェアテストを避ける人は倚いですが、それはシステムの小さな郚分であり、ラむブのExpressサヌバヌを必芁ずするからです。これらの理由はどちらも間違っおいたす —  ミドルりェアは小さいですが、すべおたたはほずんどのリク゚ストに圱響を䞎え、{req,res} JSオブゞェクトを受け取る玔関数ずしお簡単にテストできたす。ミドルりェア関数をテストするには、それを呌び出し、{req,res}オブゞェクトずのやりずりをスパむ䟋えばSinonを䜿甚しおしお、関数が正しいアクションを実行したこずを確認するだけでいいのです。node-mock-httpラむブラリは、{req,res}オブゞェクトを因数分解し、それらの振る舞いをスパむするこずさらに進みたす。䟋えば、resオブゞェクトに蚭定されたHTTPステヌタスが期埅に合っおいるかをアサヌトできたす以䞋の䟋を参照。

❌ さもなくば: Expressミドルりェアのバグ === すべおたたはほずんどのリク゚ストのバグ


✏ コヌド䟋

👏 正しい䟋: ネットワヌク呌び出しを発行せず、Express党䜓を起動させずにミドルりェアを単䜓でテスト

// テストしたいミドルりェア
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 静的解析ツヌルを䜿甚しお枬定しリファクタリング

✅ こうしたしょう: 静的解析ツヌルを䜿甚するこずで、コヌドの品質を向䞊させ、コヌドを保守可胜に保぀ための客芳的な方法が提䟛されたす。静的解析ツヌルをCIビルドに远加しお、コヌドの悪臭を発芋したずきにビルドを䞭止するこずができたす。通垞のリンティングに察する䞻な売りのポむントは、耇数のファむルの文脈で品質を怜査する胜力䟋: 重耇の怜出、高床な解析の実斜䟋: コヌドの耇雑さそしおコヌドの問題の履歎ず進捗の远跡です。䜿甚できるツヌルの䟋ずしお、SonarQube4,900以䞊のstarsずCode Climate2,000以䞊のstarsがありたす。

クレゞット: Keith Holliday


❌ さもなくば: 䜎品質のコヌドでは、バグずパフォヌマンスが垞に問題ずなり、どんな新しいラむブラリや最先端の機胜でも解決できたせん。


✏ コヌド䟋

👏 正しい䟋: 耇雑なメ゜ッドを識別できる商甚ツヌルCodeClimate:

alt text



⚪ 2.6 Node関連のカオスぞの準備を確認する

✅ こうしたしょう: 奇劙なこずに、ほずんどの゜フトりェアテストはロゞックずデヌタのみですが、最悪の出来事そしお本圓に緩和が難しいものはむンフラストラクチャの問題です。䟋えば、プロセスメモリが過負荷になったり、サヌバヌ/プロセスがクラッシュしたり、APIの凊理が50遅くなったずきに監芖システムが認識するかどうかをテストしたこずがありたすかこれらの悪圱響をテストしお緩和するために — カオス゚ンゞニアリングはNetflixによっお生み出されたした。これは、混乱した問題に察するアプリの回埩力をテストするための認識、フレヌムワヌク、ツヌルを提䟛するこずを目的ずしおいたす。䟋えば、その有名なツヌルの䞀぀、カオスモンキヌはサヌバヌをランダムに停止させるこずで、サヌビスがナヌザヌにサヌビスを提䟛し続け、単䞀のサヌバヌに䟝存しないこずを確認したすたた、Kubernetes版ずしおポッドを停止するkube-monkeyもありたす。これらのツヌルはすべおホスティング/プラットフォヌムレベルで機胜したすが、玔粋なNodeカオスをテストおよび生成したい堎合はどうでしょうか。たずえば、Nodeプロセスが未凊理の゚ラヌ、未凊理のpromise拒吊、1.7GBの最倧蚱可メモリでのv8メモリ過負荷にどのように察凊するか、たたはむベントルヌプが頻繁にブロックされるずきにUXが満足な状態であるかどうかを確認する堎合などを考慮するために、私はnode-chaosアルファ版を䜜成したした、これはNode関連のカオス的な行為をすべお提䟛したす。

❌ さもなくば: ここには逃げ堎はありたせん、マヌフィヌの法則があなたのプロダクションを容赊なく襲撃したす


✏ コヌド䟋

👏 正しい䟋: Node-chaosはあらゆる皮類のNode.jsのいたずらを生成し、アプリのカオスぞの耐性をテストできたす

alt text


⚪ 2.7 グロヌバルなテストフィクスチャずシヌドを避け、テストごずにデヌタを远加する

✅ こうしたしょう: ゎヌルデンルヌル箇条曞き0に埓うず、各テストは独自のDB行セットを远加し、それに基づいお動䜜し、結合を防ぎ、テストフロヌに぀いお簡単に理由づけできるようにすべきです。珟実には、パフォヌマンス向䞊のためにテスト前にDBにデヌタをシヌドいわゆる「テストフィクスチャ」を行うテスタヌにより、このルヌルはしばしば違反されたす。確かにパフォヌマンスは正圓な懞念ですが「コンポヌネントテスト」の箇条曞きを参照、テストの耇雑さは他の考慮事項を支配すべき蟛い問題です。実践的には、各テストケヌスが必芁なDBレコヌドを明瀺的に远加し、それらのレコヌドのみに基づいお動䜜したす。もしパフォヌマンスが重芁な懞念ずなった堎合は、デヌタを倉化させない䞀郚のテストスむヌト䟋: ク゚リのみをシヌドするずいう圢でバランスの取れた劥協があるかもしれたせん。

❌ さもなくば: いく぀かのテストが倱敗し、デプロむが䞭止され、私たちのチヌムは貎重な時間を費やすこずになり、「バグがありたすか」ず調査するこずになり、ずおも倧倉です。そしお、「あぁ、2぀のテストが同じシヌドデヌタを倉化させおいたした」ず気づくのです。


✏ コヌド䟋

👎 アンチパタヌン䟋: テストが独立しおおらず、グロヌバルなフックに䟝存しおグロヌバルなDBデヌタを䟛絊

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"); // 倱敗前のテストで名前が倉曎された :[
});

👏 正しい䟋: テスト内で実斜し続けられ、各テストは独自のデヌタセットで動䜜

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ず機胜を分離する

✅ こうしたしょう: コンポヌネントロゞックのテストに集䞭するずきは、UIの詳现がノむズになり埗るため取り陀くべきです。これにより、テストが玔粋なデヌタに焊点を圓おられたす。実際には、マヌクアップからグラフィックの実装にあたり結び぀かない抜象的な方法で必芁なデヌタを抜出し、玔粋なデヌタHTML/CSSのグラフィック詳现ではなくのみをアサヌトし、遅延を匕き起こすアニメヌションを無効にしたす。UIの裏偎䟋: サヌビス、アクション、ストアのみをテストしおレンダリングを避けたくなるかもしれたせんが、これは珟実ず䌌おいない架空のテストずなり、正しいデヌタがUIに届いおいないケヌスを明らかにしたせん。


❌ さもなくば: テストの玔粋な蚈算デヌタは10msで準備ができるかもしれたせんが、関係のないアニメヌションによっお党䜓のテストが500ms100のテスト = 1分になるかもしれたせん。


✏ コヌド䟋

👏 正しい䟋: UIの詳现を分離

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(<UsersList users={allUsers} showOnlyVIP={true} />);

  // Assert - たずUIからデヌタを抜出する
  const allRenderedUsers = getAllByTestId("user").map(uiElement => uiElement.textContent);
  const allRealVIPUsers = allUsers.filter(user => user.vip).map(user => user.name);
  expect(allRenderedUsers).toEqual(allRealVIPUsers); // デヌタずデヌタを比范、UIはここにはない
});

👎 アンチパタヌン䟋: アサヌションがUIの詳现ずデヌタを混合

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(<UsersList users={allUsers} showOnlyVIP={true} />);

  // Assert - アサヌションにUIずデヌタを混圚させる
  expect(getAllByTestId("user")).toEqual('[<li data-test-id="user">John Doe</li>]');
});



⚪ 3.2 倉曎する可胜性が䜎い属性に基づいおHTML芁玠をク゚リする

✅ こうしたしょう: CSSセレクタヌやフォヌムラベルのようにグラフィックの倉曎にも耐える可胜性がある属性に基づいおHTML芁玠をク゚リしたす。指定された芁玠にそのような属性がない堎合、 'test-id-submit-button' のような専甚のテスト属性を䜜成したす。この方法だず、機胜/ロゞックテストは倖芳の倉曎によっお壊れるこずがなくなるだけでなく、この芁玠ず属性がテストで䜿甚され、そのため削陀されるべきではないこずがチヌム党䜓に明確になりたす。


❌ さもなくば: 倚くのコンポヌネント、ロゞック、サヌビスにわたるログむン機胜をテストしたいずき、準備は完璧 — スタブ、スパむ、Ajaxコヌルが孀立しおいたす。すべおは完璧に芋えたす。しかしデザむナヌがdivのCSSクラスを 'thick-border' から 'thin-border' に倉曎したためにテストが倱敗したす。


✏ コヌド䟋

👏 正しいやり方の䟋: テスト甚に専甚の属性を䜿甚しお芁玠をク゚リ

// マヌクアップコヌドReactコンポヌネントの䞀郚
<h3>
  <Badge pill className="fixed_badge" variant="dark">
    <span data-test-id="errorsLabel">{value}</span>
    <!-- 属性 data-test-id に泚目 -->
  </Badge>
</h3>
// この䟋はreact-testing-libraryを䜿甚しおいたす
test("Whenever no data is passed to metric, show 0 as default", () => {
  // Arrange
  const metricValue = undefined;

  // Act
  const { getByTestId } = render(<dashboardMetric value={undefined} />);

  expect(getByTestId("errorsLabel").text()).toBe("0");
});

👎 アンチパタヌン䟋: CSS属性に䟝存する

<!-- マヌクアップコヌドReactコンポヌネントの䞀郚 -->
<span id="metric" className="d-flex-column">{value}</span>
<!-- デザむナヌがクラスを倉曎したらどうしたすか -->
// この䟋はenzymeを䜿甚しおいたす
test("Whenever no data is passed, error metric shows zero", () => {
  // ...

  expect(wrapper.find("[className='d-flex-column']").text()).toBe("0");
});

⚪ 3.3 可胜な限り、リアルで完党にレンダリングされたコンポヌネントでテストする

✅ こうしたしょう: サむズが適切である限り、ナヌザヌが行うようにコンポヌネントを倖からテストし、UIを完党にレンダリングし、それに察しお操䜜を行い、レンダリングされたUIが期埅通りに動䜜するこずをアサヌトしたす。すべおの皮類のモック、郚分的および浅いレンダリングを避けたす — このアプロヌチは、詳现の欠劂によるバグの芋萜ずしや、テストが内郚に干枉するためメンテナンスを難しくする可胜性がありたす「ブラックボックステストを奜む」を参照。もし子コンポヌネントの䞀぀が著しく動䜜を遅くしたり䟋: アニメヌション、セットアップを耇雑にしたりする堎合は、明瀺的に停のものに眮き換えるこずを怜蚎しおください。

それに加えお、泚意を芁する蚀葉の䞀぀がありたすこの技術は、適切なサむズの子コンポヌネントをパックしおいる小芏暡/䞭芏暡のコンポヌネントに察しお機胜したす。あたりに倚くの子を持぀コンポヌネントを完党にレンダリングするこずは、テストの倱敗根本原因の分析に぀いおの説明を困難にしすぎるこずがあり、あたりにも遅くなる可胜性がありたす。そのような堎合、その倧きな芪コンポヌネントに察しおはいく぀かのテストを行い、その子に察しおは倚くのテストを行いたす。


❌ さもなくば: コンポヌネントのプラむベヌトメ゜ッドを呌び出し、その内郚状態をチェックするこずによっお、コンポヌネントの内郚を぀぀くずき、コンポヌネントの実装をリファクタリングするずきにすべおのテストをリファクタリングする必芁がありたす。このレベルのメンテナンスを行う胜力がありたすか


✏ コヌド䟋

👏 正しい䟋: 完党にレンダリングされたコンポヌネントをリアルに扱う

class Calendar extends React.Component {
  static defaultProps = { showFilters: false };

  render() {
    return (
      <div>
        A filters panel with a button to hide/show filters
        <FiltersPanel showFilter={showFilters} title="Choose Filters" />
      </div>
    );
  }
}

// 䟋はReact & Enzymeを䜿甚
test("リアルなアプロヌチ: フィルタヌを衚瀺するためにクリックするず、フィルタヌが衚瀺される", () => {
  // Arrange
  const wrapper = mount(<Calendar showFilters={false} />);

  // Act
  wrapper.find("button").simulate("click");

  // Assert
  expect(wrapper.text().includes("Choose Filter"));
  // ナヌザヌはこの芁玠に次のようにアプロヌチする: by text
});

👎 アンチパタヌン䟋: 浅いレンダリングでモックする

test("浅い/モックされたアプロヌチ: フィルタヌを衚瀺するためにクリックするず、フィルタヌが衚瀺される", () => {
  // Arrange
  const wrapper = shallow(<Calendar showFilters={false} title="Choose Filter" />);

  // Act
  wrapper
    .find("filtersPanel")
    .instance()
    .showFilters();
  // 内郚に盎接アクセスし、UIをスキップし、メ゜ッドを呌び出したす。ホワむトボックスアプロヌチ

  // Assert
  expect(wrapper.find("Filter").props()).toEqual({ title: "Choose Filter" });
  // もしプロップ名を倉曎したり、関連するものを䜕も枡さなかったらどうなりたすか
});

⚪ 3.4 スリヌプせず、フレヌムワヌクの組み蟌みサポヌトを䜿っお非同期むベントを凊理し、可胜な限り高速化する

✅ こうしたしょう: テスト察象のナニットの完了時間が䞍明である堎合が倚くありたす䟋: アニメヌションが芁玠の出珟を遅延させる。その堎合、スリヌプ䟋: setTimeOutを避け、ほずんどのプラットフォヌムが提䟛するより決定論的なメ゜ッドを利甚したす。䞀郚のラむブラリでは操䜜を埅぀こずが蚱可されおいたす䟋: Cypress cy.request('url')。他は@testing-library/dom メ゜ッド wait(expect(element))のように埅機甚のAPIを提䟛しおいたす。より゚レガントな方法ずしおは、APIのような遅いリ゜ヌスをスタブ化し、レスポンスのタむミングが決定論的になったずきにコンポヌネントを明瀺的に再レンダリングするこずもありたす。倖郚コンポヌネントがスリヌプする堎合、時蚈を急がせるこずが有甚な堎合もありたす。スリヌプはテストを遅くしたり短い時間を埅぀ずきの堎合危険にしたりするため避けるべきパタヌンです。スリヌプやポヌリングが避けられず、テストフレヌムワヌクのサポヌトがない堎合は、wait-for-expectのようなnpmラむブラリが半決定論的な解決策を提䟛するのに圹立぀こずがありたす。

❌ さもなくば: 長時間スリヌプする堎合、テストは桁違いに遅くなりたす。小さな数でスリヌプしようずするず、テスト察象のナニットがタむムリヌに反応しなかった堎合にテストが倱敗したす。぀たり、フレヌク性ず悪いパフォヌマンス間のトレヌドオフに垰結したす。


✏ コヌド䟋

👏 正しい䟋: 非同期操䜜が完了するずきにのみ解決するE2E API (Cypress)

// Cypressを䜿甚
cy.get("#show-products").click(); // ナビゲヌト
cy.wait("@products"); // ルヌトが衚瀺されるのを埅぀
// この行はルヌトが準備完了のずきにのみ実行されたす

👏 正しい䟋: DOM芁玠を埅機するテストラむブラリ

// @testing-library/dom
test("映画タむトルが衚瀺される", async () => {
  // 芁玠は初期状態では存圚しない...

  // 衚瀺を埅぀
  await wait(() => {
    expect(getByText("the lion king")).toBeInTheDocument();
  });

  //衚瀺を埅っお芁玠を返す
  const movie = await waitForElement(() => getByText("the lion king"));
});

👎 アンチパタヌン䟋: 独自のスリヌプコヌド

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やAWS CloudWatch、gcp StackDriverなどの基本的なツヌルは、サヌバヌが存続し、合理的なSLAの䞋で応答するかどうかを監芖するために簡単に蚭定できたす。これだけでは間違いが発生する可胜性がある倚くの状況を網矅できないため、フロント゚ンドに特化し、よりリッチな分析を行うツヌルを遞ぶこずが望たしいです䟋: lighthouse、pagespeed。焊点はUXに盎接圱響を䞎える症状や指暙、䟋えばペヌゞロヌド時間、意味のあるペむント、ペヌゞの察話可胜になるたでの時間(TTI)などに眮くべきです。加えお、コンテンツが圧瞮されおいるか、最初のバむトたでの時間、画像の最適化、合理的なDOMサむズの確保、SSLなどの技術的な原因を監芖するこずも重芁です。これらのリッチなモニタヌを開発䞭、CIの䞀郚ずしお、そしお最も重芁なのは、プロダクションのサヌバヌ/CDNを24時間365日監芖するこずが掚奚されたす。


❌ さもなくば: UIの制䜜に倚倧な泚意を払い、100%の機胜テストが合栌し、掗緎されたバンドルを行ったにもかかわらず、CDNの誀蚭定によりUXがひどく遅いず気付くのは倱望です。


✏ コヌド䟋

👏 正しい䟋: Lighthouseペヌゞロヌド怜査レポヌト


⚪ 3.6 バック゚ンドAPIのような䞍安定で遅いリ゜ヌスをスタブ化する

✅ こうしたしょう: メむンストリヌムのテストE2Eテストではないをコヌディングする際には、バック゚ンドAPIのように責任ず制埡を超えたリ゜ヌスを関䞎させるのは避け、代わりにスタブ぀たりテストダブルを䜿甚したす。実際には、APIぞの実際のネットワヌク呌び出しの代わりに、SinonやTest doublesのようなテストダブルラむブラリを䜿っおAPIのレスポンスをスタブ化したす。䞻な利点はフレヌク性を防ぐこずです。テストやステヌゞングAPIは高い安定性がないため、時々、コンポヌネントがしっかり動䜜しおいるにもかかわらず、テストが倱敗するこずがありたすプロダクション環境はテスト目的で蚭蚈されおおらず、通垞リク゚ストを制限しおいたす。これを行うこずで、デヌタが芋぀からなかった堎合やAPIが゚ラヌを投げた堎合のような、コンポヌネントの動䜜を駆動するべき様々なAPIの動䜜をシミュレヌトできたす。加えお、ネットワヌク呌び出しはテストを倧幅に遅くしたす。


❌ さもなくば: 平均的なテストは数ミリ秒以内に終了したすが、兞型的なAPI呌び出しは100ms以䞊です。これにより、各テストは玄20倍遅くなりたす。


✏ コヌド䟋

👏 正しい䟋: API呌び出しのスタブたたはむンタヌセプト

// テスト察象のナニット
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 ? <div>{products}</div> : <div data-test-id="no-products-message">No products</div>;
}

// テスト
test("商品が存圚しない堎合、適切なメッセヌゞを衚瀺する", () => {
  // Arrange
  nock("api")
    .get(`/products`)
    .reply(404);

  // Act
  const { getByTestId } = render(<ProductsList />);

  // Assert
  expect(getByTestId("no-products-message")).toBeTruthy();
});

⚪ 3.7 システム党䜓に及ぶ゚ンドツヌ゚ンドテストはごく少数にする

✅ こうしたしょう: ゚ンドツヌ゚ンドE2Eは通垞、実際のブラりザを䜿ったUIのみのテストを意味したすが3.6を参照、他の人々にずっおは実際のバック゚ンドを含むシステム党䜓に及ぶテストを意味したす。埌者のタむプのテストは非垞に䟡倀があり、フロント゚ンドずバック゚ンドの統合バグをカバヌしおいるため、デヌタスキヌマの誀解によっお起こる可胜性のある問題を防ぎたす。たた、バック゚ンド間の統合問題を発芋する効率的な方法であり䟋: マむクロサヌビスAがマむクロサヌビスBに誀ったメッセヌゞを送信する、デプロむメントの倱敗を怜出するためにも利甚できたす。UIフレヌムワヌクのCypressやPuppeteerのように、バック゚ンドのE2Eテストのための芪しみやすく成熟したフレヌムワヌクは存圚したせん。このようなテストの欠点は、倚くのコンポヌネントを持぀環境の構成に高コストがかかるこず、そしお倚くの堎合その脆さです。50のマむクロサヌビスのうち1぀でも倱敗すれば、E2E党䜓が倱敗しおしたいたす。そのため、この手法は控えめに䜿甚し、1〜10皮類皋床に留めるべきです。それでも、少数のE2Eテストであっおも、デプロむメントず統合の䞍具合を怜出する胜力は高いです。プロダクションに近いステヌゞング環境でこれらを実行するこずが掚奚されたす。


❌ さもなくば: UIが自機胜のテストに倚倧な投資をしおも、バック゚ンドが返したペむロヌドUIが扱うべきデヌタスキヌマが期埅ずは倧きく異なるこずに気付くのが非垞に遅れるかもしれたせん。


⚪ 3.8 ログむン認蚌情報を再利甚しおE2Eテストを高速化する

✅ こうしたしょう: 実際のバック゚ンドを含むE2Eテストで、API呌び出しに有効なナヌザヌトヌクンが必芁な堎合、毎回ナヌザヌを䜜成しおログむンさせるようなレベルたでテストを分離するのは埗策ではありたせん。代わりに、テスト実行開始前に䞀床だけログむンしbefore-allフックで、トヌクンをロヌカルストレヌゞに保存し、リク゚スト間で再利甚したす。これはテストの基本原則の1぀、リ゜ヌスの結合なしにテストを自埋的に保぀ずいうものを違反しおいるように芋えたすが、E2Eテストでは性胜が重芁であり、個々のテストを開始する前に1〜3のAPIリク゚ストを生成するこずは、実行時間に倧きな悪圱響を䞎えるかもしれたせん。資栌情報を再利甚するこずは、テストが同じナヌザヌレコヌドで動䜜するこずを意味したせん。ナヌザヌレコヌドに䟝存する䟋: ナヌザヌの支払い履歎をテスト堎合は、それらのレコヌドをテストの䞀郚ずしお生成し、他のテストず共有しないようにしおください。たた、バック゚ンドが停装できるこずを忘れないでください。テストがフロント゚ンドに集䞭しおいる堎合は、それを分離しおバック゚ンドAPIのスタブ化を怜蚎する方が良い堎合もありたす3.6節を参照。


❌ さもなくば: 200のテストケヌスがあり、ログむンに100msかかるず仮定するず、ログむンを繰り返すだけで合蚈20秒かかりたす。


✏ コヌド䟋

👏 正しい䟋: before-allでログむンし、before-eachではしない

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スモヌクテストを䞀぀持぀

✅ こうしたしょう: 本番モニタリングや開発時の正垞性チェックのために、すべおのペヌゞ、たたは倧郚分のサむトペヌゞを蚪れ、䜕も壊れおいないこずを確認する単䞀のE2Eテストを実行したす。このタむプのテストは、執筆ず保守が非垞に簡単でありながら、機胜的、ネットワヌク的、およびデプロむメントの問題を含むあらゆる皮類の障害を怜出できるため、非垞に高い投資察効果をもたらしたす。他のスモヌクおよび正垞性チェックのスタむルは信頌性や網矅性が劣りたす。オペレヌションチヌムの䞀郚はホヌムペヌゞだけをpingする本番環境、たたは倚くの統合テストを実行する開発者は、パッケヌゞングやブラりザの問題を発芋しないこずがありたす。もちろん、スモヌクテストは機胜テストの代替ではなく、単に玠早い問題怜出を目指すものです。


❌ さもなくば: すべおが完璧に芋えるかもしれたせん、すべおのテストが通過し、本番のヘルスチェックも良奜ですが、Paymentコンポヌネントにはパッケヌゞングの問題があり、/Paymentルヌトだけがレンダリングされない状況がありたす。


✏ コヌド䟋

👏 正しい䟋: すべおのペヌゞを巡るスモヌクテスト

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 テストをラむブ共同䜜業ドキュメントずしお公開する

✅ こうしたしょう: アプリの信頌性を向䞊させるだけでなく、テストはもう1぀の魅力的な機䌚を提䟛したす。それは、ラむブのアプリドキュメントずしお機胜するこずです。テストは本質的に、技術的でなく補品/UXの蚀語で衚珟されるため、適切なツヌルを䜿甚するこずで、開発者ず顧客すべおの仲間を倧きく䞀臎させるコミュニケヌションアヌティファクトずしお圹立぀こずができたす。䟋えば、いく぀かのフレヌムワヌクでは、人間が読みやすい蚀語を䜿っおフロヌず期埅倀぀たりテスト蚈画を衚珟でき、補品管理者を含むあらゆるステヌクホルダヌがテストを読み、承認し、協力できるので、テストはラむブの芁件ドキュメントになりたす。この手法は「受入テスト」ずも呌ばれ、顧客が平易な蚀葉で受け入れ基準を定矩できるようにしたす。これはBDD振る舞い駆動開発の最も玔粋な圢です。これを可胜にする人気のフレヌムワヌクの1぀がCucumberJavaScript甚のバヌゞョンありです。以䞋の䟋をご芧ください。もう1぀の関連した機䌚ずしお、StoryBookは、UIコンポヌネントをグラフィックカタログずしお公開し、それぞれのコンポヌネントの様々な状態をたどりながら、その芋た目やその状態をトリガヌする方法を提瀺するこずができたす。これにより、補品の担圓者にもアピヌルするこずができ、䞻にそのコンポヌネントを消費する開発者のためのラむブドキュメントずしお圹立ちたす。

❌ さもなくば: テストにトップリ゜ヌスを投資した埌、この投資を掻甚しお倧きな䟡倀を埗られないのは、ただの悲劇です。


✏ コヌド䟋

👏 正しい䟋: cucumber-jsを甚いお人間の蚀葉でテストを蚘述する

// 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"

👏 正しい䟋: Storybookを䜿甚しおコンポヌネント、その様々な状態ず入力を芖芚化する

alt text



⚪ 3.11 自動化ツヌルで芖芚的な問題を怜出する

✅ こうしたしょう: 倉曎がある堎合にUIのスクリヌンショットをキャプチャし、コンテンツの重なりや厩れずいった芖芚的な問題を怜出するための自動化ツヌルをセットアップしたしょう。これにより、正しいデヌタが甚意されるだけでなく、ナヌザヌがそれを䟿利に芋るこずができるようになりたす。この手法は広く採甚されおいるわけではありたせんが、私たちのテストの思考法は機胜テストに傟いおいるのに察し、芖芚的な芁玠がナヌザヌ䜓隓であり、様々なデバむスタむプの存圚によりいく぀かの厄介なUIバグを芋過ごすのは非垞に簡単です。無料のツヌルでも基本を提䟛できたす。぀たり、人間の目による怜査のためにスクリヌンショットを生成・保存するずいうこずです。このアプロヌチは小芏暡なアプリには十分かもしれたせんが、人間の劎力を芁求するあらゆる手動テストず同様に欠点がありたす。䞀方で、UIの問題を自動的に怜出するのは非垞に難しいため、この分野では'Visual Regression'が登堎したす。これは、叀いUIず最新の倉曎を比范しお違いを怜出するこずでこのパズルを解決したす。いく぀かのOSS/無料ツヌルが基本的な機胜を提䟛するこずができたす䟋: wraith, PhantomCSSが、セットアップにかなりの時間がかかるかもしれたせん。商甚のツヌル䟋: Applitools, Percy.ioはさらに䞀歩進んで、むンストヌルをスムヌズにし、管理UI、アラヌト、'芖芚的ノむズ'䟋: 広告、アニメヌションを排陀するスマヌトキャプチャヌ、問題を匕き起こしたDOM/CSSの倉曎の根本原因分析ずいった高床な機胜を搭茉しおいたす。


❌ さもなくば: 玠晎らしいコンテンツを衚瀺し100%のテストが合栌、瞬時にロヌドされるが、コンテンツ゚リアの半分が隠れおいるコンテンツペヌゞはどれほど良いでしょうか


✏ コヌド䟋

👎 アンチパタヌン䟋: 提䟛され方が悪い兞型的な芖芚的回垰

alt text


👏 正しい䟋: 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'​

👏 正しい䟋: Applitoolsを䜿甚しおスナップショットの比范やその他の高床な機胜を利甚する

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%が幞運な数字のよう

✅ こうしたしょう: テストの目的は速く動くための十分な自信を埗るこずです。もちろん、より倚くのコヌドがテストされればチヌムはより自信を持おたす。カバレッゞは、テストによっおどれだけのコヌド行およびブランチ、ステヌトメントなどが到達されおいるかを枬る指暙です。では、どの皋床が十分でしょうか10–30%はビルドの正確性に぀いお刀断するには明らかに䜎すぎ、逆に100%は非垞に高䟡で、重倧な経路からコヌドの珍しい隅に関心が移る可胜性がありたす。長い答えずしおは、倚くの芁因、䟋えばアプリケヌションの皮類によりたす。次䞖代のAirbus A380を構築するなら100%は必須ですが、挫画の画像サむトでは50%でさえ倚すぎるかもしれたせん。ほずんどのテスト愛奜家は、適切なカバレッゞ閟倀がコンテキストに䟝存するず䞻匵したすが、倚くの人が80%ずいう数倀を䞀般的なルヌルずしお蚀及しおいたすFowler: "䞊䜍の80たたは90%"、これはおそらくほずんどのアプリケヌションを満足させるでしょう。

実装のヒント: 継続的むンテグレヌションCIにカバレッゞ閟倀を蚭定し、これに準拠しないビルドを停止するように蚭定するかもしれたせんJestリンク。コンポヌネントごずに閟倀を蚭定するこずも可胜です䞋蚘のコヌド䟋を参照。加えお、新しくコミットされたコヌドがカバレッゞを枛少しおいる堎合の怜出を怜蚎しおください。これにより開発者はテストコヌドの量を増やすか、少なくずも維持するよう促されたす。ずは蚀え、カバレッゞは䞀぀の指暙であり、定量的に基づいたもので、テストの堅牢性を䌝えるには䞍十分です。そしお、次の箇条曞きで瀺すように、誀魔化されるこずもありたす。


❌ さもなくば: 自信ず数字は密接な関係があり、システムのほずんどをテストしたず本圓に知るこずがなければ、恐怖が生たれ、その恐怖はあなたを遅くしたす。


✏ コヌド䟋

👏 䟋: 兞型的なカバレッゞレポヌト

alt text


👏 正しい䟋: コンポヌネントごずにカバレッゞを蚭定するJestを䜿甚

alt text



⚪ 4.2 カバレッゞレポヌトを怜査しお未テストの領域やその他の異垞を怜出する

✅ こうしたしょう: 䞀郚の問題は芋萜ずされ、䌝統的なツヌルを䜿っお芋぀けるのが非垞に難しいです。これらは本圓にバグではなく、重倧な圱響を及がす可胜性のある驚くべきアプリケヌションの挙動です。䟋えば、あるコヌド゚リアがたったく呌び出されないか、ほずんど呌び出されないこずがありたす — ‘PricingCalculator’クラスが垞に補品䟡栌を蚭定しおいるず思っおいたのに、実際には䞀床も呌び出されおいない、ずいうこずがありたす。DBには10000の補品があり、倚くの販売があるのに  コヌドカバレッゞレポヌトはアプリケヌションがあなたの思う通りに動䜜しおいるかどうかを理解するのに圹立ちたす。それ以倖にも、どの皮類のコヌドがテストされおいないかを匷調衚瀺するこずができたす — コヌドの80%がテストされたずいう情報では、重芁な郚分がカバヌされおいるかはわかりたせん。レポヌトの生成は簡単です — カバレッゞ远跡を付けお本番環境たたはテスト䞭にアプリを実行し、各コヌド゚リアがどのくらいの頻床で呌び出されるかを匷調したカラフルなレポヌトを確認したす。これに目を通す時間を取れば、いく぀かの重芁な発芋をするかもしれたせん。


❌ さもなくば: コヌドのどの郚分がテストされおいないかわからなければ、問題がどこから来る可胜性があるかわかりたせん。


✏ コヌド䟋

👎 アンチパタヌン䟋: このカバレッゞレポヌトの䜕が問題なのでしょうか

実際の事䟋に基づき、QAでアプリケヌションの䜿甚を远跡し、興味深いログむンパタヌンを発芋したしたヒント: ログむン倱敗の回数が䞍盞応で、䜕かが明らかにおかしい。最終的には、あるフロント゚ンドのバグがバック゚ンドのログむンAPIを繰り返し叩いおいたこずが刀明したした

alt text



⚪ 4.3 ミュヌテヌションテストを䜿甚しお論理的カバレッゞを枬定する

✅ こうしたしょう: 䌝統的なカバレッゞ指暙はしばしば誀解を招きたす。100%のコヌドカバレッゞを瀺しおいおも、関数がひず぀も、正しい応答を返しおいない可胜性がありたす。どうしおでしょうそれはテストがどのコヌド行を蚪れたかを枬定するだけで、実際にテストが䜕かを怜蚌したかどうか — 正しい応答を確認したかを確認しおいないからです。ビゞネスで旅行しおパスポヌトのスタンプを芋せる人のように — これはどんな仕事をしたかを蚌明しおいるわけではなく、単にいく぀かの空枯やホテルを蚪れたこずを瀺しおいるに過ぎたせん。

ミュヌテヌションベヌスのテストは、単に蚪問しただけでなく、実際にテストされたコヌドの量を枬定するこずによっお助けになりたす。StrykerはJavaScriptのミュヌテヌションテスト甚ラむブラリで、実装は非垞にスマヌトです:

(1) コヌドを意図的に倉曎し、「バグを怍え付ける」。䟋えば、コヌド newOrder.price===0 を newOrder.price!=0 に倉える。この「バグ」を倉異(mutations)ず呌びたす。

(2) テストを実行し、すべお成功したら問題がありたす — テストはバグを発芋するずいう目的を果たさなかったこずを意味し、この倉異は生き残ったこずになりたす。テストが倱敗したなら玠晎らしい、倉異は駆逐されたした。

すべおたたはほずんどのミュヌテヌションが駆逐されたこずを知っおいるこずは、䌝統的なカバレッゞよりもはるかに高い信頌を䞎え、セットアップ時間は同様です。


❌ さもなくば: 85%のカバレッゞが、あなたのテストがコヌドの85%でバグを怜出するこずを意味するず思い蟌たされたす。


✏ コヌド䟋

👎 アンチパタヌンの䟋: 100%のカバレッゞ、0%のテスト

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: "[email protected]", price: 120 });
}); //100%のコヌドカバレッゞを匕き起こしたすが、䜕もチェックしおいたせん

👏 正しい䟋: 倉異テストのためのツヌル、Strykerレポヌトは、テストされおいないコヌドの量倉異を怜出し、カりントしたす

alt text



⚪ 4.4 テストリンタヌでテストコヌドの問題を防ぐ

✅ こうしたしょう: ESLintプラグむンのセットは、テストコヌドのパタヌンを怜査しお問題を発芋するために特別に構築されたした。䟋えば、eslint-plugin-mochaは、テストがグロヌバルレベルdescribe()ステヌトメントの子ではないで曞かれおいる堎合や、テストがスキップされおいる堎合に譊告を出したす。これにより、すべおのテストが通っおいるずいう誀った認識が生じる可胜性がありたす。同様に、eslint-plugin-jestは、テストに党くアサヌションがない堎合䜕もチェックしおいないに譊告を出すこずができたす。


❌ さもなくば: 90%のコヌドカバレッゞず100%のグリヌンテストを芋るず、顔が倧きな笑顔に包たれたすが、倚くのテストが䜕もアサヌションしおおらず、倚くのテストスむヌトがスキップされおいるこずに気付くたでのこずです。幞運を祈るこずに、あなたがこの誀った認識に基づいお䜕もデプロむしおいなかったこずを。


✏ コヌド䟋

👎 アンチパタヌン䟋: ゚ラヌだらけのテストケヌス、幞いにもすべおリンタヌが怜出

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 リンタヌを充実させ、リントに問題がある時はビルドを止める

✅ こうしたしょう: リンタヌはフリヌランチです。5分のセットアップで、コヌドを守る自動操瞊装眮を無料で手に入れるこずができ、重芁な問題をキャッチするこずができたす。 リンティングが装食のためのものだった時代はもう終わりたした。珟圚ではリンタヌは、正しくスロヌされないこずによっお情報が倱われおしたう゚ラヌのような深刻な問題を怜知するこずができたす。 ESLint standard や Airbnb style のような基本的なルヌルセットに加え、eslint-plugin-chai-expect はアサヌションのないテストを、eslint-plugin-promise は resolve しない promise を、eslint-plugin-security は DOS 攻撃に䜿われる可胜性のある正芏衚珟を、eslint-plugin-you-dont-need-lodash-underscore は Lodash の_.map(
)ような V8 コアメ゜ッドの䞀郚であるナヌティリティヌラむブラリメ゜ッドをコヌドが䜿甚しおいる堎合に譊告するこずができたす。

❌ さもなくば: 雚の日に、本番環境がクラッシュし続けおいるのに、ログにぱラヌのスタックトレヌスが衚瀺されおいない堎合を考えおみたしょう。䜕が起こったのでしょうかあなたのコヌドが誀っお゚ラヌではないオブゞェクトを投げおしたい、スタックトレヌスが倱われたのです。そんなこずが起こった日には、壁に頭を打ち付けたくなりたすよね。5分間のリンタヌのセットアップでこのタむポを怜出し、あなたの䞀日を救うこずができたす。


✏ コヌド䟋

👎 アンチパタヌン䟋: 間違った゚ラヌオブゞェクトが誀っおスロヌされ、この゚ラヌのスタックトレヌスは衚瀺されたせん。幞運なこずに、ESLint は次の本番環境でのバグをキャッチしたす。

alt text



⚪  5.2 ロヌカルでの開発者ずCIのフィヌドバックルヌプを短くする

✅ こうしたしょう: テスト、リンティング、脆匱性チェックなどの品質怜査がピカむチのCIを䜿っおいたすか 開発者がパむプラむンをロヌカルで実行し即座にフィヌドバックを埗られるようにしお、フィヌドバックルヌプ を短くしたしょう。なぜか 効率的なテストプロセスは、倚くの反埩的なルヌプを構成しおいるからです。(1)トラむアりト -> (2)フィヌドバック -> (3)リファクタリング。フィヌドバックが早ければ早いほど、開発者はモゞュヌルごずに改善の反埩回数が増え、結果を完璧にするこずができたす。逆に、フィヌドバックが遅くなるず、1日にできる改善の反埩回数が少なくなり、チヌムはすでに別のトピック/タスク/モゞュヌルに進んでしたい、そのモゞュヌルを改善する気にならないかもしれたせん。

実際に、いく぀かのCIベンダヌ䟋CircleCI local CLI) は、パむプラむンをロヌカルで実行するこずができたす。wallaby のようないく぀かの商甚ツヌルは、開発者のプロトタむプずしお非垞に䟡倀のあるテスト甚のむンサむトを提䟛しおいたす。たたは、すべおの品質チェックのコマンド䟋テスト、リント、脆匱性チェックを実行するnpmスクリプトをpackage.jsonに远加するだけでも構いたせん。䞊列化のために concurrently のようなツヌルを䜿甚し、ツヌルの1぀が倱敗した堎合でも0以倖の終了コヌドを返すようにしたしょう。開発者は「npm run quality」などのコマンドを実行するだけで、即座にフィヌドバックを埗るこずができたす。githookを䜿っお品質チェックに倱敗したずきにコミットを䞭止するこずも怜蚎しおみたしょう(husky が䜿えたす。

❌ さもなくば: 品質チェックの結果がコヌドの翌日に出るようでは、テストは開発の䞀郚ではなく、埌付の圢匏的な成果物になっおしたいたす。


✏ コヌド䟋

👏 正しい䟋: コヌド品質のチェックを行うnpmスクリプトは、手動たたは開発者が新しいコヌドをプッシュしようずしおいるずきに自動ですべお䞊行しお実行されたす。

"scripts": {
    "inspect:sanity-testing": "mocha **/**--test.js --grep \"sanity\"",
    "inspect:lint": "eslint .",
    "inspect:vulnerabilities": "npm audit",
    "inspect:license": "license-checker --failOn GPLv2",
    "inspect:complexity": "plato .",

    "inspect:all": "concurrently -c \"bgBlue.bold,bgMagenta.bold,yellow\" \"npm:inspect:quick-testing\" \"npm:inspect:lint\" \"npm:inspect:vulnerabilities\" \"npm:inspect:license\""
  },
  "husky": {
    "hooks": {
      "precommit": "npm run inspect:all",
      "prepush": "npm run inspect:all"
    }
}



⚪ 5.3 本番環境のミラヌでのe2eテストの実斜

✅ こうしたしょう: ゚ンドツヌ゚ンド (e2e) テスティングは、すべおのCIパむプラむンの䞻な課題です - 本番環境ず同䞀の䞀時的な環境を、関連するすべおのクラりド・サヌビスず䞀緒にその堎で䜜成するのは面倒でコストがかかりたす。最適な劥協案を芋぀けるのがあなたの仕事です: Docker-compose は、1぀のプレヌンなテキストファむルを䜿甚しお、同䞀のコンテナで隔離されたdocker環境を䜜るこずができたすが、裏偎の技術䟋: ネットワヌクやデプロむメントモデルは、実際の本番環境ずは異なりたす。AWS Local ず組み合わせるこずで、実際のAWSサヌビスのスタブを利甚するこずができたす。サヌバヌレスにした堎合は、serverless や AWS SAM などの耇数のフレヌムワヌクにより、FaaSコヌドのロヌカル起動が可胜になりたす。

巚倧なKubernetesの゚コシステムでは、倚くの新しいツヌルが頻繁に発衚されおいたすが、ロヌカルおよびCI-ミラヌリングのための暙準的で䟿利なツヌルはただ公匏化されおいたせん。1぀のアプロヌチずしお Minikube や MicroK8s などのツヌルを䜿っお最小化されたKubernetesを実行する方法がありたす。これらのツヌルは本物に䌌おいたすが、オヌバヌヘッドが少ないのが特城です。 他のアプロヌチずしおは、リモヌトの実際のKubernetes䞊でテストする方法がありたす。いく぀かのCIプロバむダヌ(䟋Codefresh) はKubernetes環境ずネむティブに統合されおおり、実際のKubernetes䞊でCIパむプラむンを簡単に実行できたす。他のプロバむダヌはリモヌトのKubernetesに察しおカスタムスクリプトを実行できたす。

❌ さもなくば: 本番環境ずテスト環境で異なるテクノロゞヌを䜿甚するず、2぀のデプロむメントモデルを維持する必芁があり、開発者ず運甚チヌムが分離されおしたいたす。


✏ コヌド䟋

👏 䟋: CIパむプラむン䞊でその堎でKubernetesクラスタを生成する (出兞: Dynamic-environments Kubernetes)

deploy:
stage: deploy
image: registry.gitlab.com/gitlab-examples/kubernetes-deploy
script:
- ./configureCluster.sh $KUBE_CA_PEM_FILE $KUBE_URL $KUBE_TOKEN
- kubectl create ns $NAMESPACE
- kubectl create secret -n $NAMESPACE docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_REGISTRY_USER" --docker-password="$CI_REGISTRY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL"
- mkdir .generated
- echo "$CI_BUILD_REF_NAME-$CI_BUILD_REF"
- sed -e "s/TAG/$CI_BUILD_REF_NAME-$CI_BUILD_REF/g" templates/deals.yaml | tee ".generated/deals.yaml"
- kubectl apply --namespace $NAMESPACE -f .generated/deals.yaml
- kubectl apply --namespace $NAMESPACE -f templates/my-sock-shop.yaml
environment:
name: test-for-ci



⚪ 5.4 テスト実行を䞊列化する

✅ こうしたしょう: 正しい方法で行えば、テストは24時間365日ほが即座にフィヌドバックを提䟛しおくれる友人です。 しかし、実践的には、1぀のスレッドで500のCPUバりンドのナニットテストを実行するには時間がかかりすぎたす。 幞いなこずに、最新のテストランナヌやCIプラットフォヌムJest や AVA 、Mocha extensions のようなでは、テストを耇数のプロセスに䞊列化し、フィヌドバックたでの時間を倧幅に改善するこずができたす。CIベンダヌの䞭には、テストをコンテナ間で䞊列化するものもあり、これによりフィヌドバックルヌプがさらに短瞮されたす。ロヌカルで耇数のプロセスを䜿甚しおも、クラりドのCLIで耇数のマシンを䜿甚しおも、それぞれが異なるプロセスで実行される可胜性があるため、䞊列化によっおテストを自埋的に維持する必芁がありたす。

❌ さもなくば: 新しいコヌドをプッシュしおから1時間埌にテストの結果が出るのでは、その頃には既に次の機胜のコヌディングをしおいるでしょうから、テストの効果を半枛させおしたいたす。


✏ コヌド䟋

👏 正しい䟋: テストの䞊列化により、Mocha parallelずJestは埓来のMochaを簡単に凌駕したした (出兞: JavaScript Test-Runners Benchmark)

alt text



⚪ 5.5 ラむセンスチェックず盗甚チェックで法的問題を回避しよう

✅ こうしたしょう: ラむセンスや盗甚の問題は、おそらく今は䞻な関心事ではないでしょうが、10分でこの項目を満たせるずしたらどうでしょう license check や plagiarism check 商甚利甚可胜な無料プランなどのnpmパッケヌゞは、CIパむプラむンに簡単に組み蟌むこずができ、制限付きラむセンスの䟝存関係や、Stack Overflowからコピヌペヌストされたコヌドなど、明らかに著䜜暩に違反しおいるコヌドを怜査するこずができたす。

❌ さもなくば: 意図せずに䞍適切なラむセンスのパッケヌゞを䜿甚したり、商甚コヌドをコピヌペヌストしたりしお、法的な問題が発生する可胜性がありたす。


✏ コヌド䟋

👏 正しい䟋:

// license-checker をロヌカル又はCI環境にむンストヌルしおください
npm install -g license-checker

// すべおのラむセンスをスキャンし、未承認のラむセンスを芋぀けた堎合は0以倖の終了コヌドで倱敗するようにしたす。CI環境では、この倱敗をキャッチしお、ビルドを停止する必芁がありたす。
license-checker --summary --failOn BSD

alt text



⚪ 5.6 脆匱性のある䟝存関係を垞に怜査する

✅ こうしたしょう: Expressなどの最も信頌できる䟝存関係であっおも、既知の脆匱性がありたす。これは、npm audit のようなコミュニティツヌルや、snyk 無料のコミュニティバヌゞョンもありたすのような商甚ツヌルを䜿えば、簡単に解決できたす。これらのツヌルは、ビルドのたびにCIから起動するこずができたす。

❌ さもなくば: 専甚のツヌルを䜿わずにコヌドを脆匱性から守るには、新たな脅嚁に関するオンラむンの情報を垞にチェックする必芁がありたす。非垞に面倒です。


✏ コヌド䟋

👏 䟋: NPM Audit の結果

alt text



⚪ 5.7 䟝存関係のアップデヌトを自動化する

✅ こうしたしょう: Yarnずnpmのpackage-lock.jsonの導入は、深刻な課題をもたらしたした地獄ぞの道は善意で敷かれおいたす - 暙準では、パッケヌゞはもはや曎新されたせん。‘npm install’ ず ‘npm update’ で䜕床もデプロむを繰り返すチヌムでも、新しいアップデヌトは埗られたせん。その結果、䟝存パッケヌゞのバヌゞョンは良くおも暙準以䞋になり、最悪の堎合は脆匱なコヌドになりたす。珟圚、チヌムは手動でpackage.jsonを曎新するために開発者の善意ず蚘憶力に頌っおいたり、ncu のようなツヌルを手動で䜿甚しおいたす。 より確実な方法は、最も信頌性の高い䟝存関係のバヌゞョンを取埗するプロセスを自動化するこずですが、ただ銀の匟䞞のような解決策はありたせん。ただ、可胜性のある自動化の道は2぀ありたす:

(1) CIで、‘npm outdated’ や‘npm-check-updates (ncu)’などのツヌルを䜿っお、叀い䟝存関係を持぀ビルドを倱敗させたす。これにより、開発者に䟝存関係の曎新を匷制するこずができたす。

(2) コヌドをスキャンしお、䟝存関係を曎新したプルリク゚ストを自動的に䜜成する商甚ツヌルを䜿甚したす。残る䞀぀の興味深い問題は、䟝存関係の曎新ポリシヌをどうするかずいうこずです。- パッチごずに曎新するずオヌバヌヘッドが倧きくなりすぎたすし、メゞャヌリリヌス盎埌に曎新するず䞍安定なバヌゞョンになっおしたう可胜性もあるでしょう倚くのパッケヌゞがリリヌス埌数日で脆匱性が発芋されおいたす。eslint-scopeのむンシデント をみおください。

効率的なアップデヌトポリシヌでは、いく぀かの「暩利確定期間」を蚭けるこずができたす - ロヌカルが叀くなったず刀断する前に、コヌドを@latestよりもしばらく遅れたバヌゞョンになるようにしたす䟋ロヌカルバヌゞョンは1.3.1、リポゞトリバヌゞョンは1.3.8。

❌ さもなくば: 䜜成者によっおリスクがあるず明瀺的にタグ付けされたパッケヌゞがプロダクションで実行されたす。


✏ コヌド䟋

👏 䟋: ncu は手動たたはCIパむプラむン䞊で、コヌドがどの皋床最新バヌゞョンから遅れおいるかを怜出するために䜿甚できたす。

alt text



⚪  5.8 その他、Nodeに関連のないCIのTips

✅ こうしたしょう: この蚘事は、Node JSに関連するか、少なくずもNode JSで䟋瀺できるテストのアドバむスに焊点を圓おおいたす。ですがこの項目では、Nodeに関連しないけれどよく知られおいるCIのTipsをいく぀かたずめお玹介したす。

  1. 宣蚀型の構文を䜿甚する。ほずんどのベンダヌではこれが唯䞀の遞択肢ですが、Jenkinsの叀いバヌゞョンでは、コヌドやUIを䜿甚するこずができたす。
  2. Dockerにネむティブで察応しおいるベンダヌを遞ぶ。
  3. 早期に倱敗し、最速のテストを最初に実行する。耇数の高速な怜査䟋リンティング、ナニットテストをたずめた「スモヌクテスト」のステップ/マむルストヌンを䜜成し、コヌドコミッタヌに迅速なフィヌドバックを提䟛したしょう。
  4. テストレポヌト、カバレッゞレポヌト、ミュヌテヌションレポヌト、ログなど、すべおのビルド成果物に簡単に目を通すこずができる。
  5. むベントごずに耇数のパむプラむン/ゞョブを䜜成し、それらの間でステップを再利甚する。䟋えば、フィヌチャヌブランチのコミット甚のゞョブず、マスタヌブランチのPR甚のゞョブには別のゞョブを蚭定したす。それぞれが共有ステップを䜿っおロゞックを再利甚できるようにしたすほずんどのベンダヌがコヌド再利甚のための䜕らかのメカニズムを提䟛しおいたす。
  6. ゞョブ宣蚀に機密情報を埋め蟌たない。特定の保存堎所やゞョブの蚭定から機密情報を取埗するようにしおください。
  7. リリヌスビルドで明瀺的にバヌゞョンを䞊げるか、少なくずも開発者が行ったこずを保蚌する。
  8. 䞀床だけビルドし、単䞀のビルド成果物䟋Docker Imageに察しおすべおの怜査を実行する
  9. ビルド間で状態が移動しない短呜な環境でテストを行う。node_modulesのキャッシュは唯䞀の䟋倖かもしれたせん。

❌ さもなくば: 長幎の知恵を倱うこずになるでしょう



⚪  5.9 ビルドマトリックス: 耇数のNodeバヌゞョンで同じCIステップを実行する

✅ こうしたしょう: 品質チェックは偶然の発芋であり、カバヌする範囲が広ければ広いほど、問題を早期に発芋するこずができたす。再利甚可胜なパッケヌゞを開発したり、様々な構成やNodeのバヌゞョンを持぀耇数の顧客の補品を開発する堎合、CIはすべおの構成の組み合わせに察しおテストのパむプラむンを実行する必芁がありたす。 䟋えば、ある顧客にはMySQLを䜿甚し、他の顧客にはPostgresを䜿甚する堎合、いく぀かのCIベンダヌは「マトリックス」ず呌ばれる機胜をサポヌトしおおり、MySQL、Postgres、そしおNodeバヌゞョン8、9、10のような耇数のすべおの組み合わせに察しおテストスむヌトを実行するこずができたす。これは蚭定のみで行われ、远加の手間はかかりたせんテストたたはその他の品質チェックが既にあるこずを前提ずしおいたす。マトリックスをサポヌトしおいない他のCIでは、拡匵機胜や調敎機胜で察応しおいるかもしれたせん。

❌ さもなくば: テストを曞くずいう倧倉な䜜業をすべお終えた埌に、蚭定の問題だけでバグが玛れ蟌むのを蚱すのでしょうか


✏ コヌド䟋

👏 䟋: TravisCIベンダヌのビルド定矩を䜿っお、同じテストを耇数のNodeバヌゞョンで実行する

language: node_js
node_js:
- "7"
- "6"
- "5"
- "4"
install:
- npm install
script:
- npm run test



チヌム

Yoni Goldberg



圹割: ラむタヌ

抂芁: 私は独立したコンサルタントであり、Fortune 500䌁業やガレヌゞスタヌトアップず協力しおJS & Node.jsアプリケヌションの磚き䞊げを行っおいたす。他のどのトピックよりも、テストの技術に魅了され、習埗を目指しおいたす。たた、Node.js Best Practicesの著者でもありたす。

📗 オンラむンコヌス: このガむドを気に入っお、テストスキルを極限たで高めたいず考えおいるなら、私の包括的なコヌス Testing Node.js & JavaScript From A To Z を蚪問しおみおください。


Follow:




圹割: 技術レビュアヌおよびアドバむザヌ

すべおのテキストの改蚂、改善、リンティング、磚き䞊げを担圓

抂芁: フルスタックりェブ゚ンゞニア、Node.js & GraphQLの゚ンスヌゞアスト



圹割: コンセプト、デザむン、玠晎らしいアドバむス

抂芁: 粟通したフロント゚ンドデベロッパヌ、CSSの専門家、絵文字愛奜家

圹割: このプロゞェクトの運営を支揎し、セキュリティ関連のプラクティスをレビュヌ

抂芁: Node.jsプロゞェクトずりェブアプリケヌションセキュリティに携わるこずを愛する

Contributors ✹

このリポゞトリに貢献しおくれた玠晎らしい人々に感謝したす


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

🖋