169 похожих чатов

Кто как организовывает тесты? Есть компонент A, который, среди прочих, используется

в компоненте B, который так же используется в компоненте C.
Компонент А покрыт модульными тестами.

Получается так, что при тестировании компонента B на полную работоспособность, приходится либо повторять некоторые тесты из тестов компонента А, либо мокать А и проверять только переданные в него пропсы. Такая же ситуация возникает с компонентом C, который должен повторять тесты для компонента А и B, либо мокать B.

Оба подхода кажутся неправильными, т.к. при применении первого, прохождение теста зависит от правильности работы других компонентов, а при применении второго приходится учитывать внутреннюю реализацию, и такие тесты перестают быть актуальными при малейшем рефакторинге

19 ответов

13 просмотров

Ну по мне тут есть несколько вариантов. 1) Ты протестировал компонент A, далее ты тестируешь компонент B, подменяя компонент A на какую нибудь заглушку. (Для этого в enzyme например есть shallow render) И тогда получается если упал тест в B, ты знаешь что виноват именно компонент B, а не какой то другой. 2) Второй подход не мокать компоненты и тестировать как есть (по сути интеграционные тесты получаются). Kent Dodds говорил в одной статье про shallow render: "Какая разница что твой юнит тест с замоканным компонентом проходит если модуль в целом не работает". И получается ты тестируешь сразу работоспособность целого модуля ничего не мокая, делая по большей части интеграционные тесты. В твоем случае при применении первого подхода когда ты проверяешь полную работоспособность, логично что твой тест упадет если модуль который он использует сломанный (Интеграционный тест получается), значит твоя система не работает в целом. Во втором случае ты мокаешь компонент и у тебя получается чистый юнит тест без каких то зависимостей. Ты проверил работоспособность конкретно модуля B. И если он у тебя ломается при небольшом рефакторинге когда общее поведение сохраняется, то это немного странно.

Sergey-Grishchenko Автор вопроса

Изменение АПИ компонента А может сломать тесты компонента B, если тесты проверяют работоспособность B при моке А, который имитирует его правильную работу. Например, у А есть коллбэк. У B есть коллбэк, который с какими-то изменениями пробрасывается в А. Есть тест, который проверяет правильно ли вызывается коллбэк, переданный в B, когда А вызывает коллбэк. Получается, изменив имя коллбэка в А, упадёт данный тест для B. Это логично с одной стороны, т.к. это спасает от ситуации, когда интерфейс поменяли, а в каком-то компоненте использование поменять забыли. Но получается очень шаткая "конструкция". По поводу интеграционных тестов согласен. Реализуем их для каждой фичи, но shared компоненты такими тестами не протестировать. И при падении интеграционного теста потом не так уж и легко найти причину его падения

Sergey-Grishchenko Автор вопроса

По поводу Enzyme думал тоже, но у него с shallow render'ом и эффектами есть проблема

Если мы пишем unit тест компонента B, то он не должен проверять как там что то вызывается в A. Он предполагает что компонент A изначально рабочий, для этого мы его и мокаем.

Это уже интеграционный тест. Ты проверяешь работу двух модулей. И логично если сломается один, то другой тоже упадет

Sergey-Grishchenko Автор вопроса

it( 'should call onAClick with current input value on A click', () => { let onClick; mockedA.mockImplementation(props => (onClick = props.onClick)) const onAClick = jest.fn() const defaultValue = {a: 1} render(<B onAClick={onAClick} defaultValue={defaultValue} />) onClick() expect(onAClick).toBeCalledWith(defaultValue) } )

Если честно, немного сложно понять что тут происходит

Sergey-Grishchenko Автор вопроса

Компонент А замокан, мы получаем переданный в его пропсы коллбэк и вызываем его сами, чтобы проверить правильно ли отработает логика в компоненте B, которая должна произойти по этому коллбэку. В данном случае, B должен вызвать коллбэк onAClick с текущим значением внутреннего инпута. Но так же это мог бы быть какой-нибудь сайд эффект

Ну это вроде unit тест. У тебя компонент A тут указан замоканный. И если ты изменишь реальный компонент A, то этот тест не должен упасть. Но сама система уже может не работать.

Sergey-Grishchenko Автор вопроса

Вообще да. Если изменится АПИ А, то придётся поменять компонент B для работоспособности. И, следовательно, поменять юнит тест для этого, поменяв название пропа, который мы забираем из А

Если изменится A, то упадет тест только для компонента A. Тест для компонента B останется рабочим

И ещё есть вопрос если можно конечно почему когда я querySelectorAll("button") делаю и хочу что бы при клике изменились все кнопки оно ошибку дают но только при querySelector(button) работает но только первую попавшийся задет тот свет

Sergey-Grishchenko Автор вопроса

Да, но B будет нерабочим. Чтобы починить B, придётся поменять название коллбэка, который передаётся в A ...<A onClick={handleAClick} -> <A newOnClick={handleAClick} , а это уже в свою очередь приведёт к падению теста

querySelectorAll возвращает тебе массив

Да nodeList а как можно с этим работать что бы получилось использовать map и усвоить знание ?

Коллекцию

Да, пардон

Тебе нужно получить массив из коллекции и его ты можешь мапить

Для каждого из них так положено делать x[0].style.backgroundColor = "red";

Похожие вопросы

Обсуждают сегодня

а через ESC-код ?
Alexey Kulakov
29
30500 за редактор? )
Владимир
47
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
13
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
в JclConsole объявлено так: function CtrlHandler(CtrlType: DWORD): BOOL; stdcall; - где ваше объявление с stdcall? у вас на картинке нет stdcall
Karagy
8
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
Ребят в СИ можно реализовать ООП?
Николай
33
program test; {$mode delphi} procedure proc(v: int32); overload; begin end; procedure proc(v: int64); overload; begin end; var x: uint64; begin proc(x); end. Уж не знаю...
notme
6
у вас два процесса. один посылает другому сигнал. у вас есть код обоих процессов? если всё не так - расскажите как оно на самом деле. а именно кто кому чего, есть-ли консоли,...
Karagy
6
Карта сайта