На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (16) « Первая ... 12 13 [14] 15 16  все  ( Перейти к последнему сообщению )  
> Rust vs C++ , очередная шляпа
    Цитата D_KEY @
    Пусть это будет метод, возвращающий некое описание класса, например.

    Что значит «некое описание класса»? Если оно «некое», динамическое, для каждого наследника A разное, то нельзя в тесте для A этого не учитывать и хардкодить expected как просто "A", т.к. тест testA не пройдёт для наследников A, как у тебя не пройдёт даже до рефакторинга для B, а должен, потому что B — субтип A и должен следовать LSP и спецификации супертипа (A) соответственно.

    Добавлено
    Цитата D_KEY @
    Я тебе привел пример, когда такой код не будет нарушением контракта.

    Где? Я пропустил, видимо. Понапишут своих портянок, а потом коды не замечают =)

    Цитата D_KEY @
    У разных классов будут разные значения.

    Дерьмовые классы, нарушающие LSP. Или дерьмовая спецификация (а значит и тесты), не учитывающие эту динамику.

    Цитата D_KEY @
    И, повторяю еще раз. Тесты не имеют отношения к моему примеру. Их можно вообще убрать.

    Если их убрать, то в чём пример? Приведи пример кода без тестов.

    Цитата D_KEY @
    А пример о том, что изменение сигнатуры метода в базовом классе может пройти незаметно без override, а это может являться ошибкой.

    А может и не являться. И может пройти заметно без override, если IDE не тупая как пробка и видит методы с той же сигнатурой. Я ж уже писал, что Java'вские IDE и так прекрасно показывают, что метод пререопределяет родительский, без аннотации @Override. Точно также IDE это видит и при рефакторинге, если тебе хочется, чтобы она это учитывала. Так зачем явно писать override?
    Сообщение отредактировано: korvin -
      D_KEY, вот смотри до рефакторинга, после рефакторинга и после фикса спецификации. Если бы спецификация изначально была бы корректная, то не пришлось бы её фиксить. В твоём же рабочем процессе (автоматический апдейт дочерних сигнатур или просто ошибки на неуместный оверрайд) девелопер просто будет молча убирать оверрайд / подгонять тело метода под новую сигнатуру (или просто игнорировать новый параметр), совершенно не задумываясь, поменялась ли спецификация родительского класса или нет. В общем, просто уборка мусора под ковёр.
        Цитата D_KEY @
        В первом случае идет речь о тесте самого класса. Я, наверное, никогда не видел, чтобы в тесте класса перед вызовами унаследованных функций объект явно кастили к базовому(а только это спасло бы помимо override в моем примере).

        Ну и? Сам функционал же ты будешь тестировать? Ты же у себя в программе написал не просто A a; a.foo, а через фабрику эти сущности создаешь. А в тестах у тебя этого нет. Я тебе на это и указал в самом начале.

        Цитата D_KEY @
        Ну я уже написал, например, проверять, что дернул нужные методы нужное число раз с соответствующими аргументами.

        Где проверять? И зачем проверять сколько раз ты что там дернул? Я не совсем понял.

        Цитата D_KEY @
        А зачем использовать существующие классы? У них свои тесты есть. Это же модульное тестирование. Кроме того, реализаций обычно несколько, какую выбрать? Моки обычно позволяют сделать дополнительные проверки.

        Как зачем? А как проверять работу? Моки чтоли тестировать? Так это просто заглушки, для имитации того, что ты не можешь получить в ЮТ. Если у тебя несколько реализаций - обычно все нужно тестировать. В идеале. Чтоб у тебя всевозможные сценарии отрабатывали. На практике правда, это не всегда достижимо.
          Цитата Wound @
          Как зачем? А как проверять работу? Моки чтоли тестировать? Так это просто заглушки, для имитации того, что ты не можешь получить в ЮТ.

          В ЮТ ты проверяешь работу своего модуля, а не всего подряд.

          Цитата
          Если у тебя несколько реализаций - обычно все нужно тестировать

          Так оно и будет протестировано. Для каждой реализации будет свой ЮТ.
          Зачем тестить все реализации в тесте линкера? Он же работает через интерфейсы. В его ЮТ нужно тестить его работу.

          Добавлено
          Цитата Wound @
          Где проверять? И зачем проверять сколько раз ты что там дернул? Я не совсем понял.

          Ну допустим твой линкер должен дёрнуть такой-то метод одного интерфейса и такой-то другого. Ты создаешь мок-реализации интерфейсов и проверяешь, что эти вызовы были сделаны нужное число раз и с заданными параметрами.

          Добавлено
          Чуть позже могу показать на gmock'е
          Сообщение отредактировано: D_KEY -
            Цитата D_KEY @
            В ЮТ ты проверяешь работу своего модуля, а не всего подряд.

            Конечно. Я так понял классы эти - А и B ты написал, и на этом работа с ними закончена? Ты их будешь как то использовать? Скорее будешь. Вот и напишешь соответствующие ЮТ на их использование. Это уже будет тестирование другого модуля, которые в идеале и должен выявить ошибку в твоем рефакторинге.

            Цитата D_KEY @
            Так оно и будет протестировано. Для каждой реализации будет свой ЮТ.
            Зачем тестить все реализации в тесте линкера? Он же работает через интерфейсы. В его ЮТ нужно тестить его работу.

            Ну потому что у тебя есть разные сущности. Например ты протестировал связь CUser с OrgUnit, а связь OrgUnit с OrgUnit не будет выполнятся, потому как для нее нужно сделать больше телодвижений. Ок, возьми не Link, может там эта не совсем очевидно. Возьми например перемещение.
            Можно перемещать как User, так и OrgUnit в другой OrgUnit, но разница в работе будет очевидна. Когда ты перемещаешь User - тебе нужно просто взять его и переместить, а когда перемещаешь OrgUnit то нужно сделать больше проверок и работы. Например нужно убедится что у тебя OrgUnit не перемещается в тот же самый, нужно как то разорвать связь в дереве OrgUnitov где был старый и обновить новое.
            Как ты будешь это тестировать? Передашь OrgUnit и CUser - работает, и флаг ему в руки, работу перемещения я протестировал?
              Цитата korvin @
              Дерьмовые классы, нарушающие LSP. Или дерьмовая спецификация (а значит и тесты), не учитывающие эту динамику.

              Ты предлагаешь не тестить конкретные реализации? Ещё раз, вот иерархия ошибок. Метод string message(). Он должен возвращать у всех классов в иерархии одно и то же? :crazy:
              Почему это нарушение контакта? Или ты предлагаешь не тестить конкретные реализации? Почему?
                Цитата D_KEY @
                Ну допустим твой линкер должен дёрнуть такой-то метод одного интерфейса и такой-то другого. Ты создаешь мок-реализации интерфейсов и проверяешь, что эти вызовы были сделаны нужное число раз и с заданными параметрами.

                А тестирую я что? Что у меня будет в Expected и Actual ? Количество вызовов? Тогда я не совсем понимаю, что я тестирую.
                  Цитата Wound @
                  Цитата D_KEY @
                  Ну допустим твой линкер должен дёрнуть такой-то метод одного интерфейса и такой-то другого. Ты создаешь мок-реализации интерфейсов и проверяешь, что эти вызовы были сделаны нужное число раз и с заданными параметрами.

                  А тестирую я что? Что у меня будет в Expected и Actual ? Количество вызовов? Тогда я не совсем понимаю, что я тестирую.

                  Работу линкера, это же его ЮТ.

                  Добавлено
                  Цитата Wound @
                  Ты их будешь как то использовать? Скорее будешь. Вот и напишешь соответствующие ЮТ на их использование.

                  Их будут использовать через интерфейсы. И те, кто их использует, ничего о них не знает, потому в тестах нет никакого смысла использовать эти конкретные реализации. У них есть свои ЮТ, которые проверяют корректность их работы.

                  Добавлено
                  Wound, видел я такие ЮТ, какие ты хочешь, которые пол системы поднимают для тестов одного модуля :crazy:

                  Добавлено
                  Или я тебя не понял.

                  Давай другой пример рассмотрим.

                  Добавлено
                  Цитата korvin @
                  Если их убрать, то в чём пример? Приведи пример кода без тестов.

                  Так просто убери их и все. Пример был просто про то, что без override у тебя компиляция молча пройдет, поскольку в наследнике просто появится новый метод с точки зрения языка. С override же ты явно пишешь, что вот этот метод должен был быть перекрыт, соответственно у компилятора появляется возможность указать тебе, что ничего ты не перекрываешь и тут, вероятно, ошибка. Еще на стадии компиляции, не доходя до тестов и рантайма.

                  Добавлено
                  Цитата korvin @
                  D_KEY, вот смотри

                  Да, можно написать тесты, которые это отловят, но не факт, что именно такие тесты были написаны. И не факт, что ты можешь написать такой обобщенный тест в случае конкретного метода (в данном случае ты смог вычислить нужное значение в тесте, а если бы там не было привязки к типу?)
                  Т.е. может быть ситуация, когда контракт базового класса или интерфейса не накладывает строгих ограничений на значение, но это не мешает написать тест на этот метод для каждой конкретной реализации, если ты знаешь, как он должен формироваться. И даже если ты не станешь это тестить, то от проблемы никак не уйдешь.
                  Кроме того, с override ты это отловишь на этапе компиляции. Мне казалось, что ты всегда за это. Кроме того, ты смешиваешь в одну кучу язык, тесты, IDE и процессы :)
                  Написать override там, где ты хотел перекрыть метод - очень просто. Как и отследить это при ревью кода.
                  Сообщение отредактировано: D_KEY -
                    Цитата korvin @
                    Я ж уже писал, что Java'вские IDE и так прекрасно показывают, что метод пререопределяет родительский, без аннотации @Override. Точно также IDE это видит и при рефакторинге, если тебе хочется, чтобы она это учитывала. Так зачем явно писать override?

                    То, что видит IDE - это фактическое состояние дел, а писать @Override явно - это декларация твоих намерений. Слегка разные назначения, как мне кажется.
                      Цитата D_KEY @
                      Работу линкера, это же его ЮТ.

                      Та ка нахрен мне тестировать его в отрыве от сущностей, которыми он манипулирует? Ты ж собрался мок наследовать от IContainer/IPrincipal и писать там свой функционал паралельно. Ну напишешь ты - у тебя с моком будет работать, а в каком нибудь CUser/COrgUnit не будет работать, потому что из класса выше, кто то по ошибке убрал твой override. И все, приплыли? Да и тебе не кажется, что писать паралельно какие то моки на все подряд - это излишняя, бесполезная работа?
                      Я все равно не понимаю зачем так делать :-? Никогда такого не видел, ни в С++, ни в C#, ни где то еще.

                      Цитата D_KEY @
                      Их будут использовать через интерфейсы. И те, кто их использует, ничего о них не знает, потому в тестах нет никакого смысла использовать эти конкретные реализации. У них есть свои ЮТ, которые проверяют корректность их работы.

                      Так ты же выше написал что в ЮТ тоже будешь юзать интерфейсы, тогда какие проблемы? Я если честно вот вообще не понимаю, что ты мне рассказываешь.

                      У тебя получается что я тестирую исключительно то, что написано в методе, не учитывая совершенно поведение системы в целом. Т.е. у меня ожидаются два каких то класса на входе, с двумя каким то методами, которые нужно вызвать, я беру мочу эти два класса у тебя в ЮТ, делая их методы пустыми, ну или возвращающими константы, и потом эти классы передаю в функцию тестирования функционала. У меня оно как то отрабатывает, но в итоге, что я протестил то? :D Что 2 + 2 = 4 ? Не, ну круто, че. А потом в проде, у тебя хренак, и поплыли баги со всех щелей, потому что у тебя тесты и близко не имитируют то, как работает программа.

                      Цитата D_KEY @
                      Wound, видел я такие ЮТ, какие ты хочешь, которые пол системы поднимают для тестов одного модуля

                      В смысле пол системы? Поднимаетя ровно то, что нужно для тестирования функционала. Что то тяжелое, громоздкое, не нужное, и нужное например только как константы - мочится.
                      В целом все тесты у тебя тестируют разные части твоей системы, проходя в идеале все сценарии, на которые расчитана программа, с приближенными на сколько это возможно к реальности данными.

                      Используя моки ты как раз отдаляешься от реальности, но в конкретном случае, этой реальностью можно пренебречь, поэтому ты и будешь юзать вот тут мок.
                        Цитата Wound @
                        Ну напишешь ты - у тебя с моком будет работать, а в каком нибудь CUser/COrgUnit не будет работать

                        Почему не будет-то? У них есть свои тесты, они проверяют. Ты похоже не понимаешь, что такое ЮТ.

                        Цитата
                        что писать паралельно какие то моки на все подряд - это излишняя, бесполезная работа?

                        Не понимаю, о чем ты.
                        Вот есть у тебя класс. Он использует какие-то объекты через интерфейсы.
                        Зачем в его тесте использовать какие-то конкретные объекты, а не моки? Тем более, что их вообще может не быть у тебя(например, клиент предоставляет) или они на другом уровне системы.

                        Цитата
                        Я если честно вот вообще не понимаю, что ты мне рассказываешь.

                        Взаимно.

                        Цитата
                        У тебя получается что я тестирую исключительно то, что написано в методе, не учитывая совершенно поведение системы в целом

                        ЮТ и не должны(да и не могут) учитывать поведение всей системы, для этого есть другие тесты.

                        Цитата
                        Т.е. у меня ожидаются два каких то класса на входе, с двумя каким то методами, которые нужно вызвать, я беру мочу эти два класса у тебя в ЮТ, делая их методы пустыми, ну или возвращающими константы, и потом эти классы передаю в функцию тестирования функционала

                        Моки могут быть довольно сложными.

                        Цитата
                        У меня оно как то отрабатывает, но в итоге, что я протестил то?

                        Этот модуль.

                        Цитата
                        А потом в проде, у тебя хренак, и поплыли баги со всех щелей, потому что у тебя тесты и близко не имитируют то, как работает программа.

                        ЮТ и не должны этим заниматься. Они проверяют работу конкретных модулей. Потому они так и называются, внезапно.

                        Давай какой-то пример рассмотрим? Я покажу на нем.
                          Цитата D_KEY @

                          Давай какой-то пример рассмотрим? Я покажу на нем.

                          - У вас есть книги по садомазохизму?
                          - Да.
                          - Бросьте мне одну в лицо!
                          :facepalm:
                            Цитата D_KEY @
                            Почему не будет-то? У них есть свои тесты, они проверяют. Ты похоже не понимаешь, что такое ЮТ.

                            Кого они проверяют? Я тебе говорю, что для какой то операции, необходимо вызвать какой то метод из этих классов явно/неявно.

                            Цитата D_KEY @
                            Вот есть у тебя класс. Он использует какие-то объекты через интерфейсы.
                            Зачем в его тесте использовать какие-то конкретные объекты, а не моки? Тем более, что их вообще может не быть у тебя(например, клиент предоставляет) или они на другом уровне системы.

                            Смотря какие объекты в нем используются. Почему бы не использовать конкретные объекты, вместо моков? Ты на все зависимые сущности моки пишешь?

                            Цитата D_KEY @
                            ЮТ и не должны(да и не могут) учитывать поведение всей системы, для этого есть другие тесты.

                            Не всей системы, а только той части, которая тестируется.

                            Цитата D_KEY @
                            Моки могут быть довольно сложными.

                            Могут, и чего? Я тебе пишу про то, что ты можешь в моке не учесть, какую то вещь, которая есть в используемом классе.

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

                            Цитата D_KEY @
                            Этот модуль.

                            А функционал работы/взаимодействия, не?

                            Цитата D_KEY @
                            ЮТ и не должны этим заниматься. Они проверяют работу конкретных модулей. Потому они так и называются, внезапно.

                            Так все верно. У тебя есть три модуля, первый это Пользовател, второй Контейнер, трейти Линковщик. И буду у тебя три модульных теста. Первый у тебя протестирует пользователя, второй Контейнер, а третий Линковку пользователя и контейнера. В итоге ты протестировал функционал своей системы. Я лично понимаю это так.
                              Цитата Wound @
                              Я тебе говорю, что для какой то операции, необходимо вызвать какой то метод из этих классов явно/неявно.

                              В линковщике? Ну ты же их через интерфейс используешь? Вот и замокай его в тесте линковщика. В чем проблема?

                              Цитата
                              Почему бы не использовать конкретные объекты, вместо моков?

                              Потому, что тест линковщика, который использует интерфейсы, а не конкретные объекты, не должен иметь зависимость от конкретных реализаций интерфейсов. Ему это не нужно.

                              Цитата
                              Ты на все зависимые сущности моки пишешь?

                              Если работа идет через интерфейсы, то да. Не могу вспомнить контрпример.

                              Цитата
                              Не всей системы, а только той части, которая тестируется.

                              Так тестируется только конкретный модуль. И ничего больше. Мы же о ЮТ говорим.

                              Цитата
                              Я тебе пишу про то, что ты можешь в моке не учесть, какую то вещь, которая есть в используемом классе.

                              Так у тебя этих конкретных классов может быть 100500. У них свои тесты есть. Понимаешь?

                              Цитата
                              На практике же, довольно часто приходится работать с довольно связанными сущностями.

                              Это хреновая декомпозиция системы. Я тебя не зря спросил про IoC. Хотя лучше про dependency inversion principle сказать.

                              Цитата
                              Так все верно. У тебя есть три модуля, первый это Пользовател, второй Контейнер, трейти Линковщик.

                              Может другой пример?
                              Сообщение отредактировано: D_KEY -
                                Цитата korvin @
                                Да, я, видимо, неточно выразился. Я имел в виду, что для класса нужно прогонять не только тесты для его собственных методов, но и тесты для всех методов, унаследованных от родительских классов.
                                Ещё одно хорошее "зачем": разве не достаточно тестом показать факт наследования тестируемого класса от интересующего нас базового? Разве не следует из гарантий языка программирования заранее известный (однозначно предсказываемый) итог запуска тестов на наследуемых методах?
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0598 ]   [ 15 queries used ]   [ Generated: 27.04.24, 21:08 GMT ]