From 1486397d57f7d4003b5adf0410faf3ce47c19a6c Mon Sep 17 00:00:00 2001 From: ycaptain Date: Sat, 4 May 2024 02:09:47 -0400 Subject: [PATCH 1/2] fix missing chapter 1.9 for zh-CN fix missing chapter 1.9 for zh-CN --- readme-zh-CN.md | 57 ++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/readme-zh-CN.md b/readme-zh-CN.md index 18b3ee5f..adc137dc 100644 --- a/readme-zh-CN.md +++ b/readme-zh-CN.md @@ -541,13 +541,13 @@ expect(menu).toMatchInlineSnapshot(`

-## ⚪ ️1.9 不要写全局的 fixtures 和 seeds,而是放在每个测试中 +## ⚪ ️1.9 复制代码,但只复制必要部分 -:white_check_mark: **建议:** 参照黄金法则,每条测试需要在它自己的 DB 行中运行避免互相污染。现实中,这条规则经常被打破:为了性能提升而在执行测试前全局初始化数据库([也被称为‘test fixture’](https://en.wikipedia.org/wiki/Test_fixture))。尽管性能很重要,但是它可以通过后面讲的「分组件测试」缓和。为了减轻复杂度,我们可以在每个测试中只初始化自己需要的数据。除非性能问题真的非常显著,那么可以做一定的妥协——仅在全局放不会改变的数据(比如 query)。 +:white_check_mark: **建议:** 确保包含影响测试结果的所有必要细节,但不要多加。比如,考虑一个需要处理 100 行 JSON 输入的用例——在每个用例都粘贴一份是很繁琐的。将其提取到 `transferFactory.getJSON()` 中会使得这个用例变得模糊——没有数据,就很难将测试结果与原因联系起来(“为什么会返回 400 状态码”)。经典书籍 x-unit patterns 将这种模式称为“神秘的客人”——有些看不到的东西影响了我们的测试结果,我们不清楚是什么。更好的做法是把重复冗长的部分提取出来,并明确指出对用例重要的具体细节。以上面的例子为例,用例可以通过传入的参数来突出重要细节:`transferFactory.getJSON({ sender: undefined })`。在这个例子中,读者可以立即推断出,变量 `sender` 为 `undefined` 是导致用例预期校验错误或者任何类似合理结果的原因。
-❌ **否则:** 一部分测试挂了,我们的团队花费大量宝贵时间后发现,是由于两个测试同时改变了同一个 seed 数据导致的。 +❌ **否则:** 直接复制 500 行 JSON 文本会使得测试难以维护和阅读。而将所有内容提取出去,会使得这个用例难以理解。
@@ -556,45 +556,40 @@ expect(menu).toMatchInlineSnapshot(`
-### :thumbsdown: 反例: 用例之间不独立,而是依赖同一个全局钩子来生成全局 DB 数据 +### :thumbsdown: 反例: 用例失败原因不明确,因为所有原因都是外部的,并隐藏在大量的 JSON 文本里 -![](https://img.shields.io/badge/🔧%20Example%20using%20Mocha-blue.svg - "Examples with Jest") +![](https://img.shields.io/badge/🔧%20Example%20using%20Mocha-blue.svg "Examples with Mocha") ```javascript -before(() => { - //adding sites and admins data to our DB. Where is the data? outside. At some external json or migration framework - await DB.AddSeedDataFromJson('seed.json'); -}); -it("When updating site name, get successful confirmation", async () => { - //I know that site name "portal" exists - I saw it in the seed files - const siteToUpdate = await SiteService.getSiteByName("Portal"); - const updateNameResult = await SiteService.changeName(siteToUpdate, "newName"); - expect(updateNameResult).to.be(true); -}); -it("When querying by site name, get the right site", async () => { - //I know that site name "portal" exists - I saw it in the seed files - const siteToCheck = await SiteService.getSiteByName("Portal"); - expect(siteToCheck.name).to.be.equal("Portal"); //Failure! The previous test change the name :[ -}); +test("When no credit, then the transfer is declined", async() => { + // Arrange + const transferRequest = testHelpers.factorMoneyTransfer() //get back 200 lines of JSON; + const transferServiceUnderTest = new TransferService(); + // Act + const transferResponse = await transferServiceUnderTest.transfer(transferRequest); + + // Assert + expect(transferResponse.status).toBe(409);// But why do we expect failure: All seems perfectly valid in the test 🤔 +}); ```
-### :clap: 正例: 每个用例操作它自己的数据集 +### :clap: 正例: 突出每个用例结果的原因 ```javascript -it("When updating site name, get successful confirmation", async () => { - //test is adding a fresh new records and acting on the records only - const siteUnderTest = await SiteService.addSite({ - name: "siteForUpdateTest" - }); - const updateNameResult = await SiteService.changeName(siteUnderTest, "newName"); +test("When no credit, then the transfer is declined ", async() => { + // Arrange + const transferRequest = testHelpers.factorMoneyTransfer({userCredit:100, transferAmount:200}) //obviously there is lack of credit + const transferServiceUnderTest = new TransferService({disallowOvercharge:true}); - expect(updateNameResult).to.be(true); -}); + // Act + const transferResponse = await transferServiceUnderTest.transfer(transferRequest); + // Assert + expect(transferResponse.status).toBe(409); // Obviously if the user has no credit it should fail +}); ``` @@ -2054,4 +2049,4 @@ script: **About:** 喜欢从事 Node.js 项目和 Web 应用安全性的工作。 \ No newline at end of file +--> From b05499c3cef61bf16993e7cc10206bb9748d2a96 Mon Sep 17 00:00:00 2001 From: ycaptain Date: Sat, 4 May 2024 02:16:19 -0400 Subject: [PATCH 2/2] fix missing chapter 1.9 for zh-TW fix missing chapter 1.9 for zh-TW --- readme-zh-TW.md | 51 +++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/readme-zh-TW.md b/readme-zh-TW.md index d45796a7..61d0c596 100644 --- a/readme-zh-TW.md +++ b/readme-zh-TW.md @@ -537,13 +537,13 @@ it("When visiting TestJavaScript.com home page, a menu is displayed", () => {

-## ⚪ ️1.9 避免使用全域的 test fixtures 或 seeds,而是放進每個測試中 +## ⚪ ️1.9 複製代碼,但只複製必要部分 -:white_check_mark: **建議:** 參照黃金原則,每個測試需要在它自己的 DB 中進行操作避免互相污染。但現實中,這條規則經常被打破:為了性能的提升而在執行測試前初始化全域資料庫 (也被稱為"[test fixture](https://en.wikipedia.org/wiki/Test_fixture)")。儘管性能很重要,但是它可以通過後面講的「組件測試」來做取捨。為了減輕複雜度,我們可以在每個測試中只初始化自己需要的數據。除非性能問題真的非常嚴重,那還是可以做一定程度的妥協 - 僅在全域放不會改變的數據 (比如 query)。 +:white_check_mark: **建議:** 確保包含影響測試結果的所有必要細節,但不要多加。比如,考慮一個需要處理 100 行 JSON 輸入的例子——在每個例子都貼一份是很繁瑣的。將其提取到 `transferFactory.getJSON()` 中會使得這個例子變得模糊——沒有數據,就很難將測試結果與原因聯繫起來(“為什麼會返回 400 狀態碼”)。經典書籍 x-unit patterns 將這種模式稱為“神秘的客人”——有些看不到的東西影響了我們的測試結果,我們不清楚是什麼。更好的做法是把重複冗長的部分提取出來,並明確指出對例子重要的具體細節。以上面的例子為例,例子可以通過傳入的參數來突出重要細節:`transferFactory.getJSON({ sender: undefined })`。在這個例子中,讀者可以立即推斷出,變量 `sender` 為 `undefined` 是導致例子預期驗證錯誤或任何類似合理結果的原因。
-❌ **否則:** 有一些測試 fail 了,團隊花了許多時間後發現,只是因為兩個測試同時改變了同一個 seed。 +❌ **否則:** 直接複製 500 行 JSON 文本會使得測試難以維護和閱讀。而將所有內容提取出去,會使得這個例子難以理解。
@@ -551,43 +551,40 @@ it("When visiting TestJavaScript.com home page, a menu is displayed", () => {
-### :thumbsdown: 反例:測試案例之間不是獨立的。而是相依於全域的 DB 資料 +### :thumbsdown: 反例:例子失敗原因不明確,因為所有原因都是外部的,並隱藏在大量的 JSON 文本裡 ![](https://img.shields.io/badge/🔧%20Example%20using%20Mocha-blue.svg "Examples with Mocha") ```javascript -before(async () => { - // adding sites and admins data to our DB. Where is the data? outside. At some external json or migration framework - await DB.AddSeedDataFromJson('seed.json'); -}); -it("When updating site name, get successful confirmation", async () => { - // I know that site name "portal" exists - I saw it in the seed files - const siteToUpdate = await SiteService.getSiteByName("Portal"); - const updateNameResult = await SiteService.changeName(siteToUpdate, "newName"); - expect(updateNameResult).to.be(true); -}); -it("When querying by site name, get the right site", async () => { - // I know that site name "portal" exists - I saw it in the seed files - const siteToCheck = await SiteService.getSiteByName("Portal"); - expect(siteToCheck.name).to.be.equal("Portal"); // Failure! The previous test change the name :[ -}); +test("When no credit, then the transfer is declined", async() => { + // Arrange + const transferRequest = testHelpers.factorMoneyTransfer() //get back 200 lines of JSON; + const transferServiceUnderTest = new TransferService(); + + // Act + const transferResponse = await transferServiceUnderTest.transfer(transferRequest); + // Assert + expect(transferResponse.status).toBe(409);// But why do we expect failure: All seems perfectly valid in the test 🤔 +}); ```
-### :clap: 正例:每個測試案例只操作他自己的資料 +### :clap: 正例:突出每個例子結果的原因 ```javascript -it("When updating site name, get successful confirmation", async () => { - // test is adding a fresh new records and acting on the records only - const siteUnderTest = await SiteService.addSite({ - name: "siteForUpdateTest" - }); - const updateNameResult = await SiteService.changeName(siteUnderTest, "newName"); +test("When no credit, then the transfer is declined ", async() => { + // Arrange + const transferRequest = testHelpers.factorMoneyTransfer({userCredit:100, transferAmount:200}) //obviously there is lack of credit + const transferServiceUnderTest = new TransferService({disallowOvercharge:true}); + + // Act + const transferResponse = await transferServiceUnderTest.transfer(transferRequest); - expect(updateNameResult).to.be(true); + // Assert + expect(transferResponse.status).toBe(409); // Obviously if the user has no credit it should fail }); ```