Medium
7μ£Όμ°¨ κ³Όμ 체ν¬ν¬μΈνΈ
κΈ°λ³Έκ³Όμ
Medium
- μ΄ 11κ°μ νμΌ, 115κ°μ λ¨μ ν μ€νΈλ₯Ό 무μ¬ν μμ±νκ³ ν΅κ³Όμν¨λ€.
μ§λ¬Έ
Q. medium.useEventOperations.spec.tsx > μλ toastFnκ³Ό mockκ³Ό μ΄ fnμ 무μμ ν΄μ€κΉμ?
notistack λΌμ΄λΈλ¬λ¦¬μ useSnackbar ν
μ λͺ¨νΉνμ¬ ν
μ€νΈ νκ²½μμ μ€λ΅λ° νΈμΆ μ¬λΆμ λ©μμ§λ₯Ό κ²μ¦ν μ μκ² ν΄μ€λλ€. ν
μ€νΈ νκ²½μμλ μ€μ UI μ€λ΅λ°λ₯Ό λμ°μ§ λͺ»νκΈ° λλ¬Έμ enqueueSnackbarFnμ΄ νΈμΆλμλμ§, μ΄λ€ λ©μμ§κ° μ λ¬λμλμ§ νμΈνλ λ°©λ²μ μ¬μ©ν©λλ€.
const enqueueSnackbarFn = vi.fn();
vi.mock('notistack', async () => {
const actual = await vi.importActual('notistack');
return {
...actual,
useSnackbar: () => ({ enqueueSnackbar: enqueueSnackbarFn }),
};
});
Q. medium.integration.spec.tsx > μ¬κΈ°μ ChakraProviderλ‘ λ¬Άμ΄μ£Όλ λμμ μλ―ΈμμκΉμ? μλ€λ©΄ μ΄λ€ μλ―ΈμΌκΉμ?
ν
μ€νΈ νκ²½μμ μ€μ μ΄μ νκ²½κ³Ό λμΌν Context μ 곡μλ€μ μ€μ νμ¬ μ»΄ν¬λνΈκ° μ μμ μΌλ‘ λμν μ μκ² λ§λλλ€. SnackbarProviderλ notistackμμ useSnackbar ν
μ μ¬μ©ν μ μκ² λ§λλ 컨ν
μ€νΈ νλ‘λ°μ΄λμ΄κ³ , ThemeProviderλ MUI μ»΄ν¬λνΈλ€μ΄ themeλ₯Ό λ°μμ μ¬λ°λ₯΄κ² λ λλ μ μκ² λ§λλ νλ‘λ°μ΄λμ
λλ€.
import CssBaseline from '@mui/material/CssBaseline';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import { render } from '@testing-library/react';
import { SnackbarProvider } from 'notistack';
import type { ReactElement } from 'react';
import { App } from '../App';
//...
const setup = (element: ReactElement) => {
const theme = createTheme();
const user = userEvent.setup();
return {
...render(
<ThemeProvider theme={theme}>
<CssBaseline />
<SnackbarProvider>{element}</SnackbarProvider>
</ThemeProvider>
),
user,
};
};
Q. handlersUtils > μλ μ¬λ¬κ°μ§ use ν¨μλ μ΄λ€ μν μ ν κΉμ? μ΄λ»κ² μ¬μ©λ μ μμκΉμ?
MSWμ server.use()λ₯Ό ν΅ν΄ νΉμ ν
μ€νΈμμλ§ μ¬μ©ν μμ νΈλ€λ¬λ₯Ό λ±λ‘ν©λλ€. κ° ν
μ€νΈλ§λ€ λ
립μ μΈ νκ²½μ λ§λ€μ΄ λ³λ ¬ μ€ν μμλ μμ μ μΈ ν
μ€νΈλ₯Ό κ°λ₯νκ² νλ©°, νΉμ μλν¬μΈνΈμ λν΄ μ±κ³΅ νΉμ μ€ν¨, κ·Έλ¦¬κ³ λ¦¬ν΄κ°κΉμ§ μ ν΄μ 보λ΄μ€ μ μμ΅λλ€.
import { http, HttpResponse } from 'msw';
import { server } from '../setupTests';
import type { Event } from '../types';
export const setupMockHandlerCreation = (initEvents = [] as Event[]) => {
const mockEvents: Event[] = [...initEvents];
server.use(
http.get('/api/events', () => {
return HttpResponse.json({ events: mockEvents });
}),
http.post('/api/events', async ({ request }) => {
const newEvent = (await request.json()) as Event;
newEvent.id = String(mockEvents.length + 1); // κ°λ¨ν ID μμ±
mockEvents.push(newEvent);
return HttpResponse.json(newEvent, { status: 201 });
})
);
};
Q. setupTests.ts > μ μ΄ μκ°μ μ€μ ν΄μ£Όλ κ±ΈκΉμ?
beforeEach(() => {
expect.hasAssertions(); // ? Med: μ΄κ±Έ μ μ¨μΌνλμ§ λ¬Όμ΄λ³΄μ
vi.setSystemTime(new Date('2025-10-01')); // ? Med: μ΄κ±Έ μ μ¨μΌνλμ§ λ¬Όμ΄λ³΄μ
resetEvents();
});
λͺ¨λ ν μ€νΈκ° λμΌν κΈ°μ€ λ μ§(2025-10-01)λ₯Ό μ¬μ©νλλ‘ λ³΄μ₯νμ¬ μκ° μμ‘΄μ μΈ λ‘μ§μ μμ μ μΌλ‘ ν μ€νΈν μ μκ² ν©λλ€. νμμ‘΄μ μ°¨μ΄λ μ€μ μ€νμμ μ΄ λ¬λΌμ λ°μνλ ν μ€νΈμΌμ΄μ€λ₯Ό μ κ±°νκΈ° μν μ€μ μ λλ€.
κ΄λ ¨ λ΄μ© μ 리본
- https://github.com/chan9yu/front_6th_chapter3-1/issues/1
- https://github.com/chan9yu/front_6th_chapter3-1/issues/2
μ¬ν κ³Όμ
- App μ»΄ν¬λνΈ μ μ ν λ¨μμ μ»΄ν¬λνΈ, ν , μ νΈ ν¨μλ‘ λΆλ¦¬νλκ°?
- ν΄λΉ λͺ¨λλ€μ λν μ μ ν ν μ€νΈλ₯Ό 5κ° μ΄μ μμ±νλκ°?
κ³Όμ μ ννκ³
μ΄λ² κ³Όμ λ₯Ό ν΅ν΄ ν μ€νΈ μ½λ μμ±μ μ 체μ μΈ νλ¦μ κ²½νν μ μμμ΅λλ€. κ·Έλμ ν μ€νΈ μ½λλ₯Ό μ€μ λ‘ μ¨λ³Έ μ μ΄ μμ΄μ Medium λμ΄λλ₯Ό μ ννλλ°, κ²°κ³Όμ μΌλ‘ λͺ©νμλ λͺ¨λ ν μ€νΈ μΌμ΄μ€λ₯Ό μμ±νκ² λμμ΅λλ€. ν μ€νΈ μμ±λΏλ§ μλλΌ μ»΄ν¬λνΈ λΆλ¦¬ μμ κΉμ§ ν¨κ» νλ©΄μ μ¬λ―Έμλ κ³Όμ κ° λμλκ±° κ°μμ
κΈ°μ μ μ±μ₯
μ΄λ² κ³Όμ λ₯Ό ν΅ν΄ React Testing Libraryμ ν΅μ¬ κ°λ
μΈ getBy, queryBy, findByμ μ°¨μ΄μ κ³Ό νμ©λ²μ λ°°μΈ μ μμμ΅λλ€. MSWλ₯Ό ν΅ν API λͺ¨νΉκ³Ό λ€νΈμν¬ μμ² κ°λ‘μ±κΈ° νλ λ°©λ²λ μ¨λ³Ό μ μμκ³ , μ»΄ν¬λνΈ λ¨μ ν
μ€νΈμ ν΅ν© ν
μ€νΈμ μ°¨μ΄μ μ μ€μ λ‘ κ΅¬ννλ©΄μ μ΄λμ λ κ°μ μ‘μ μ μμμ΅λλ€.
ꡬννλ©΄μ μ΄λ €μ λ 건 MUI μ»΄ν¬λνΈ ν μ€νΈν λ μ¬λ°λ₯Έ selectorλ₯Ό κ³ λ₯΄λ κ²μ΄μλλ°, aria-labelκ³Ό role μμ±μ μ νμ©ν΄μ μ κ·Όμ±μ κ³ λ €ν ν μ€νΈ μμ±λ²μ μ¬μ©ν΄λ΄€μ΅λλ€.
μ½λ νμ§
μ½λ νμ§μ λμ΄κΈ° μν΄μ ν μ€νΈλ₯Ό λ¨Όμ μ§κ³ κ·Έ λ€μμ μ»΄ν¬λνΈλ₯Ό μͺΌκ°λ λ°©μμΌλ‘ μ§ννμ΅λλ€. ν μ€νΈκ° κΉ¨μ§μ§ μλ μ μμ μ‘°κΈμ© μ»΄ν¬λνΈλ₯Ό λΆλ¦¬ν΄λκ°μ΅λλ€.
λ¬Όλ‘ μμ§ λΆμ‘±ν λΆλΆλ λ§μλ°μ.. μ»΄ν¬λνΈλ₯Ό λλλ€ λ³΄λ propsλ₯Ό μ¬λ¬ λ¨κ³λ‘ λ΄λ €μ£Όλ μΌμ΄ λ§μμ‘κ³ , ν μ€νΈ μΌμ΄μ€ μ€μλ λΉμ·ν λ‘μ§μ΄ μ€λ³΅λλ κ²λ€λ μμ΄μ μ λ¦¬κ° νμν κ±° κ°μ΅λλ€.
νμ΅ ν¨κ³Ό λΆμ
μ΄λ² κ³Όμ μμ κ°μ₯ ν¬κ² μ»μ΄κ°κ±΄ ν μ€νΈ μ½λ μμ±μ μ 체μ μΈ νλ¦μ μ΄ν΄ν κ²μ λλ€. κ·Έλ₯ κΈ°λ₯μ΄ μ λμκ°λμ§λ§ 보λ κ²μμ λ²μ΄λμ, μ€μ λ‘ μ¬μ©μκ° μ°λ κ΄μ μμ μ»΄ν¬λνΈκ° μ λλ‘ λμνλμ§ νμΈνλ λ°©λ²μ λ°°μ κ³ μμΌλ‘ κ°λ°ν λ κΈ°νκ° λλ€λ©΄ ν μ€νΈ μ½λλ₯Ό ν΅ν΄ μ½λ νμ§λ λμΌ μ μμ κ² κ°μ΅λλ€
μμ§ λ 곡λΆν΄μΌ ν λΆλΆλ€λ λ§μ κ±° κ°μ΅λλ€ λ³΅μ‘ν μν κ΄λ¦¬κ° μλ μ»΄ν¬λνΈλ₯Ό μ΄λ»κ² ν μ€νΈν μ§, E2E ν μ€νΈμ λ¨μ ν μ€νΈλ₯Ό μ΄λ€ λΉμ¨λ‘ μ¨μΌ ν μ§, ν μ€νΈ 컀λ²λ¦¬μ§μ μ€μ νμ§ μ¬μ΄μ μ μ ν μ μ μ΄λ»κ² μ°Ύμμ§ κ°μ κ²λ€.... μμ μ€μ λ‘ ν μ€νΈ μ½λλ₯Ό λ§μ΄ μ§λ΄μΌ μ κ±° κ°μμ
κ³Όμ νΌλλ°±
κ³Όμ μμ μ’μλ λΆλΆμ ν μ€νΈ μ²μ νλ μ¬λμ μν΄ μ¬λ¬ λμ΄λκ° μλ€λ μ μ λλ€. μ λ Medium λμ΄λλ₯Ό ν΅ν΄ μ λ ν μ€νΈλΆν° μμν΄μ ν΅ν© ν μ€νΈκΉμ§ μμ°μ€λ½κ² λ°°μΈ μ μμκ³ , μ€μ μ¬μ©μκ° μ°λ μλ리μ€λ‘ λ§λ ν΅ν© ν μ€νΈκ° μ¬λ―Έμμμ΅λλ€. μ΄λ° μμΌλ‘ λ¨κ³λ³λ‘ μ κ·ΌνλκΉ ν μ€νΈμ μ 체μ μΈ νλ¦μ μ΄ν΄ν μ μμλκ±° κ°μμ
리뷰 λ°κ³ μΆμ λ΄μ©
ν μ€νΈ μΌμ΄μ€μ λ²μμ λν κ³ λ―Όμ΄ μμ΅λλ€ "μ»΄ν¬λνΈκ° λ λλ§λλκ°" κ°μ κΈ°λ³Έμ μΈ ν μ€νΈλΆν° 볡μ‘ν μ¬μ©μ μλ리μ€κΉμ§ λ€μνκ² μμ±νλλ°, μ΄λ μ λ μ μμ ν μ€νΈλ₯Ό μμ±νλ κ² μ μ νμ§ κΆκΈν©λλ€. νΉν λ¨μν λ λλ§ ν μ€νΈκ° μ€μ λ‘ μλ―Έκ° μλ 건μ§, μλλ©΄ μ’ λ λΉμ¦λμ€ λ‘μ§μ μ§μ€ν΄μΌ νλ κ±΄μ§ μμ§ κ°μ μλͺ»μ‘μμ΅λλ€...
ν μ€νΈ μ½λμ μ€λ³΅μ λν΄ κΆκΈν μ λ μμ΅λλ€! λΉμ·ν λ‘μ§μ ν μ€νΈνλ μΌμ΄μ€λ€μ΄ μλλ°, μ΄λ° κ²½μ° ν μ€νΈλ₯Ό ν©μΉλ κ² μ’μμ§ μλλ©΄ κ°κ°μ μΌμ΄μ€λ₯Ό λͺ ννκ² κ΅¬λΆν΄μ μ μ§νλ κ² μ’μμ§ μ‘°μΈμ λ°μλ³΄κ³ μΆμ΅λλ€!
κ³Όμ νΌλλ°±
μλ νμΈμ μ°¬κ·λ! 7μ£Όμ°¨ κ³Όμ μ μ§νν΄μ£Όμ ¨λ€μ γ γ κ³ μνμ ¨μ΅λλ€!!
ν μ€νΈ μΌμ΄μ€μ λ²μμ λν κ³ λ―Όμ΄ μμ΅λλ€ "μ»΄ν¬λνΈκ° λ λλ§λλκ°" κ°μ κΈ°λ³Έμ μΈ ν μ€νΈλΆν° 볡μ‘ν μ¬μ©μ μλ리μ€κΉμ§ λ€μνκ² μμ±νλλ°, μ΄λ μ λ μ μμ ν μ€νΈλ₯Ό μμ±νλ κ² μ μ νμ§ κΆκΈν©λλ€. νΉν λ¨μν λ λλ§ ν μ€νΈκ° μ€μ λ‘ μλ―Έκ° μλ 건μ§, μλλ©΄ μ’ λ λΉμ¦λμ€ λ‘μ§μ μ§μ€ν΄μΌ νλ κ±΄μ§ μμ§ κ°μ μλͺ»μ‘μμ΅λλ€...
https://discord.com/channels/1288769861589270590/1369931229696229386/1408221063317295295
μ€ν μ½μΉλκ»μ λ¨κ²¨μ£ΌμκΈ΄ νλλ°, μ λ λμ²΄λ‘ μ»΄ν¬λνΈμ λν λ λλ§ ν μ€νΈλ 무μλ―Ένλ€κ³ μκ°ν΄μ γ γ μ»΄ν¬λνΈλ "λ°μ΄ν°λ₯Ό νννλ μλ¨"μ΄κ³ , κ·Έλ λ€λ©΄ λ°μ΄ν°μ outputμ λν κ²μ¦μ ν μ μλ€λ©΄ μ»΄ν¬λνΈλ μμ°μ€λ½κ² κ²μ¦λλκ² λ§λ€κ³ μκ°ν©λλ€. λ€λ§ μΈν°λμ μ μ»΄ν¬λνΈκ° μ°κ²°ν΄μ£ΌκΈ° λλ¬Έμ μΈν°λμ μ°κ²°μ΄ μμ°μ€λ¬μ΄μ§μ λν΄μλ μ»΄ν¬λνΈ λ μ΄μ΄μμ ν μ€νΈν΄λ³Ό μ μκ² μ£ !? λ€λ§ μ΄κ² vitest μ²λΌ nodejs νκ²½μμ κ²μ¦νλκ² λμ²΄λ‘ μ΄λ €μ΄μ. κ·Έλμ μ»΄ν¬λνΈ λ μ΄μ΄μ λν ν μ€νΈκ° νμνλ€λ©΄ μμ e2e ν μ€νΈλ₯Ό ν΄λ³΄λ©΄ μ΄λ¨κΉ!? λΌλ μκ°μ λλ€.
κ²°λ‘ μ, λΉμ¦λμ€ λ‘μ§μ μ‘°κΈ λ μ΄μ μ λ§μΆ°μ ν μ€νΈ ν΄μ£Όμλ©΄ μ’κ² λ€λ μκ°μ λλ€!
ν μ€νΈ μ½λμ μ€λ³΅μ λν΄ κΆκΈν μ λ μμ΅λλ€! λΉμ·ν λ‘μ§μ ν μ€νΈνλ μΌμ΄μ€λ€μ΄ μλλ°, μ΄λ° κ²½μ° ν μ€νΈλ₯Ό ν©μΉλ κ² μ’μμ§ μλλ©΄ κ°κ°μ μΌμ΄μ€λ₯Ό λͺ ννκ² κ΅¬λΆν΄μ μ μ§νλ κ² μ’μμ§ μ‘°μΈμ λ°μλ³΄κ³ μΆμ΅λλ€!
κ²μ¦νλ μ½λλ₯Ό μμ ν¨μλ‘ λΆλ¦¬ν΄μ£Όμλ©΄ μ’λ΅λλ€ γ γ
μ΄λ° λλμ΄μ£ .
test('μΌμ μΆκ° ν
μ€νΈ', () => {
νΌμ
λ ₯_κ²μ¦();
νΌμ μ₯_κ²μ¦();
λͺ©λ‘νμΈ_κ²μ¦();
})