이 반응 테스트 방법은 컨텍스트에 의존하여 실제 시나리오를 모방합니다.
이 게시물에서는 테스트 라이브러리를 사용하여 컨텍스트에 의존하는 React 구성 요소를 테스트하기위한 사고 과정을 살펴 보겠습니다. 저의 목표는 이러한 구성 요소를 테스트하고 모의 사용의 장단점을 검사하는 것과 컨텍스트를 조롱하지 않고 테스트를 검토하는 것입니다. 우리는 각 접근 방식이 테스트의 신뢰성에 어떤 영향을 미치는지 살펴보고, 실제 응용 프로그램에서 한 방법이 다른 방법보다 더 유리한시기와 이유에 대한 통찰력을 공유하겠습니다.
당신이 알아야 할 것
- Reactjs가 사용되는 것 (아마도 이미 일부 앱을 작성했을 것입니다)
- Vitest는 무엇입니까
반응 컨텍스트 란 무엇입니까?
Reactjs 컨텍스트는 Reactjs 구성 요소의 구조에서 일반적인 문제에 대한 해결책으로 나타났습니다 : Prop Drilling. 소품 드릴링은 동일한 데이터 세트에 액세스 해야하는 구성 요소 체인이있을 때 발생합니다. 컨텍스트 메커니즘을 통해 컨텍스트 자체가 첫 번째 자손 인 한 구성 요소가 동일한 데이터 세트를 공유 할 수 있습니다.
Reactjs 문서에서, 다른 구성 요소는이 정보가 필요할 수 있으므로 테마를 보유하는 컨텍스트가 사용됩니다. 문서는 컨텍스트를 사용하여 소품을 통해 값을 전달하는 대신이를 처리합니다. 또 다른 예는 응용 프로그램의 레이아웃을 보유하는 컨텍스트 사용입니다.
이 예제의 앱
테마 앱을 따르는 예제는 사용됩니다. 사용자가 명암/어두운 테마를 전환 할 수있는 응용 프로그램입니다. 이 앱은 Reactjs 공식 문서에도 사용됩니다. 이 응용 프로그램은 라이트 테마 모드와 다크 테마 모드 사이를 전환하는 간단한 토글로 구성됩니다. 응용 프로그램은 얻는 것만 큼 간단하며 단일 파일로 모든 것을 그릴 수 있습니다.
import { createContext, useContext, useState } from 'react'
const ThemeContext = createContext('light')
function Page() {
const theme = useContext(ThemeContext)
return (
)
}
function App() {
const [theme, setTheme] = useState('light')
return (
)
}
export default App
이 응용 프로그램에는 두 가지 주요 구성 요소가 있습니다. App
그리고 Page
. 그만큼 App
구성 요소는 기본 구성 요소 역할을하며 현재 테마의 상태를 포함하며, 이는 “밝은”또는 “어두운”일 수 있습니다. 또한 밝은 모드와 어두운 모드 사이의 테마를 전환하는 버튼도 포함되어 있습니다. 그만큼 Page
구성 요소는 자녀입니다 App
테마 컨텍스트를 소비하여 현재 테마를 표시합니다. 버튼 App
구성 요소는 클릭하면 테마를 전환하고 그에 따라 컨텍스트 값을 업데이트하는 간단한 토글 버튼입니다.
테스트를위한 점화
일반적으로 모든 응용 프로그램에서 우리는 어떤 종류의 테스트를하고 싶은지, 그리고 어떤 종류의 테스트를 수행하고 싶은지에 초점을 맞춰야합니다. 예를 들어, 전체 응용 프로그램 대신 단일 구성 요소를 타겟팅 할 수 있습니다. 이 예에서는 페이지 구성 요소로 시작합니다. 테스트 더블을 사용하여 테스트해야합니다.
테스트-더블은 앱 구조 자체에서 컨텍스트에 따라 달라 지므로 컨텍스트의 값도 변경해야합니다.
테스트 바우스
Reactjs의 컨텍스트로 테스트 접근 방식을 시작하려면 첫 번째 테스트를 시작합니다.
import { render, screen } from '@testing-library/react'
import { Page } from './Page'
describe(' ', () => {
it('should render light as default theme', () => {
render( )
expect(screen.getByText('current theme: light')).toBeInTheDocument()
})
})
라이트 테마가 themecontext에서 기본 테마로 설정된 경우이 테스트는 예상대로 전달됩니다. 우리는이 첫 번째 예제를 추진할 수도 있지만 어두운 테마에 관심이있을 때 두 번째 테스트에서 흥미로워집니다. 어두운 테마에 들어가려면 Reactjs 컨텍스트에 의존하여 테스트 더블 사용을 시작해야합니다. 두 번째 테스트는 vi.mock
믹스뿐만 아니라 vi.mocked
. 작성된 두 번째 테스트는 첫 번째 테스트도 변경해야했습니다.
import { render, screen } from '@testing-library/react'
import { Page } from './Page'
import { useContext } from 'react'
vi.mock('react', () => {
return {
...vi.importActual('react'),
useContext: vi.fn(),
createContext: vi.fn()
}
})
describe(' ', () => {
it('should render light as default theme', () => {
vi.mocked(useContext).mockReturnValue('light')
render( )
expect(screen.getByText('current theme: light')).toBeInTheDocument()
})
it('should render dark theme', () => {
vi.mocked(useContext).mockReturnValue('dark')
render( )
expect(screen.getByText('current theme: dark')).toBeInTheDocument()
})
})
두 테스트 케이스 모두 이제 가짜를 사용하여 응용 프로그램을 테스트합니다. 컨텍스트에서 반환 데이터를 변경하면 테스트도 변경됩니다. 여기서주의 사항은 다음과 같습니다.
- 우리는“당신이 소유하지 않는 것을 조롱하지 말아라”를 허스트하는 반응 컨텍스트를 조롱하고 있습니다.
- 우리는 조롱을 사용해야하기 때문에 시험은 더욱 장점이됩니다.
- 우리가 작성한 두 가지 테스트는 응용 프로그램과의 사용자 상호 작용을 반영하지 않습니다. 토글 버튼이 누르면 테마가 변경 될 것임을 알고 있습니다.
테스트 더블없이
다음 접근법은 응용 프로그램에 포함 된 컨텍스트를 분리하거나 테스트 더블을 사용하지 않고 사용하는 것입니다. TDD 로이 접근 방식을 취하면 사용자의 행동 방식을 시뮬레이션하는 매우 간단한 테스트로 시작할 수 있습니다.
import { render, screen } from '@testing-library/react'
import App from './App'
import userEvent from '@testing-library/user-event'
describe(' ', () => {
it('should render toggle button', () => {
render( )
expect(screen.getByText('Toggle')).toBeInTheDocument()
})
})
그런 다음 두 번째 테스트를 따르면 기본적으로 라이트 테마를 설정하려고합니다.
import { render, screen } from '@testing-library/react'
import App from './App'
import userEvent from '@testing-library/user-event'
describe(' ', () => {
it('should render toggle button', () => {
render( )
expect(screen.getByText('Toggle')).toBeInTheDocument()
})
it('should render light as default theme', () => {
render( )
expect(screen.getByText('current theme: light')).toBeInTheDocument()
})
})
그리고 마지막으로 테마 전환 :
import { render, screen } from '@testing-library/react'
import App from './App'
import userEvent from '@testing-library/user-event'
describe(' ', () => {
it('should render toggle button', () => {
render( )
expect(screen.getByText('Toggle')).toBeInTheDocument()
})
it('should render light as default theme', () => {
render( )
expect(screen.getByText('current theme: light')).toBeInTheDocument()
})
it('should render dark theme on toggle', async () => {
const user = userEvent.setup()
render( )
await user.click(screen.getByText('Toggle'))
expect(screen.getByText('current theme: dark')).toBeInTheDocument()
})
})
이 전략에 대한주의 사항 :
- 테스트 더블이 필요하지 않으며 코드가 적은 테스트를합니다.
- 테스트의 동작은 실제 응용 프로그램에서 사용자가 수행 할 작업과 일치합니다.
각 접근법의 장단점
이 섹션에서는 다른 속성과 관련하여 각 접근 방식의 장단점을 살펴볼 것입니다.
소품에 대한 리팩토링
컨텍스트에 테스트 더블을 사용하면 이런 종류의 변화에 대한 테스트가 깨지기 쉽습니다. 소품으로 UseContext의 사용을 리팩토링하면 동작이 그렇지 않은 경우에도 자동으로 테스트가 실패합니다. Test-Doubles를 사용하지 않는 옵션을 사용하면 그러한 의미에서 리팩토링이 지원됩니다. “대규모 소프트웨어 프로젝트의 리팩토링”이라는 책에서 저자 Stefan Rock과 Martin Lippert는 내가 여기에서 언급 한 것과 유사한 시나리오를 묘사했습니다. 그들이 논의한 문제 중 하나는 리팩토링 및 수업 구조 변경과 관련이 있으며 C3 프로젝트를 인용합니다.
About every 3 or 4 iterations we do a refactoring that causes us to toss or otherwise radically
modify a group of classes. The tests will either go away or be changed to reflect the classes’ new
behavior. We are constantly splitting classes up and moving behavior around. This may or may not affect the UnitTests
이 상황을 극복하기 위해 이상적으로 단위 테스트는 “안정적인 API”를 기반으로 작성되며 테스트중인 대상 시스템은 손대지 않지만 때로는 API 변경도 필요합니다. 이를 위해 저자가 제안한 솔루션은 자동 수락 테스트를 암시하는 것입니다.
사용자 정의 컨텍스트 생성
Reactjs의 컨텍스트 제공 업체에 직접 의존하는 대신 사용자 정의 컨텍스트를 사용하는 것도 마찬가지입니다. 테스트-가우블없이 옵션을 사용하면 리팩토링이 가능합니다.
결론
이 안내서에서는 테스트 더블이 필요하지 않고 상황에 의존하는 구성 요소를 테스트하는 방법을 살펴보고 테스트를보다 간단하고 실제 사용자 상호 작용과 대조적 인 각 접근법의 장단점에 더 가깝게 만듭니다. 가능할 때마다, 사용자 상호 작용을 반영하는 Simples 접근법을 사용하는 것을 따라야합니다. 그러나 테스트 더블이 필요한 경우 테스트 코드의 유지 관리 가능성을 목표로 사용해야합니다. 간단한 테스트를 통해 생산 코드의 리팩토링을 확신 할 수 있습니다.
자원
다음 단계
- 여러 컨텍스트 또는 중첩 제공 업체와 관련된보다 복잡한 시나리오를 테스트하십시오.
- 이 가이드에서는 조롱을 피했지만 조롱이 필요한 경우가 있습니다. 이러한 시나리오의 고급 조롱 기술을 탐색하십시오.
Post Comment