current position:Home>Front end test collection - how to write front-end test to ensure code quality?
Front end test collection - how to write front-end test to ensure code quality?
2021-08-27 08:58:57 【EvalStudio】
“ automated testing ” There are thousands of articles related to this topic , But if you look closely, you will find that a large part of them are back-end or BFF Test of , Their test coverage can almost reach 100%( According to different requirements of different teams ).
But when it comes to front-end testing , Few people say they can do 100% Coverage of , Of course, there's a reason , Front-end UI Change too fast , Adjust often , Pure right UI Whether the test is worth taking the time to write ? Most front ends will Say NO.
Today's article is a collection of front-end tests , This paper analyzes several test types included in front-end test from the principle of test pyramid , The cost performance of each test type is introduced 、 Usage scenarios and test frameworks or tools commonly used for each test . Because unit testing is often the largest proportion of automated testing , So from 2 This paper introduces how to write a unit test , How to reasonably use test avatars to isolate test dependencies , Improve test independence . Expect front-end test strategy development & Practice can help improve software quality , Reduce “ 8、 ... and (B) o (U) Brother (G)”.
Test pyramids
The test pyramid is Mike Cohn stay 《Succeeding with Agile》 The concept of , It divides the test into three layers :UI Test layer 、Service Test layer and unit test . The higher the cost from the bottom up , The less efficient , So it's recommended to go from top to bottom , The more you write down, the more test cases . But from today's technical point of view, this is not entirely the case , Because now the front end UI The cost of layer testing is much less than before , for example UI Snapshot test 、 The key to relying on the front-end framework DOM Element testing, etc .
Benchmarking now , The most significant reference of the whole test pyramid is :
- (1) Different levels of test granularity
- (2) The higher the level is. , Write fewer tests , Because of its low cost performance .
So now the more appropriate front-end test pyramid should be similar to :
-
(1)E2E test
Some team front ends also include E2E test , In order to ensure stable functional availability , however E2E The cost of testing is relative to other 2 The floor is higher , Therefore, the functions of the main process should be as E2E Test of .
-
(2) Integration testing
When you encounter complex front-end business , State management is often introduced , from DOM Operation trigger status change , cause re-render, Integration testing can be used to ensure that the whole process is correct .
-
(3) unit testing
Speaking of unit testing , Back end or BFF Unit test , It's easy for everyone to understand , So what does the front-end unit test generally include ? Unit tests apply to Util Method , commonly util Methods are pure functions , The unit test of pure function is very easy to write , Because every input and output is clear . Of course, in addition to the above , It also includes unit tests for data processing in state management 、UI Unit testing at the level of . Specific test preparation, follow-up to see specific cases .
Common front-end test methods
The test pyramid was introduced earlier , So what are the test methods often used in the front-end field ? The following are the test methods commonly used in practice :
unit testing
In the front end , A unit can be a UI Components 、 One Util Method 、 A state management processing function 、 A business logic function, etc , These functions can be guaranteed through unit testing .
Here are Jest A test case in the document , This test is for sum Methods were tested , In real projects , Often write a lot of custom methods , The responsibilities of each method should be very clear , You can specify the input and output parameters , Test each scenario .
function sum(a, b) {
return a + b;
}
module.exports = sum;
Copy code
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
Copy code
Snapshot test
Snapshot test , seeing the name of a thing one thinks of its function , It's a test for snapshots . In the front-end test framework , Snapshot tests are often performed for the first time , Make a snapshot , With Jest Case study ,React The snapshot test of the component is as follows :
import React from 'react';
import renderer from 'react-test-renderer';
import Link from '../Link.react';
it('renders correctly', () => {
const tree = renderer
.create(<Link page="http://www.facebook.com">Facebook</Link>)
.toJSON();
expect(tree).toMatchSnapshot();
});
Copy code
For details, please refer to jest In document Snapshot test (www.jestjs.cn/docs/snapsh…)
The above tests run for the first time , A snapshot file was created as follows , Saved the snapshot results of the first run . When the component changes , When you run the snapshot test again , New snapshot results will be regenerated , This new snapshot result will be compared with the previously saved snapshot file , If it's not consistent , The snapshot test will fail . Of course, test frameworks generally provide commands to update snapshots ,Jest In the framework U command .
exports[`renders correctly 1`] = ` <a className="normal" href="http://www.facebook.com" onMouseEnter={[Function]} onMouseLeave={[Function]} > Facebook </a> `;
Copy code
According to the analysis of the above snapshot test , It can be found that for UI Components are not suitable for snapshot testing , Because the snapshot is updated almost every time to pass the test , Then you lose the meaning of snapshot testing . Therefore, snapshot testing is generally applicable to stable front-end pages or components , You can avoid erroneous changes through snapshot testing .
Contract test
Now many teams are front-end and back-end separated teams , It often takes a lot of time on joint commissioning ( For example, interface availability ? Whether the interface complies with the document ? Whether the interface is stable ?). Contract testing is a contract between provider and consumer based on interface , This contract is generally an interface specification document , Often contains requests URL、Method、 Request parameters 、response Data structure, etc . In a scene where the front and back ends are separated , The contract test is more biased towards Service Between API test , Mainly to decouple the dependencies between services , To speed up the API The speed of verification .
The front end is the consumer of the contract , What contract testing often does is create corresponding unit tests , In this unit test, a test that conforms to the contract specification is initiated request To Mock Server Get the corresponding response To verify the results , When there is no mock server when , The front end can also add contract compliant mock response File to decouple API. Common tools are based on YAML Of Swagger Specification, And based on JSON Format Pact Specification, Refer to their documentation for details .
- Swagger Specification:swagger.io/specificati…
- Pact Specification:github.com/pact-founda…
E2E test
E2E test , Also called end-to-end testing , More functional automated testing . This kind of test often simulates a real user operation to verify whether the results meet the expectations .E2E The test is usually a black box test , Focus on whether the whole system meets user expectations .
There are many tools that can be used for the above test methods , See the next chapter for details .
Front end test tools
Testing tools generally include testing frameworks Test Framework、 Assertions library Assertion Library、mock library 、 Test report, tool library, etc .
Let's introduce some libraries commonly used in front-end testing , Attach the official document .
Testing Library
Test Library Is a collection of test libraries , It simulates user interaction , Test by verifying the external state change of the component , In this way, you can not go deep into the implementation details of the component , Improve the efficiency of testing . The following is an overview of React Testing Library, Of course Testing Library There is also vue testing library and angular testing library Such as the library .
at present React The officially recommended test plan is React Testing Library + Jest The combination of .
We recommend using React Testing Library, It makes it as easy to write test cases for components as it is for end users . When used React edition <= 16 when , have access to Enzyme Test tools , It makes it easy to React The output of the component is asserted 、 Control and traverse .
React Testing Library yes Testing Library A test library in , When you want to write maintainable React components test , No need to pay attention React Detailed internal implementation of the component , You can use this library for component testing .React Testing Library Provides many functions to locate elements , The positioned element can be used as an assertion or user interaction . Please refer to file .
Reference link :
- React Testing Library:testing-library.com/react
- Test Library:github.com/testing-lib…
- Enzyme:airbnb.io/enzyme/
Jest
Jest yes Facebook Open source testing framework , Built in JSDOM Running environment 、 Assertions library , Provide coverage (coverage)、 Snapshot comparison (snapshots)、 Analog functions (Mock Funtion) And so on , It is one of the most widely used front-end testing frameworks at present . If you are using Create React App The initialization of the React frame , It's built in Jest As its test library . If you are from 0 Start building the framework , According to official documents, it is also easy to introduce Jest, I won't go into details here ,Jest It's very easy to get started , If necessary, you can check 《JEST file 》.
Reference link :
- JEST file :jestjs.io/zh-Hans/doc…
- Create React App Test documentation :create-react-app.dev/docs/runnin…
Mocha
Mocha It's based on JS Flexible testing framework , Contains asynchronous processing (beforeEach、afterEach Wait for the hook function ,Promise To deal with 、timeout Processing and so on )、 Concise test report 、 And you can customize the assertion tool :
- should.js - BDD Style throughout (github.com/shouldjs/sh…)
- expect.js - expect() Style assertion (github.com/LearnBoost/…)
- chai - expect(),assert() and should Assertion of style (chaijs.com/)
- better-assert - C Style self documenting assert() .(github.com/visionmedia…)
- unexpected - “ Extensible BDD Assertion tool ”.(unexpected.js.org/)
These assertions can be added and used by users .
Jasmine
Angular The default testing framework is Karma( from Google The front-end test run framework developed by the team ) + Jasmine.
Jasmine It is a fully functional testing framework , Has a complete assertion method 、Setup and Teardown Method 、 Asynchronous processing 、Mock Functions, etc . Jasmine Document links :github.com/jasmine/jas…
Cypress
Cypress Is in Mocha API Developed on the basis of E2E The test framework , Does not rely on the front-end framework , There is no need for other test tool Libraries , Simple configuration , And provides a powerful GUI Graphical tools , Can automatically capture the screen , It can also be used in the test process Debug . It is a popular end-to-end testing tool . Specific reference documentation , Write use cases according to the document and get familiar with them . Cypress Document links :www.cypress.io/
There are many other tool Libraries , Be similar to Jasmine、Selenium、Puppeteer、phantomjs I'm not going to list , If necessary, you can see the document and use it by yourself , More libraries can be seen Another little partner sorted out the test related Library (github.com/huaize2020/…).
Front end test strategy
The front end has a lot of UI Interaction , The cost performance of this part of the test is relatively low , because DOM The structure often changes , If you really need testing, consider snapshot testing .
In the front-end project, what needs to be tested is the logical part of the front-end code , Now the front end is not just UI, It also includes state management and business logic , For this part, unit testing can be used to ensure .
In the test strategy, you can also consider writing integration tests , For example, simulate a dom operation , Trigger state changes and re rendering , Finally, verify whether the rendering results meet the expectations . This type of test is also a kind of black box test , Because state changes and... Were not exposed in the test re-render The logic of , Instead, the function is guaranteed by triggering the operation to verify the final result .
Of course, different projects still need to consider the particularity of the project , According to the focus and cost of different tests, consider what kind of test strategy to adopt .
How to write unit tests well
How to write unit tests can be learned from 2 Write from a different angle , The business perspective and the technical perspective do not conflict with each other , Just think differently :
Write unit tests from a business perspective
From a business perspective, you can use Given\When\Then To describe a unit test ,given What kind of premise is provided ( It is generally used to prepare test data ),when As something ( Generally, it is to call specific methods ),then What happened ( Usually test assertions ).
Look at a specific case : Define a unit test , The test has its own description and test content . The test content is divided into preparation products data (given)、 call getTotalAmount The function under test (when)、expect Assertion calculation result result (then).
// Realization
const getTotalAmount = (products) => {
return products.reduce((total, product) => total + product.price, 0);
}
Copy code
// test
it('should return total amount 600 when there are three products priced 100, 200, 300', () => {
// given - Prepare the data
const products = [
{ name: 'nike', price: 100 },
{ name: 'adidas', price: 200 },
{ name: 'lining', price: 300 },
]
// when - Call the function under test
const result = getTotalAmount(products)
// then - assertion results
expect(result).toBe(600)
})
Copy code
Write unit tests from a technical point of view
From a technical point of view, it can be divided into four test stages : Preparation stage (Setup) 、 Execution phase (Exercise) 、 Validation phase (Verify)、 Disassembly stage (Teardown).
Most test frameworks have many corresponding methods for the four phases , The following is a case : adopt beforeEach Get ready for the test , In a single test , Execute the specific method under test , adopt expect Assert validation test results , Pass after the test afterEach Empty data , Avoid affecting other tests , Need to be in Teardown The data cleared in the phase is generally shared by different tests .
// test
describe("getTotalAmount test", function () {
let products=[]
// Setup
beforeEach(function () {
products = [
{ name: 'nike', price: 100 },
{ name: 'adidas', price: 200 },
{ name: 'lining', price: 300 },
]
});
// Teardown
afterEach(function () {
products=[]
});
it("should return total amount 600 when there are three products priced 100, 200, 300", function () {
// Exercise
const result = getTotalAmount(products)
// Verify
expect(result).toBe(600)
});
});
Copy code
Test stand in
Test stand in (Test Doubles) In order to isolate some dependencies that affect the test , For example, third-party UI Components 、 Third party tools 、 Interface, etc. . After isolating dependencies , You can focus on the functions of the front end itself , Ensure its own code function . Test avatars are generally divided into the following uses :
Test Stub
Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.
Test Stub Provide an encapsulated response for each call , Generally, it will not respond to requests outside the test . Stub Often translated into “ pile ”, In the test , Frequently used Stub To completely replace the component under test ( System ) Dependent objects in , We set the output for it ( Return value ), It's like the component under test ( System ) A pile in , Only for testing , We will not verify the logic inside the pile, nor will we verify whether the pile is called . All you need to test is its impact , That is, the preset return value .
Be similar to jest.fn() It's just one. Stub, Sure mock Its return value , You can also return a by default undefined Methods .
const myObj = {
doSomething() {
console.log('does something');
}
};
test('stub .toHaveBeenCalled()', () => {
const stub = jest.fn();
stub();
expect(stub).toHaveBeenCalled();
});
test('Stub jest.fn() return value', () => {
let stub = jest.fn().mockReturnValue('default');
expect(stub()).toBe('default');
})
Copy code
Test Spy
Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.
As described in the figure below ,Test Spy It refers to the use of test avatars to capture the calls made by the tested system to other components , So that it can be verified by test in subsequent tests . It is similar to the later mentioned Mock The big difference “ Capture ”,Mock yes setUp When the time is right Object to Mock fall , and Spy It captures the call .
For example, in the following case , Added incrementSpy Test stand in , Captured counter Of increment Method call , When performing tests , Verify that the test avatar is indeed called 1 Time ( Of course not increment The specific implementation of ).
let count = 0;
const counter = {
increment() {
count += 1;
},
getCount() {
return count;
}
};
const app = counter => {
counter.increment();
};
test('app() with jest.spyOn(counter) .toHaveBeenCalledTimes(1)', () => {
const incrementSpy = jest.spyOn(counter, 'increment');
app(counter);
expect(incrementSpy).toHaveBeenCalledTimes(1);
});
Copy code
Mock Object
Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don't expect and are checked during verification to ensure they got all the calls they were expecting.
Use specific test objects (Mock Object) Replace the test dependent object , In the test, just verify whether it is called correctly . Here's the picture ,Mock object stay coding It is preset to receive the call , And it will check whether all the expected calls have been received during verification , If you receive an unexpected call , An exception will be thrown .
for example Jest One of them Mock Case study ,Mock One. counter object, And the mock Of counter object As an input parameter to isolate counter Impact on testing , Verify... In the test counter Of increment Whether it is called correctly , And don't care counter Of increment The concrete implementation of the method .
let count = 0;
const counter = {
increment() {
count += 1;
},
getCount() {
return count;
}
};
const app = counter => {
counter.increment();
};
test('app() with mock counter .toHaveBeenCalledTimes(1)', () => {
const mockCounter = {
increment: jest.fn()
};
app(mockCounter);
expect(mockCounter.increment).toHaveBeenCalledTimes(1);
});
Copy code
Fake Object
Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an InMemoryTestDatabase is a good example).
Fake Object It's simpler 、 A lighter implementation replaces the components that are dependent on in the test . Typical in backend testing Fake Object Is a memory database , Use it to simulate real database operations , But this Fake Object Not suitable for use in a production environment , Generally only used for testing . in summary ,Fake Object Sounds and Test Stub Their positioning is very similar , but Fake Object Is a lighter implementation that relies on components , It only provides interfaces like dependent components, which is convenient for the system under test ( Components ) To call , And as mentioned earlier Stub It is a real dependence , Different values will be returned according to different test scenario settings for testing .
In front-end testing , Often rely on other components or systems , For example, a reference to a third party UI Component library . However, in the test , We don't care about third parties UI The specific implementation of the library . These can be used Fake Object 了 .
For example, using react Frameworks often combine redux Use it together , When it comes to one connect 了 redux When testing components of , You can put redux Use redux-mock-store This lightweight test library replaces .
import configureStore from 'redux-mock-store';
const mockStore = configureStore([]);
describe('My Connected React-Redux Component', () => {
let store;
beforeEach(() => {
store = mockStore({
myState: 'sample text',
});
});
it('should render with given state from Redux store', () => {
});
it('should dispatch an action on button click', () => {
});
});
Copy code
Dummy Object
Dummy Object It refers to the false parameters passed in for testing , Pass in the method as a parameter Dummy Object Just to successfully call the method under test , No other role .
Such as the front util A parameter needs to be transmitted through the , This parameter is not really used , Just to pass through , So these are passed on but not really used Object Namely Dummy Object.
These test doubles should be used according to the specific situation in practice , Different schools have different use schemes . In the test , When there are component dependencies , Whether the test is state verification or behavior verification . In case of status verification , I don't care about the number of calls , In general use Stub and Fake Object; If it is behavior verification, it will generally use Spy or Mock To verify the result of the call .
Test avatar related documentation Links :
- Test Doubles:xunitpatterns.com/Test%20Doub…
- redux-mock-store:github.com/reduxjs/red…
summary
The types of front-end tests are roughly the ones mentioned above , The rate of unit testing is the highest , Because the cost of each unit test is smaller than other tests , And it can also test the performance of various scenarios more comprehensively case. The front end is medium pure JS I won't say much about function testing , Almost all testing tools support well , If it involves DOM Related component testing ,Test Library It's a good choice , The specific tools used for testing can be determined according to the project situation ( Combined with project technology selection and testing strategy ). Of course, the test framework is just a tool for writing tests , To write a test well, you still need to clarify the test responsibilities of each test case , Cover as many test scenarios as possible , Avoid error , It also avoids function failure caused by subsequent refactoring , Improve software quality .
Last
WeChat search official account Eval Studio, Watch more .
copyright notice
author[EvalStudio],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210827085844987z.html
The sidebar is recommended
- Crazy blessing! Tencent boss's "million JVM learning notes", real topic of Huawei Java interview 2020-2021
- JS JavaScript how to get the subscript of a value in the array
- How to implement injection in vuex source code?
- JQuery operation select (value, setting, selected)
- One line of code teaches you how to advertise on Tanabata Valentine's Day - Animation 3D photo album (music + text) HTML + CSS + JavaScript
- An article disassembles the pyramid architecture behind the gamefi outbreak
- BEM - a front-end CSS naming methodology
- [vue3] encapsulate custom global plug-ins
- Error using swiper plug-in in Vue
- Another ruthless character fell by 40000, which was "more beautiful" than Passat and maiteng, and didn't lose BMW
guess what you like
-
Huang Lei basks in Zhang Yixing's album, and the relationship between teachers and apprentices is no less than that in the past. Netizens envy Huang Lei
-
He was cheated by Wang Xiaofei and Li Chengxuan successively. Is an Yixuan a blessed daughter and not a blessed home?
-
Zhou Shen sang the theme song of the film "summer friends and sunny days" in mainland China. Netizen: endless aftertaste
-
Pink is Wangyuan online! Back to the peak! The new hairstyle is creamy and sassy
-
Front end interview daily 3 + 1 - day 858
-
Spring Webflux tutorial: how to build reactive web applications
-
[golang] walk into go language lesson 24 TCP high-level operation
-
August 23, 2021 Daily: less than three years after its establishment, Google dissolved the health department
-
The female doctor of Southeast University is no less beautiful than the female star. She has been married four times, and her personal experience has been controversial
-
There are many potential safety hazards in Chinese restaurant. The top of the program recording shed collapses, and the artist will fall down if he is careless
Random recommended
- Anti Mafia storm: He Yun's helpless son, Sun Xing, is destined to be caught by his dry son
- Introduction to flex flexible layout in CSS -- learning notes
- CSS learning notes - Flex layout (Ruan Yifeng tutorial summary)
- Today, let's talk about the arrow function of ES6
- Some thoughts on small program development
- Talk about mobile terminal adaptation
- Unwilling to cooperate with Wang Yibo again, Zhao Liying's fans went on a collective strike and made a public apology in less than a day
- JS function scope, closure, let, const
- Zheng Shuang's 30th birthday is deserted. Chen Jia has been sending blessings for ten years. Is it really just forgetting to make friends?
- Unveil the mystery of ascension
- Asynchronous solution async await
- Analysis and expansion of Vue infinite scroll source code
- Compression webpack plugin first screen loading optimization
- Specific usage of vue3 video play plug-in
- "The story of huiyeji" -- people are always greedy, and fairies should be spotless!
- Installing Vue devtool for chrome and Firefox
- Basic usage of JS object
- 1. JavaScript variable promotion mechanism
- Two easy-to-use animation JS that make the page move
- Front end Engineering - scaffold
- Java SQL Server intelligent fixed asset management, back end + front end + mobile end
- Mediator pattern of JavaScript Design Pattern
- Array de duplication problem solution - Nan recognition problem
- New choice for app development: building mobile applications using Vue native
- New gs8 Chengdu auto show announces interior Toyota technology blessing
- Vieira officially terminated his contract and left the team. The national security club sent blessings to him
- Less than 200000 to buy a Ford RV? 2.0T gasoline / diesel power, horizontal bed / longitudinal bed layout can be selected
- How does "heart 4" come to an end? Pinhole was boycotted by the brand, Ma Dong deleted the bad comments, and no one blessed him
- We are fearless in epidemic prevention and control -- pay tribute to the front-line workers of epidemic prevention!
- Front end, netty framework tutorial
- Xiaomi 11 | miui12.5 | android11 solves the problem that the httpcanary certificate cannot be installed
- The wireless charging of SAIC Roewe rx5 plus is so easy to use!
- Upload and preview pictures with JavaScript, and summarize the most complete mybatis core configuration file
- [25] typescript
- CSS transform Complete Guide (Second Edition) flight.archives 007
- Ajax foundation - HTTP foundation of interview essential knowledge
- Cloud lesson | explain in detail how Huawei cloud exclusive load balancing charges
- Decorator pattern of JavaScript Design Pattern
- [JS] 10. Closure application (loop processing)
- Left hand IRR, right hand NPV, master the password of getting rich