겁먹지 마...React의 스냅샷 테스트 및 시뮬레이션 양식 및 도구
스냅샷 테스트.
스냅숏 테스트는 듣기에 좀 비슷하다.만약 당신이 생성된 코드를 위해 사진을 한 장 찍었다면, 무슨 일이 생겨서 그 사진과 다르게 보였습니까?구성 요소의 고급 수준에서 스냅샷을 가져오기 때문에 일반적으로 캡슐화된 Div 스냅샷 테스트를 통해 요소 아래에 있는 모든 컨텐츠의 변경 사항을 모니터링할 수 있습니다.그러나 스냅샷 테스트는 시간이 얼어붙을 때보다 본질적으로 정적 구성 요소에 효과가 있지만 동적 가변 요소가 있는 구성 요소에는 소음일 뿐이다.물론 이들은 실제 TDD를 진행할 때 장애에 부딪힐 수 있다.어쨌든그것을 어떻게 실현하는지 봅시다.
스냅샷 테스트 수행
농담으로 이 일을 까다롭게 만들었다.먼저 렌더링에서 가져와야 합니다
container
.const {container} = render(<NewBook/>)
컨테이너는 모든 서브어셈블리를 포함하여 렌더링 어셈블리의 컨텐트입니다.그리고 우리는 스냅샷과 일치하기를 원하는 내용을 말하고 싶다.expect(container.firstChild).toMatchSnapshot();
이 방면의 첫 번째 아이는 첨부된div이다.Jest는 처음 이렇게 하면 멋진 일을 할 것입니다.
__snapshots__
폴더에 스냅샷을 만들어 줍니다.만약 당신이 그것을 보았다면, 그것은 기본적으로div의 출력을 폐쇄하는 것을 발견할 수 있을 것이다. 이것은 매우 멋있지만, 여기서 내가 말한 것은 자주 변화하는 일에 가장 적합하다. 만약 당신이 어떤 것을 추가하거나 조정하기로 결정했다면?예컨대, 하나의 추가라벨테스트 키트는 완료되면 스냅샷과 일치하지 않음을 나타냅니다.
expect(value).toMatchSnapshot() Received value does not match stored snapshot 1. - Snapshot
Snapshot Summary
1 snapshot test failed in 1 test suite. Inspect your code changes or pressu
to update them.`
만약 이것이 예상한 조정이라면, 말한 바와 같이, 가볍게
u
키만 누르면 바로 스냅샷을 업데이트할 수 있다.이것 또한 당신이 원하지 않는 것을 쉽게 받아들일 수 있기 때문에 조심해야 한다. 스냅숏은 일을 너무 쉽게 만들지 않아서 당신이 원하는 것을 스냅숏으로 만들어야 한다.그럼에도 불구하고 스냅샷 테스트는 여전히 매우 유용한 방법으로 변화가 발생할 때 신속하게 표시할 수 있고 동적성이 비교적 나쁜 구성 요소에 대해서는 반드시 스냅샷 테스트를 고려해야 한다.단원 테스트를 대체하기 위한 것이 아니라 스냅샷을 작성하는 것도 현실적이지 않기 때문에 TDD 원칙에 부합되지 않고 빠른 추가 테스트 층을 제공한다.자세한 내용은 JEST Documentation about Snapshots에서 확인할 수 있습니다.
비웃음 및 모니터링 양식 제출
자, 제가 첫 번째 테스트 댓글에서 언급한 조롱을 다시 한 번 봅시다.그러나 이번에는 더 복잡한 현실 세계의 예에 적용할 수 있다.즉, 테스트 폼 구성 요소의 예를 살펴보자.이것은 아날로그 함수의 흔한 용례이다. 왜냐하면 우리는 테스트할 때 데이터베이스에 데이터를 제출하고 싶지 않기 때문이다.우리 모두의 데이터베이스는 수동 테스트를 할 때의'test'와'aaaa'같은 항목으로 가득 차 있음을 확신합니다. 이 항목들을 어떻게 줄이는지 봅시다!
책 제목을 받아들여 제출하는 새로운 도서표를 사용하자. 그리 복잡하지는 않지만, 하나의 예로 들 수 있다.먼저 테스트를 구축해 보겠습니다.
import React from 'react'
import { render, cleanup, fireEvent} from 'react-testing-library'; //Added FireEvent from React Testing Library
import BookForm from './BookForm';
afterEach(cleanup)
test('<BookForm>', () => {
const {debug, getByText} = render(<BookForm/>)
expect(getByText('Submit').tagName).toBe('BUTTON') //Looks for an element with the text Submit, just for the sake of being different.
fireEvent.click(getByText('Submit'))
debug()
});
그러면 버튼을 사용하여 구성 요소를 구축하고 양식을 제출할 때 다음과 같은 무례한 기능을 사용합니다.import React, { Component } from 'react'
export default class BookForm extends Component {
render() {
return (
<div>
<form data-testid='book-form' onSubmit={ ()=> console.log("clicked the button!")}>
<button type="submit">Submit</button>
</form>
</div>
)
}
}
클릭 함수를 추가한 이유는 테스트를 실행할 때 로그에 clicked the button!
가 나타나는 것을 볼 수 있기 때문입니다.PASS src/BookForm.test.js
● Console
console.log src/BookForm.js:10
clicked the button!
이것은 신속하고 더러운 방식으로 작업을 테스트하는 데 도움이 될 것이다.그러나 만약에 폼 제출이 확실히 역할을 한다면 우리의 테스트는 위험해지기 시작할 것이다. 따라서 우리는 안전한 방식으로 폼을 제출해야 한다.이를 위해, 안전하게 모의할 수 있도록 구성 요소가 사용하는 모델을 고려해야 한다.이것은 도구를 통해submit에서 실행되는 기능을 제공하는 것과 관련이 있다.최종 구성 요소는 다음과 같습니다.export default class BookForm extends Component {
state = {
text: ''
}
render() {
const {submitForm} = this.props
const {text} = this.state
return (
<div>
<form data-testid='book-form' onSubmit={ ()=> submitForm({text})}>
<button type="submit">Submit</button>
</form>
</div>
)
}
}
알겠습니다. 여기서 큰 문제는 왜 우리가submitForm 함수를props로 바꿔야 합니까?프로그램의 정상적인 작업보다 이 함수를 실행하는 것을 테스트할 때, 이 함수의 기능을 변경해야 하기 때문이다.작성한 테스트를 살펴보면 다음과 같은 의미가 있습니다.import React from 'react'
import { render, cleanup, fireEvent} from 'react-testing-library';
import BookForm from './BookForm';
afterEach(cleanup)
const onSubmit = jest.fn(); //Our new Spy function
test('<BookForm>', () => {
const {debug, getByText, queryByTestId} = render(<BookForm submitForm={onSubmit} />) // The spy function is used to for the submit form
//Unit Tests to check elements exist
expect(queryByTestId('book-form')).toBeTruthy()
expect(queryByTestId('book-form').tagName).toBe("FORM")
expect(getByText('Submit').tagName).toBe('BUTTON')
//Check Form Submits
fireEvent.click(getByText('Submit'))
expect(onSubmit).toHaveBeenCalledTimes(1); //This tests makes sure we van submit the spy function
debug()
});
그래서 우리는 댓글을 되풀이하기 위해 다음과 같이 말했다.expect(onSubmit).toHaveBeenCalledTimes(1)
와 함께 운행하는지 테스트했다.그랬으면 좋겠어요.이점: 모니터링 콘솔 오류
우리는 우리가 좋아하는 모든 것을 거의 감시할 수 있다.심지어 구성 요소의 호출이 정확하지 않을 때도 오류가 발생할 수 있습니다.예를 들어, 우리는 하나의 구성 요소가 특정 유형을 정의한 도구를 필요로 하는데, 우리는 우리가 도구를 제공하지 않을 때 무슨 일이 일어날지 테스트하고 싶을 수도 있다.따라서 다음과 같이 mocking 함수를 사용하여 콘솔 오류를 처리할 수 있습니다.
console.error = jest.fn()
test('<ExampleComponent'>, () => {
render(<ExampleComponent />)
expect(console.error).toBeCalled()
});
물론 컨트롤러 오류는 제거되었지만, 전송된 도구가 부족해서 발생할 수 있는 모든 오류가 표시됩니다.네, 저희가 예약한 블로그로 돌아가겠습니다.
테스트의 입력 값 지정
우리의 테스트를 현실 생활에 더욱 부합시키기 위해서, 우리는 표를 작성하여 특정한 입력으로 제출할 수 있는지 확인해야 할 수도 있다.우리의 예시에서, 우리는 우리의 도서 표에 제목 텍스트가 입력되기를 바란다.이 가능하다, ~할 수 있다,...
test('<BookForm>', () => {
const {getByLabelText} = render(<BookForm submitForm={onSubmit} />) //Adding the getByLabelText
//1. Unit Test to check our input element exists
expect(getByLabelText('Title').tagName).toBe('INPUT') //test to make sure the input is there
//2. change the Input Value using the change event.
fireEvent.change(getByLabelText('Title'), {target: {value: "Girl, Woman, Other"}}) //This event sets the value of the input and lets the change affect the state.
//3. Check Form Submits as expected
fireEvent.click(getByText('Submit'))
expect(onSubmit).toHaveBeenCalledWith({title: 'Girl, Woman, Other'}) //This checks that the submission has the title we asked it to have earlier.
새 검색어 getBy LabelText를 사용했습니다. 이것은 우리가 찾으려는 요소를 찾기 위해 탭의 텍스트를 이상하게 보지 않습니다.두 번째 단계에서는 FireEvent를 사용합니다.우리의 목표는 원소를 입력하는 것이기 때문에, 우리는 우리의 가치를 찾아내고 변경할 수 있도록 깊이 파고들어야 한다.마지막으로, 우리는 우리의 스파이 기능이 어떤 Tohaven Called With 방법을 사용했는지 검사할 수 있으며, 이것은 쉽게 이해할 수 있는 방법이기를 바란다.따라서 이 테스트를 통과한 React 코드가 어떤 모습인지 살펴보는 것이 좋습니다.
import React, { Component } from 'react'
export default class BookForm extends Component {
state = {
title: '' //what gets sent on submit
}
render() {
const {submitForm} = this.props
const {title} = this.state
return (
<div>
<form data-testid='book-form' onSubmit={ ()=> submitForm({title})}>
<label htmlFor="title">Title</label> //Remember that it is the text of the element our test is looking for not the HTMLFor
<input id="title" type="text" onChange={(e) => this.setState({title: e.target.value})}></input> //Quick and Dirty input controlling
<button type="submit">Submit</button>
</form>
</div>
)
}
}
멋있다. 지금은 세계에서 가장 복잡한 형식이 아니지만, 이러한 기술이 어떻게 그에 상응하여 확대되는지, 그리고 우리가 동적 내용을 테스트하는 간단한 정도를 이해할 수 있기를 바란다.만약 당신이 일찍 스냅샷 테스트를 설정했다면, 코드를 쓸 때, 그것들은 좀 짜증날 수도 있다는 것을 지금 발견할 수 있을 것이다.장점: 부정적인 단언
테스트에서 다음과 같은 결론을 얻었습니다.
expect(onSubmit).toHaveBeenCalledWith({title: 'Girl, Woman, Other'})
만약 그것이 실제로 발생한다면 이 단언이 정확한지 확인하는 것이다.어떤 경우 패스는 무슨 일이 일어났는지 확인하는 것을 의미한다.농담으로 말하자면 이것은 방법에
not
를 추가하는 것처럼 간단하다. 아래와 같다.expect(onSubmit).not.toHaveBeenCalledWith({title: 'Girl, Woman, Other'})
예를 들어 테스트 도구가 데이터를 필요로 하는 구성 요소에 데이터를 제공하지 않았을 때 어떤 상황이 발생할지 여부가 유용할 수 있습니다.이것은 매우 편리하다. 왜냐하면 우리의 다음 주제는...
조소도구
그래서 우리는 폼 데이터를 시뮬레이션할 수 있지만, 우리가React에서 일반적으로 처리하는 또 다른 일은 도구이다.만약 우리의 조립품이 도구를 필요로 한다면, 우리는 도구를 제공하는 방식이 필요하다.기본적인 측면에서 상기 모든 것이 의미가 있다면 이것은 매우 간단하다.테스트를 수행하려면 다음이 필요합니다.
console.error = jest.fn()
const book = {
title: "The Stand"
}
test('<Book> without Book props', () => { //No props so
render(<Book />)
expect(console.error).toHaveBeenCalled();
})
test('<Book> with Book Props', () => {
render(<Book book={book}/>)
expect(console.error).not.toHaveBeenCalled();
})
멋있죠?네, 하지만 지금 여러 가지 테스트를 진행하고 있습니다. 주의할 점이 있습니다.위의 예에서, 우리는 컨트롤러를 검사할 수 있는 두 곳이 있다.오류가 호출되었습니다.한 번은 도구가 없고, 두 번째는 도구가 없으니, 우리는 그것이 운행되지 않기를 바란다.그러나, 만약 당신이 이것을 실행한다면, 그것은 컨트롤러라고 말할 수 있기 때문에 실패할 것이다.오류가 두 번째 실행 중...뭘 줬어?!간단하게 말하면, 컨트롤러.error는 첫 번째 테스트를 실행할 때 호출됩니다. 따라서 두 번째 테스트를 실행할 때 호출된다고 생각합니다.이 문제를 해결하는 것은 상당히 간단하기 때문에 정리 기능을 조정해야 한다.
afterEach( () => {
cleanup
console.error.mockClear()
})
이제 콘솔의 잘못된 기억이 테스트 사이에서 지워져서 일이 더욱 정상적으로 되었다.불행하게도, 당신이 실제 세계의 구성 요소를 테스트하기 시작할 때, 당신은 많은 작은 문제에 부딪힐 것이다.흔히 볼 수 있는 예는 기본적으로 테스트에서 발견되지 않은 것들이다. 이 블로그 글의 범위를 넘어서 모든 용례를 포함하지만, 그것을 만났을 때 need some research 이다.
테스트와 코드를 작성할 때 순서에 따라 점진적인 방법을 취하는 것은 확실히 범위를 좁히는 데 도움이 되고 이런 문제의 해결 방안을 찾는 데 도움이 된다.
마무리
이것은 사람을 화나게 하는 블로그 글이다. 나는 어떤 것들을 건드렸지만 다른 것은 소홀히 했다.테스트 도구, 폼, 입력이 React의 대다수 사용자에게 유용하기를 바랍니다.나의 목표는 네가 통상적으로 테스트하는 내용의 60%를 기초로 하고 다른 40%를 검색하는 데 약간의 배경을 제공하는 것이다
다음에는 API 테스트와 비동기적인 재미를 살펴볼 수 있습니다!
Reference
이 문제에 관하여(겁먹지 마...React의 스냅샷 테스트 및 시뮬레이션 양식 및 도구), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/neosaurrrus/don-t-be-afraid-of-snapshot-testing-and-mocking-forms-and-props-in-react-4i3k텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)