javascript 代碼_如何開始對JavaScript代碼進行單元測試

javascript 代碼

We all know we should write unit tests. But, it's hard to know where to start and how much time to devote to tests compared to actual implementation. So, where to start? And is it just about testing code or do unit tests have other benefits?

我們都知道我們應該編寫單元測試。 但是,與實際實施相比,很難知道從哪里開始以及花多少時間進行測試。 那么,從哪里開始呢? 僅僅是測試代碼還是單元測試還有其他好處?

In this article, I will explain the different types of tests, and which benefits unit testing brings to development teams. I'll showcase Jest - a JavaScript testing framework.

在本文中,我將解釋不同類型的測試,以及單元測試給開發團隊帶來的好處。 我將展示Jest-一個JavaScript測試框架。

不同類型的測試 (Different types of testing)

Before we dive into unit testing specifics, I want to do a quick run through of the different types of tests. There is often some confusion around them and I'm not surprised. Sometimes the line between them is quite thin.

在深入探討單元測試細節之前,我想快速介紹一下不同類型的測試。 他們周圍經常會有一些困惑,我并不感到驚訝。 有時它們之間的界限很細。

單元測試 (Unit tests)

Unit tests only test a single part of your implementation. A unit. No dependencies or integrations, no framework specifics. They're like a method that returns a link in a specific language:

單元測試僅測試實現的一部分。 一個單位。 沒有依賴關系或集成,沒有框架細節。 它們就像一個以特定語言返回鏈接的方法:

export function getAboutUsLink(language){switch (language.toLowerCase()){case englishCode.toLowerCase():return '/about-us';case spanishCode.toLowerCase():return '/acerca-de';}return '';
}

整合測試 (Integration tests)

At some point, your code communicates with a database, file system or another third party. It could even be another module in your app.

在某些時候,您的代碼與數據庫,文件系統或其他第三方進行通信。 它甚至可能是您應用程序中的另一個模塊。

That piece of implementation should be tested by integration tests. They typically have a more complicated setup that involves preparing testing environments, initializing dependencies, and so on.

該實現部分應通過集成測試進行測試。 它們通常具有更復雜的設置,其中涉及準備測試環境,初始化依賴關系等。

功能測試 (Functional tests)

Unit tests and integration tests give you confidence that your app works. Functional tests look at the app from the user's point of view and test that the system works as expected.

單元測試和集成測試使您對應用程序的運行充滿信心。 功能測試從用戶的角度來看應用程序,并測試系統是否按預期工作。

In the diagram above, you see that unit tests form the large base of your application's testing suite. Typically, they are small, there are a lot of them, and they are executed automatically.

在上圖中,您可以看到單元測試構成了應用程序測試套件的基礎。 通常,它們很小,有很多,它們是自動執行的。

So now let's get into unit tests in a bit more detail.

現在,讓我們更詳細地進行單元測試。

為什么要打擾單元測試? (Why Should I Bother Writing Unit Tests?)

Whenever I ask developers whether they wrote tests for their application, they always tell me: "I did not have time for them" or "I don't need them, I know it works."

每當我問開發人員是否為他們的應用程序編寫了測試時,他們總是告訴我:“我沒有時間為他們服務”或“我不需要它們,我知道這是可行的”。

So I smile politely and tell them what I want to tell you. Unit tests are not only about testing. They help you in other ways, too, so you can:

所以我禮貌地微笑著,告訴他們我想告訴你什么。 單元測試不僅涉及測試。 他們也以其他方式幫助您,因此您可以:

Be confident that your code works. When was the last time you committed a code change, your build failed, and half of your app stopped working? Mine was last week.

確信您的代碼有效。 上一次提交代碼更改的時間是什么時候,構建失敗,并且一半的應用程序停止工作? 我的是上周。

But that's still OK. The real problem is when the build succeeds, the change is deployed, and your app starts being unstable.

但這還是可以的。 真正的問題是,當構建成功,部署更改并且您的應用開始不穩定時。

When that happens, you start losing confidence in your code and eventually just pray for the app to work. Unit tests will help you discover issues much sooner and gain confidence.

發生這種情況時,您將開始對代碼失去信心,最終只能祈禱該應用程序正常運行。 單元測試將幫助您更快地發現問題并獲得信心。

Make better architectural decisions. Code changes, but some decisions about platform, modules, structure, and others need to be made during the early stages of a project.

做出更好的架構決策。 代碼已更改,但是在項目的早期階段需要做出一些有關平臺,模塊,結構等的決定。

When you start thinking about unit testing right at the start, it will help you structure your code better and achieve proper separation of concerns. You won't be tempted to assign multiple responsibilities to single code blocks as those would be a nightmare to unit-test.

當您從一開始就開始考慮單元測試時,它將幫助您更好地構建代碼并實現關注點的適當分離。 您不會試圖將多個職責分配給單個代碼塊,因為這將是單元測試的噩夢。

Pinpoint functionality before coding. You write the method's signature and start implementing it right away. Oh, but what should happen in case a parameter is null? What if its value is outside of the expected range or contains too many characters? Do you throw an exception or return null?

編碼前查明功能。 您編寫了方法的簽名,并立即開始實現它。 哦,但是如果參數為null怎么辦? 如果其值超出預期范圍或包含太多字符該怎么辦? 您拋出異常還是返回null?

Unit tests will help you discover all these cases. Look at the questions again and you'll find it's exactly what defines your unit test cases.

單元測試將幫助您發現所有這些情況。 再次查看問題,您會發現這正是定義單元測試用例的要素。

I'm sure there are many more benefits to writing unit tests. These are just the ones that I recall from my experience. Those that I learned the hard way.

我相信編寫單元測試還有更多好處。 這些只是我從我的經歷中回想起的。 那些我很難學的東西。

如何編寫您的第一個JavaScript單元測試 (How to Write Your First JavaScript Unit Test)

But let's get back to JavaScript. We will start with Jest, which is a JavaScript testing framework. It's a tool that enables automatic unit testing, provides code coverage, and lets us easily mock objects. Jest also has an extension for Visual Studio Code available here.

但是,讓我們回到JavaScript。 我們將從Jest開始,這是一個JavaScript測試框架。 它是一種工具,可以進行自動單元測試,提供代碼覆蓋范圍并讓我們輕松地模擬對象。 玩笑也有Visual Studio代碼的擴展可以在這里找到 。

There are also other frameworks, if you're interested, you can check them in this article.

還有其他框架,如果您有興趣,可以在本文中進行檢查。

npm i jest --save-dev

Let's use the previously mentioned method getAboutUsLink as an implementation we want to test:

讓我們使用前面提到的方法getAboutUsLink作為我們要測試的實現:

const englishCode = "en-US";
const spanishCode = "es-ES";
function getAboutUsLink(language){switch (language.toLowerCase()){case englishCode.toLowerCase():return '/about-us';case spanishCode.toLowerCase():return '/acerca-de';}return '';
}
module.exports = getAboutUsLink;

I put this into the index.js file. We can write tests in the same file, but a good practice is to separate unit tests into a dedicated file.

我將其放入index.js文件。 我們可以在同一文件中編寫測試,但是一個好的實踐是將單元測試分成一個專用文件。

The common naming patterns include {filename}.test.js and {filename}.spec.js. I used the first, index.test.js:

常見的命名模式包括{filename}.test.js{filename}.spec.js 。 我使用了第一個index.test.js

const getAboutUsLink = require("./index");
test("Returns about-us for english language", () => {expect(getAboutUsLink("en-US")).toBe("/about-us");
});

First, we need to import the function we want to test. Every test is defined as an invocation of the test function. The first parameter is the name of the test for your reference. The other is an arrow function where we call the function we want to test and specify which result we expect. I

首先,我們需要導入要測試的功能。 每個測試都定義為對test功能的調用。 第一個參數是測試的名稱,以供您參考。 另一個是箭頭函數,我們在其中調用要測試的函數并指定期望的結果。 一世

n this case, we call getAboutUsLink function with en-US as the language parameter. We expect the result to be /about-us.

在這種情況下,我們使用en-US作為語言參數調用getAboutUsLink函數。 我們期望結果是/about-us

Now we can install the Jest CLI globally and run the test:

現在,我們可以全局安裝Jest CLI并運行測試:

npm i jest-cli -g
jest

If you see a configuration-related error, make sure you have your package.json file present. In case you don't, generate one using npm init.

如果看到與配置有關的錯誤,請確保存在package.json文件。 如果您不這樣做,請使用npm init生成一個。

You should see something like this:

您應該會看到以下內容:

PASS  ./index.test.js√ Returns about-us for english language (4ms)console.log index.js:15/about-us
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.389s

Great job! This was the first simple JavaScript unit test from start to end. If you installed the Visual Studio Code extension, it will run tests automatically once you save a file. Let's try it by extending the test with this line:

很好! 這是從頭到尾的第一個簡單JavaScript單元測試。 如果安裝了Visual Studio Code擴展,則在保存文件后它將自動運行測試。 讓我們通過以下代碼擴展測試:

expect(getAboutUsLink("cs-CZ")).toBe("/o-nas");

Once you save the file, Jest will inform you that the test failed. That helps you discover potential issues even before committing your changes.

保存文件后,Jest將通知您測試失敗。 這甚至可以在您提交更改之前幫助您發現潛在的問題。

測試高級功能和模擬服務 (Testing Advanced Functionality and Mocking Services)

In real life, the language codes for the getAboutUsLink method would not be constants in the same file. Their value is typically used throughout the project so they would be defined in their own module and imported into all functions that use them.

在現實生活中,getAboutUsLink方法的語言代碼在同一文件中不是常量。 它們的值通常在整個項目中使用,因此它們將在自己的模塊中定義,并導入到使用它們的所有函數中。

import { englishCode, spanishCode } from './LanguageCodes'

You can import these constants into the test the same way. But the situation will get more complicated if you're working with objects instead of simple constants. Take a look at this method:

您可以以相同的方式將這些常量導入測試。 但是,如果使用對象而不是簡單的常量,情況將變得更加復雜。 看一下這個方法:

import { UserStore } from './UserStore'
function getUserDisplayName(){const user = UserStore.getUser(userId);return `${user.LastName}, ${user.FirstName}`;
}

This method uses imported UserStore:

此方法使用導入的UserStore

class User {getUser(userId){// logic to get data from a database}setUser(user){// logic to store data in a database}
}
let UserStore = new User();
export { UserStore }

In order to properly unit test this method, we need to mock UserStore. A mock is a substitute for the original object. It allows us to separate dependencies and real data from the tested method's implementation just like dummies help with crash tests of cars instead of real people.

為了正確地對該方法進行單元測試,我們需要模擬UserStore 。 模擬可以替代原始對象。 它使我們能夠從測試方法的實現中分離依賴項和真實數據,就像假人可以幫助汽車(而不是真實的人)進行碰撞測試一樣。

If we didn't use the mock, we'd be testing both this function and the store. That would be an integration test and we would likely need to mock the used database.

如果我們不使用該模擬,那么我們將同時測試此功能和商店。 那將是一個集成測試,我們可能需要模擬使用的數據庫。

模擬服務 (Mocking a Service)

To mock objects, you can either provide a mocking function or a manual mock. I will focus on the latter as I have a plain and simple use-case. But feel free to check out other mocking possibilities Jest provides.

要模擬對象,可以提供模擬功能或手動模擬。 由于我有一個簡單的用例,因此我將重點討論后者。 但是,請隨時查看Jest提供的其他模擬可能性 。

jest.mock('./UserStore',?()?=>?({UserStore:?({getUser:?jest.fn().mockImplementation(arg?=>?({FirstName:?'Ondrej',LastName:?'Polesny'})),setUser: jest.fn()})
}));

First, we need to specify what are we mocking - the ./UserStore module. Next, we need to return the mock that contains all exported objects from that module.

首先,我們需要指定要./UserStore模塊。 接下來,我們需要返回包含該模塊中所有導出對象的模擬對象。

In this sample, it's only the User object named UserStore with the function getUser. But with real implementations, the mock may be much longer. Any functions you don't really care about in the scope of unit testing can be easily mocked with jest.fn().

在此示例中,只有名為UserStoreUser對象具有功能getUser 。 但是對于實際的實現,模擬可能會更長。 使用jest.fn()可以輕松jest.fn()在單元測試范圍內您真正不在意的任何功能。

The unit test for the getUserDisplayName function is similar to the one we created before:

getUserDisplayName函數的單元測試類似于我們之前創建的單元測試:

test("Returns?display?name",?()?=>?{expect(getUserDisplayName(1)).toBe("Polesny,?Ondrej");
})

As soon as I save the file, Jest tells me I have 2 passing tests. If you're executing tests manually, do so now and make sure you see the same result.

保存文件后,Jest告訴我我有2個通過測試。 如果您手動執行測試,請立即執行,并確保看到相同的結果。

代碼覆蓋率報告 (Code Coverage Report)

Now that we know how to test JavaScript code, it's good to cover as much code as possible with tests. And that is hard to do. In the end, we're just people. We want to get our tasks done and unit tests usually yield an unwanted workload that we tend to overlook. Code coverage is a tool that helps us fight that.

既然我們知道如何測試JavaScript代碼,那么最好在測試中覆蓋盡可能多的代碼。 這很難做到。 最后,我們就是人。 我們希望完成任務,單元測試通常會產生不必要的工作負載,而我們往往會忽略這些工作負載。 代碼覆蓋率是可以幫助我們解決這一問題的工具。

Code coverage will tell you how big a portion of your code is covered by unit tests. Take for example my first unit test checking the getAboutUsLink function:

代碼覆蓋率將告訴您單元測試覆蓋了代碼的很大一部分。 以我檢查getAboutUsLink函數的第一個單元測試getAboutUsLink

test("Returns about-us for english language", () => {expect(getAboutUsLink("en-US")).toBe("/about-us");
});

It checks the English link, but the Spanish version stays untested. The code coverage is 50%. The other unit test is checking the getDisplayName function thoroughly and its code coverage is 100%. Together, the total code coverage is 67%. We had 3 use cases to test, but our tests only cover 2 of them.

它檢查英語鏈接,但西班牙語版本未經測試。 代碼覆蓋率為50%。 另一個單元測試是徹底檢查getDisplayName函數,其代碼覆蓋率為100%。 在一起,總代碼覆蓋率為67%。 我們有3個用例進行測試,但我們的測試僅涵蓋其中2個。

To see the code coverage report, type the following command into the terminal:

要查看代碼覆蓋率報告,請在終端中鍵入以下命令:

jest --coverage

Or, if you're using Visual Studio Code with the Jest extension, you can run the command (CTRL+SHIFT+P) Jest: Toggle Coverage Overlay. It will show you right in the implementation which lines of code are not covered with tests.

或者,如果您將Visual Studio Code與Jest擴展名一起使用,則可以運行(CTRL + SHIFT + P) Jest:Toggle Coverage Overlay命令 。 它會在實現中正確顯示出哪些代碼行未包含在測試中。

By running the coverage check, Jest will also create an HTML report. Find it in your project folder under coverage/lcov-report/index.html.

通過運行覆蓋率檢查,Jest還將創建一個HTML報告。 在coverage/lcov-report/index.html下的項目文件夾中找到它。

Now, I don't have to mention that you should strive for 100% code coverage, right? :-)

現在,我不必提起您應該爭取100%的代碼覆蓋率,對吧? :-)

摘要 (Summary)

In this article, I showed you how to start with unit testing in JavaScript. While it's nice to have your code coverage shine at 100% in the report, in reality, it's not always possible to (meaningfully) get there. The goal is to let unit tests help you maintain your code and ensure it always works as intended. They enable you to:

在本文中,我向您展示了如何開始使用JavaScript進行單元測試。 雖然使代碼覆蓋率在報告中達到100%很高興,但實際上,并非總是可以(有意義地)達到目標。 目的是讓單元測試幫助您維護代碼并確保其始終按預期工作。 它們使您能夠:

  • clearly define implementation requirements,

    明確定義實施要求,
  • better design your code and separate concerns,

    更好地設計代碼并分離關注點,
  • discover issues you may introduce with your newer commits,

    發現您可能在較新的提交中引入的問題,
  • and give you confidence that your code works.

    并給您信心,您的代碼可以正常工作。

The best place to start is the Getting started page in the Jest documentation so you can try out these practices for yourself.

最好的起點是Jest文檔中的“ 入門”頁面,因此您可以自己嘗試這些實踐。

Do you have your own experience with testing code? I'd love to hear it, let me know on Twitter or join one of my Twitch streams.

您有測試代碼方面的經驗嗎? 我希望聽到它,在Twitter上告訴我,或加入我的Twitch視頻流之一 。

翻譯自: https://www.freecodecamp.org/news/how-to-start-unit-testing-javascript/

javascript 代碼

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390401.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390401.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390401.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

個人作業——軟件工程實踐總結作業

一、請回望暑假時的第一次作業,你對于軟件工程課程的想象 1)對比開篇博客你對課程目標和期待,“希望通過實踐鍛煉,增強計算機專業的能力和就業競爭力”,對比目前的所學所練所得,在哪些方面達到了你的期待和…

(轉)在阿里,我們如何管理代碼分支?

阿里妹導讀:代碼分支模式的選擇并沒有絕對的正確和錯誤之分,關鍵是與項目的規模和發布節奏相匹配。阿里協同研發平臺在經過眾多實踐歷練后,總結出了一套獨創的分支管理方法:AoneFlow,通過兼備靈活高效與簡單實用的流程…

WIN10系統 截圖或者某些程序時屏幕會自動放大怎么辦

右擊這個應用程序,兼容性,以兼容模式運行,同時勾選高DPI設置時禁止顯示縮放即可

css背景圖片添加url_CSS背景圖片–如何向您的Div添加圖片URL

css背景圖片添加urlSay you want to put an image or two on a webpage. One way is to use the background-image CSS property. 假設您要在網頁上放置一兩個圖片。 一種方法是使用background-image CSS屬性。 This property applies one or more background images to an el…

golang基礎01

1.環境變量:go env//代碼目錄和第三方庫文件set GOPATHC:\Users\hanxiaodong\go//go安裝目錄set GOROOTC:\Gopath里要配置:goroot/bin;和gopath/bin; gopath目錄下三個文件夾:pkg:編譯好的庫文件 .a 文件bin:可執行文件…

hugo 能做web開發嗎_如何自托管Hugo Web應用

hugo 能做web開發嗎After hosting with Netlify for a few years, I decided to head back to self hosting. There are a few reasons for that, but the main reasoning was that I had more control over how things worked. 在Netlify托管了幾年之后,我決定回到…

資源 | 深度學習課程入門與介紹

【1】Andrew NG Deep Learning.ai http://deeplearning.ai/網易云課堂(中文字幕):http://mooc.study.163.com/smartSpec/detail/1001319001.htm推薦理由:Andrew Ng老師是講課的能手,很多人認識他是從Stanford的經典《機…

PostCSS 以及 cssnext語法

本文是對近兩天學習postcss的總結,在這里分享給大家。 如有錯誤,還請指正! 什么是postcss postcss 一種對css編譯的工具,類似babel對js的處理,常見的功能如: 1 . 使用下一代css語法 2 . 自動補全瀏覽器前綴…

5187. 收集足夠蘋果的最小花園周長

給你一個用無限二維網格表示的花園,每一個 整數坐標處都有一棵蘋果樹。整數坐標 (i, j) 處的蘋果樹有 |i| |j| 個蘋果。 你將會買下正中心坐標是 (0, 0) 的一塊 正方形土地 ,且每條邊都與兩條坐標軸之一平行。 給你一個整數 neededApples &#xff0c…

虛擬機 VMware Workstation12 安裝OS X 系統

Windows下虛擬機安裝Mac OS X —– VMware Workstation12安裝Mac OS X 10.11本文即將介紹WIN虛擬MAC的教程。完整詳細教程(包含安裝中的一些問題)【并且適用其他mac os x版本】Windows下 VM12虛擬機安裝OS X 10.11(詳細教程) 工具/原料 Mac OS X 10.11 鏡…

aws dynamodb_DynamoDB備忘單–您需要了解的有關2020 AWS認證開發人員助理認證的Amazon Dynamo DB的所有信息

aws dynamodbThe emergence of cloud services has changed the way we build web-applications. This in turn has changed the responsibilities of a Web Developer. 云服務的出現改變了我們構建Web應用程序的方式。 反過來,這改變了Web開發人員的職責。 We use…

北大CIO走進龍泉寺交流研討會圓滿舉行

緣起 2016年4月16日,北京大學信息化與信息管理研究中心秘書長姚樂博士與國家非物質文化遺產蔚縣剪紙傳承人周淑英女士一起在龍泉寺拜見了中國佛教協會會長、龍泉寺主持學誠法師。在拜見學誠法師時,姚樂博士與學誠法師聊到了“賢二機器僧”和人工智能。姚…

負載均衡種類

http://blog.csdn.net/zhoudaxia/article/details/23672319DNS DNS輪詢是最簡單的負載均衡方式。以域名作為訪問入口,通過配置多條DNS A記錄使得請求可以分配到不同的服務器。DNS輪詢沒有快速的健康檢查機制,而且只支持WRR的調度策略導致負載很難“均衡”…

代碼流星雨是什么形式_為什么要在2020年與流星合作

代碼流星雨是什么形式Meteor, an allegedly dead development platform, is still alive and can bring massive value to your everyday coding experience.Meteor,據稱已失效的開發平臺,仍然有效,可以為您的日常編碼體驗帶來巨大的價值。 …

Centos7 Docker私有倉庫搭建

Centos7 Docker私有倉庫搭建 倉庫:集中存放鏡像的地方,可分為公共倉庫和私有倉庫(公共倉庫"http://hub.docker.com"或國內的"http://www.daocloud.io") Registry:注冊服務器才是存放倉庫具體的服務…

MySQL觸發器使用詳解

MySQL包含對觸發器的支持。觸發器是一種與表操作有關的數據庫對象,當觸發器所在表上出現指定事件時,將調用該對象,即表的操作事件觸發表上的觸發器的執行。 創建觸發器在MySQL中,創建觸發器語法如下: 代碼如下: CREATE…

java中訪問修飾符_Java中的訪問修飾符介紹

java中訪問修飾符什么是訪問修飾符? (What are Access Modifiers?) Have you ever wanted to define how people would access some of your properties? You would not want anyone using your underwear. However, your close friends and relatives can use yo…

VIM 編輯器

2019獨角獸企業重金招聘Python工程師標準>>> VIM 相對于VI 的提升 VIM 支持多級撤銷VIM 可以跨平臺運行VIM 支持語法高亮VIM 支持圖形界面VIM 編輯器的操作模式 Command Mode -命令模式Insert Mode -輸入模式Last Lin Mode -底行模式#使用yum 命令安裝vim 軟件&…

/etc/profile、/etc/bashrc、~/.bash_profile、~/.bashrc 文件的作用

轉載自:http://blog.csdn.net/u013968345/article/details/21262033 /etc/profile:此文件為系統的每個用戶設置環境信息,當用戶第一次登錄時,該文件被執行. 并從/etc/profile.d目錄的配置文件中搜集shell的設置. /etc/bashrc:為每一個運行bash shell的用戶執行此文件…

python初學者_終極Python初學者手冊

python初學者Python has become one of the fastest-growing programming languages over the past few years. 在過去的幾年中,Python已成為增長最快的編程語言之一。 Not only it is widely used, it is also an awesome language to tackle if you want to get …