Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix missing chapter 1.9 in Chinese and Traditional Chinese version #261

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 26 additions & 31 deletions readme-zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -541,13 +541,13 @@ expect(menu).toMatchInlineSnapshot(`

<br/><br/>

## ⚪ ️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` 是导致用例预期校验错误或者任何类似合理结果的原因
<br/>


❌ **否则:** 一部分测试挂了,我们的团队花费大量宝贵时间后发现,是由于两个测试同时改变了同一个 seed 数据导致的
❌ **否则:** 直接复制 500 行 JSON 文本会使得测试难以维护和阅读。而将所有内容提取出去,会使得这个用例难以理解


<br/>
Expand All @@ -556,45 +556,40 @@ expect(menu).toMatchInlineSnapshot(`

<br/>

### :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 🤔
});
```
<br/>

### :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
});
```

</details>
Expand Down Expand Up @@ -2054,4 +2049,4 @@ script:
**About:** 喜欢从事 Node.js 项目和 Web 应用安全性的工作。
<!--stackedit_data:
eyJoaXN0b3J5IjpbMTc4NDc5MDYwM119
-->
-->
51 changes: 24 additions & 27 deletions readme-zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -537,57 +537,54 @@ it("When visiting TestJavaScript.com home page, a menu is displayed", () => {

<br/><br/>

## ⚪ ️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` 是導致例子預期驗證錯誤或任何類似合理結果的原因

<br/>

❌ **否則:** 有一些測試 fail 了,團隊花了許多時間後發現,只是因為兩個測試同時改變了同一個 seed
❌ **否則:** 直接複製 500 行 JSON 文本會使得測試難以維護和閱讀。而將所有內容提取出去,會使得這個例子難以理解

<br/>

<details><summary>✏ <b>程式範例</b></summary>

<br/>

### :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 🤔
});
```

<br/>

### :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
});
```

Expand Down