Preface: Why do we need to automate tests?
The tested components are sound, the testable component architecture is sound, and if a component is difficult to write test cases, it proves that the component design is bad. While writing component use cases, you can help component developers find problems and tweak the code to make the architecture sound.
- Testing ensures the expected results
- As a description of the behavior of existing code
- Encourage developers to write testable code, and generally testable code is more readable
- If a dependent component is modified, the affected component can detect errors in the test
Why is React particularly good for component testing?
1.React is componentized
2.Functional Component: Pure functions are best written tests with fixed inputs and fixed outputs
3. One-way data flow: Components do not modify incoming data
Test type
- Unit testing: testing software in units of the original. The definition of a “unit” is up to you. If you’re using functional programming, a unit most likely refers to a function. Your unit test will call this function with different arguments and assert that it returns the expected result; In object-oriented languages, all the way down to a method and all the way up to a class can be a unit (from a single method to an entire class can be a unit). That is, a unit can be a function, a module or a component. The basic characteristic is that as long as the input is unchanged, it must return the same output. The easier a piece of software is to unit test, the better its modular structure, and the weaker the coupling between modules. React’s componentization and functional programming make it a natural fit for unit testing.
- Function test: it is equivalent to black box test, the tester does not understand the internal situation of the program, do not need to have programming language expertise, only know the input, output and function of the program, from the user’s point of view for the software interface, function and external structure of the test, not considering the internal logic
- Integration test: on the basis of unit test, assemble all modules into subsystems or systems according to design requirements for testing
- Smoke test: The test of the main functions to confirm whether the main functions meet the requirements and the normal operation of the software before formal comprehensive testing
Break down
For our unit tests, we can either write cases for a function, or we can write cases for a string of function calls. Pyramid model
Before the pyramid, there was the ice cream model. It includes a lot of manual testing, end-to-end automated testing, and a small amount of unit testing. As a result, as the product grows, manual regression testing takes longer and longer, making quality difficult to control; Automated cases fail frequently, with each failure corresponding to a long function call. What went wrong? Unit tests are few and far between.
Mike Cohn in his book “Succeeding With Agile” changed his words. This metaphor is very graphic, and it lets you know at a glance that testing needs to be layered. It also tells you how many tests you need to write for each layer. Testing the pyramid itself is a good rule of thumb, and it’s best to remember two things Cohn mentioned in the pyramid model:
- Write tests of varying granularity
- The higher the level, the fewer tests you should write
At the same time, our understanding of the pyramid must not stop there, to understand further: I understand the pyramid model as — ice cream melted. That is, the “manual testing” at the top should theoretically be all automated, melted down, and first melted into unit tests. Those that cannot be covered by unit tests are placed in the middle layer (layered testing), and those that cannot be covered by unit tests are placed in the UI layer. Therefore, the UI layer case, can not have, run slowly and unstable. According to Steve, I don’t know whether unit testing or layered testing is called automated testing, so we should treat all automated cases as a whole. Cases should not be redundant, and if unit testing can cover them, we should remove the case from the layered or UI. The lower level tests are less relevant, while the higher level tests are more extensive. Unit tests, for example, focus on a single unit and nothing else. So, once a unit is written, the test can be passed; The integration test can only be tested by assembling several units together. The precondition for the test to pass is that all these units have been written, and the cycle is obviously longer than that of the unit test. System test is to connect the whole system of each module together, all kinds of data are ready, it is possible to pass. In addition, because there are too many modules involved, any adjustment of a module may destroy the high-level test, so the high-level test is usually relatively fragile. In actual work, some high-level tests will involve external systems, so that the complexity is constantly increasing.
Why single test
- Unit testing is very important to the quality of our products.
- Unit testing is at the bottom of the test of all kind of test, is the first link, also is one of the most important link, is the only time a guarantee can test code coverage reached 100%, is the basis and premise of the whole process of software testing, unit testing, to prevent the development of the late too many bugs and out of control, unit testing is the best cost performance.
- According to statistics, about 80% of errors are introduced during the software design phase, and the cost of fixing a software error increases as the software life progresses. The later an error is discovered, the more expensive it becomes to fix, and it increases exponentially. As coders, who are the primary enforcers of unit tests, they are the only ones who can produce a bug free program that no one else can
- Code specification, optimization, testable code
- Rest assured refactoring
- Automate three-thousand times
Technical selection of Jest – general testing framework
The characteristics,
Jest is Facebook’s open source front-end testing framework for React and React Native unit testing, which has been integrated into create-React-app. Jest features:
- Ease of use: Based on Jasmine, assertion library, support for multiple test styles
- Adaptability: Jest is modular, extensible, and configurable
- Sandbox and Snapshot: Jest comes with a built-in JSDOM that emulates the browser environment and executes in parallel
- Snapshot test: Jest serializes the React component tree and generates snapshots of strings to provide high-performance UI detection by comparing strings
- Mock system: Jest implements a powerful Mock system that supports both automatic and manual mocks
- Support for asynchronous code testing: Support for Promise and async/await
- Automatically generate static analysis results: built-in Istanbul, test code coverage, and generate corresponding reports
2. Assertion library
1. Determine whether a value corresponds to the corresponding result
2, jestjs. IO/docs/en/usi…
3. Other assertion libraries: Chai, etc
3. Examples
Fourth, Jest Api
globals API
- Describe (name, FN) : Describe a block that describes a group of functionally related test cases
- It (name, fn, timeout) : alias test, used to hold test cases
- AfterAll (fn, timeout) : method to execute afterAll test cases have run
- BeforeAll (fn, timeout) : method executed beforeAll test cases are executed
- AfterEach (fn) : method to execute afterEach test case has been executed
- BeforeEach (fn) : method that needs to be executed beforeEach test case is executed
Both global and describe can have the above four periodic functions. The describe after function has a higher priority than the global after function, and the describe before function has a lower priority than the global before function
beforeAll(() => { console.log('global before all'); }); afterAll(() => { console.log('global after all'); }); beforeEach(() =>{ console.log('global before each'); }); afterEach(() => { console.log('global after each'); }); describe('test1', () => { beforeAll(() => { console.log('test1 before all'); }); afterAll(() => { console.log('test1 after all'); }); beforeEach(() => { console.log('test1 before each'); }); afterEach(() => { console.log('test1 after each'); }); it('test sum', () => { expect(sum(2, 3)).toEqual(5); }); it('test mutil', () => { expect(sum(2, 3)).toEqual(7); }); }); Copy the codeCopy the code
Common assertion
-
Expect (value) : When testing a value for assertion, expect wraps the value
-
ToBe (value) : Uses object. is for comparison. For floating-point comparisons, use toBeCloseTo
-
Not: Used to take the inverse
-
ToEqual (value) : Used for deep comparison of objects
-
ToMatch (regexpOrString) : Used to check whether strings, either regular expressions or strings, match
-
ToContain (item) : check whether an item contains an array or a string
-
ToBeNull (value) : matches only null
-
ToBeUndefined (value) : matches only undefined
-
ToBeDefined (value) : The opposite of toBeUndefined
-
ToBeTruthy (Value) : Matches any value that makes the if statement true
-
ToBeFalsy (value) : Matches any value that makes the if statement false
-
ToBeGreaterThan: (number) is greater than
-
ToBeGreaterThanOrEqual (number) : greater than or equal to
-
ToBeLessThan (number) : less than
-
ToBeLessThanOrEqual (number) : less than or equal to
-
ToBeInstanceOf (class) : Determines whether it is an instance of class
-
Anything (value) : Matches all values except null and undefined
-
Convergency: Used to take out the promise for the fulfilled package value, support chain call
-
Rejects: This method is used to retrieve the value of a rejected promise, supporting a chain call
-
ToHaveBeenCalled () : determines whether the mock function has been called
-
ToHaveBeenCalledTimes (number) : Used to determine the number of times a mock function is invoked
-
Assertions (number) : Verifies that number of assertions are called in a test case
-
Extend (matchers) : Customize some assertions
Enzyme – General test framework for technology selection
React test tool 1. ReactTestUtils test tool 2.Airbnb test tool based on the official package – Enzyme
Enzyme is Airbnb’s open source React test tool library, which functions the secondary encapsulation of the official test tool library ReactTestUtils, provides a set of concise and powerful APIS, and has built-in Cheerio.
DOM processing is implemented in jquery-style way, and the development experience is very friendly. It has gained popularity in the open source community and was officially featured by React.
1. Enzyme advantage
1. Simple and easy to understand
2. Similar to Jquery chain writing
Two, two test methods
1.Shallow Rendering
2.DOM Rendering
Three, installation,
yarn add enzyme --save-dev
yarn add enzyme-adapter-react-16 --save-dev
4. Examples
Five, the Enzyme API
Three rendering methods
- Shallow: Shallow rendering, encapsulation of the official shallow Renderer. Rendering a component as a virtual DOM object renders only the first layer and the child components are not rendered, making it very efficient. You don’t need a DOM environment, and you can access component information using jQuery
- Render the React component into a static HTML string, then use the Cheerio library to parse the string and return an instance of Cheerio that can be used to analyze the HTML structure of the component
- Mount: Full render, which loads a component render into a real DOM node to test DOM API interaction and component lifecycle. Jsdom was used to simulate the browser environment
Shallow and mount can be used to simulate interactions because they return DOM objects, whereas the Render method cannot. The shallow method will suffice, using Render if you need to judge a child component, or mount if you need to test the life cycle of the component.
Commonly used method
- Simulate (event, mock) : A mock event is used to trigger an event. Event is the event name and mock is an event object
- Instance () : Returns an instance of the component
- Find (selector) : Finds nodes according to their selectors. A selector can be a CSS selector, a component’s constructor, a component’s display name, etc
- At (index) : Returns a rendered object
- Get (index) : Returns a React node. To test it, re-render it
- Contains (nodeOrNodes) : Indicates whether the current object contains nodes that are the main parameters. The parameter type is react object or object array
- Text () : Returns the text content of the current component
- HTML () : Returns the HTML code form of the current component
- Props () : Returns all properties of the root component
- Prop (key) : Returns the specified property of the root component
- State () : Returns the state of the root component
- SetState (nextState) : Sets the state of the root component
- SetProps (nextProps) : Sets the properties of the root component