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

    С чего ты взял? Фабрика тестируется отдельно. В своем юнит-тесте.

    Цитата
    А они как бы все в язык несут, все новомодности модные собирают со всех языков и несут в язык. Чтоб было. :D

    Понятно :D

    Цитата
    Пишешь ЮТ - которые эмулируют работу, с помощью тех же mock объектов. Как правило помимо самих функций - тестируется еще и функционал который они делают. Потому как в 99% случаев, бывает такое, что для того, что бы юзнуть функцию в ЮТ, для нее нужно настроить окружение. А это подразумевает имитирование работы части функционала.
    Именно так.

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

    Верно.

    Цитата
    Где практически все косяки, в том числе и те, которые ты написал зачастую всплывают.

    Да как он у тебя выплывет? Класс B тестируется только в юнит-тесте класса B. В остальных юнит-тестах будет mock-объект вместо реального.
    Сообщение отредактировано: D_KEY -
      Цитата D_KEY @
      Именно так.

      У тебя в тестах не так. Если бы у тебя в тестах было бы так, то в одной из тестовой функций ты бы получил ошибку.

      Цитата D_KEY @
      Да как он у тебя выплывет? Класс B тестируется только в юнит-тесте класса B. В остальных юнит-тестах будет mock-объект вместо реального.

      Ну вся фишка в том, что в твоем случае не тестируется дин. полиморфизм. Т.е. ты просто протестировал в отрыве от функционала два метода двух разных классов. Хотя по факту у тебя там наследование, которое ты не тестируешь.
      Т.е. другими словами ты написал класс Млекопитающее, написал класс Собака, проверил их методы, но поведение сущности ты не проверил. Допустим в явошарпах, там тестируется буквально все, моки там нужны разве что для объектов, которые невозможно съэмитировать с помощью тестов. Например там физическая железка какая то. А так - даже БД создать можно. Поэтому не совсем понял о каком mock-Объекте ты говоришь. У тебя будет Mock-Объект, вместо тестируемого класса? :-?
        Цитата Wound @
        У тебя в тестах не так.

        Мои "тесты" - это лишь пример. Покажи "правильные" тесты для данного случая, кстати.

        Цитата
        Ну вся фишка в том, что в твоем случае не тестируется дин. полиморфизм.

        А ты часто видишь, чтобы кто-то явно кастил к базовому классу?

        Цитата
        Хотя по факту у тебя там наследование, которое ты не тестируешь.

        А ты тестируешь наследование?

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

        Чего? Mock-объекты и нужны для тестов.

        Цитата
        У тебя будет Mock-Объект, вместо тестируемого класса? :-?

        Нет, тестируемый класс как раз не Mock. А все его окружение, которое в реальном коде будет реальными объектами, в тестах сделано через Mock-объекты.

        Добавлено
        В моем примере в других тестах(не A и не B), вместо реальных объектов было бы Mock-объект, наследованный от A:
        ExpandedWrap disabled
          class MockA: public A {
              MOCK_CONST_METHOD0(foo, std::string());
          };

        А после рефакторинга стал бы:
        ExpandedWrap disabled
          class MockA: public A {
              MOCK_CONST_METHOD1(foo, std::string(int));
          };

        И во всех тестах, кроме тестов A, использовался бы он.
        Если используется не gtest/gmock, а какой-то другой фреймворк, то код был бы чуть другой, но суть та же.
          Цитата D_KEY @
          Мои "тесты" - это лишь пример. Покажи "правильные" тесты для данного случая, кстати.

          Так я тебе уже показывал.

          Цитата D_KEY @
          А ты часто видишь, чтобы кто-то явно кастил к базовому классу?

          Практически постоянно вижу, что работают все через интерфейсы. Через классы вообще мало кто работает.

          Цитата D_KEY @
          А ты тестируешь наследование?

          Почему нет? Я же его для чего то там написал, раз написал - значит нужно тестировать. А ты не тестируешь поведение, да? Тестируешь только голые методы классов?

          Цитата D_KEY @
          Чего? Mock-объекты и нужны для тестов.

          Для каких тестов? Mock-объекты нужны для имитации того, что ты не можешь иметь в ЮТ. Допустим - это может быть БД, Флешка, какое то устройство, еще чего то, какой нибудь контекст, который получается путем сложных манипуляций и т.д.

          Цитата D_KEY @
          Нет, тестируемый класс как раз не Mock. А все его окружение, которое в реальном коде будет реальными объектами, в тестах сделано через Mock-объекты.

          Ну ты пишешь что у тебя вот та фишка: factory->make_instance(...); будет где то там в Mock Объекте или вообще будет mock'Ом. Я если честно не понял ничего из того что ты пишешь. Зачем это будет моком? И что он в данном случае будет делать? :D Для чего он нужен другими словами? Ты же не будешь вызывать методы классов через него и проверять значения.

          Цитата D_KEY @
          В моем примере в других тестах(не A и не B), вместо реальных объектов было бы Mock-объект, наследованный от A:

          Слишком скудная информация. И как это потом использовать? Т.е. ты возвращаешь из метода что то, что не соответствует реальному результату? Что ты тогда тестишь то? У тебя явно тут идет расхождение в предложенных тестах и моках. Я если честно не совсем понимаю тебя.
            Wound, ты не знаешь, что такое mock объекты и как они используются?

            Добавлено
            Цитата Wound @
            Практически постоянно вижу, что работают все через интерфейсы. Через классы вообще мало кто работает.

            Ты пишешь тест на класс. Что значит никто не тестит через классы? Покажи плиз свой обычный тест на класс.

            Добавлено
            Wound, я не понимаю тебя, извини.

            Добавлено
            Цитата Wound @
            Mock-объекты нужны для имитации того, что ты не можешь иметь в ЮТ. Допустим - это может быть БД, Флешка, какое то устройство, еще чего то, какой нибудь контекст, который получается путем сложных манипуляций и т.д.

            Именно. В результате у тебя при тесте конкретного класса другие конкретные классы, как правило, не задействованы. Вместо них у тебя будет mock- объект с нужным интерфейсом.
              Цитата D_KEY @
              Wound, ты не знаешь, что такое mock объекты и как они используются?

              Знаю, я не понимаю, зачем делать так, как ты пишешь.

              Цитата D_KEY @
              Ты пишешь тест на класс. Что значит никто не тестит через классы? Покажи плиз свой обычный тест на класс.

              Ок, вот у тебя есть метод класса, который принимает две сущности, и линкует одну к другой:
              ExpandedWrap disabled
                class EntityLinker
                {
                public:
                   virtual bool LinkToContainer(IContainer* orgUnit, IPrincipal* principal)
                   {
                       if(orgUnit != nullptr && principal != nullptr)
                       {
                           return orgUnit->Link(principal);
                       }
                       return false;
                   }
                };

              У тебя вместо IPrincipal может быть например CUser, или там CPrinter, или может быть даже COrganizationUnit. В нашем случае это классы A и B. У юзера и принтера тоже есть свои какие то методы, и они тестируются отдельно.
              Я в тесте буду писать:
              ExpandedWrap disabled
                void testLinkToContainer()
                {
                    /*Тут, вместо new даже может быть Mock, который будет делать все тоже самое, кроме физического создания контейнера в системе, например как в примере создавать эксземпляр класса, напихивать в него данные, возвращать его, но не сохранять в системе*/
                    IContainer* pContainer = new COrgUnit(CN, DN, Location,...);
                 
                    /*Тут ровно тоже самое, создается либо через mock, либо напрямую нужный класс, забивается данными*/
                    IPrincipal* pPrincipal = new Personage(CN, DN, Location,...);
                 
                    //! Допустим через интерфейс создаем юзер аккаунт, который нужен будет для линковки
                    pPrincipal->CreateUserAccountPersonage();
                 
                    EntityLinker* linker = new EntiryLinker(...);
                  
                    //! Дальше тут какие то проверки, что все засетаплено честно.
                 
                    //! Дальше собственно выполняем нашу линковку:
                    linker->LinkToContainer(pContainer, pPrincipal);
                 
                   /*Дальше идет тестирование результатов линковки*/
                }

              Собственно вот у нас есть вот такая структура, как ты ее будешь тестить? Ну вот линковку?
              На сколько я понял, ты будешь писать что то типа:
              ExpandedWrap disabled
                void testLinkToContainer()
                {
                    /*Тут, вместо new даже может быть Mock, который будет делать все тоже самое, кроме физического создания контейнера в системе, например как в примере создавать эксземпляр класса, напихивать в него данные, возвращать его, но не сохранять в системе*/
                    COrgUnit unit(CN, DN, Location,...);
                 
                    /*Тут ровно тоже самое, создается либо через mock, либо напрямую нужный класс, забывается данными*/
                    CAccountPrincipal principal(CN, DN, Location,...);
                 
                    //! Что вот с этим делать? Такого метода нема у CAccountPrincipal
                    //pPrincipal->CreateUserAccountPersonage();
                    
                    EntityLinker* linker = new EntiryLinker(...);
                  
                    //! Дальше тут какие то проверки, что все засетаплено честно.
                 
                    //! Дальше собственно выполняем нашу линковку:
                    linker->LinkToContainer(&unit, &principal);
                 
                   /*Дальше идет тестирование результатов линковки*/
                }

              Верно? А если тебе до линковки нужно будет вызвать какой нибудь метод, который есть в базовом классе IContainer/IPrincipal, но нет в том, который ты пытаешься протестить? Что делать? :-?
              Обычно ЮТ, можно тестировать как отдельные методы, так и функционал в целом, когда ты уже начинает писать ЮТ для классов, которые юзают твои вот эти А/B.
              Напиши как ты будешь тестить и куда прикручивать моки?

              Цитата D_KEY @
              Wound, я не понимаю тебя, извини.

              Я если честно тоже не понимаю тебя. Ты заглушки тестишь что ли? Или что? Я так и не понял.

              Цитата D_KEY @
              Именно. В результате у тебя при тесте конкретного класса другие конкретные классы, как правило, не задействованы. Вместо них у тебя будет mock- объект с нужным интерфейсом.
              "I

              Так другие конкретные классы - это у тебя всегда сущности, которые ты не можешь создать в ЮТ? :blink:
                Цитата Wound @
                Так другие конкретные классы - это у тебя всегда сущности, которые ты не можешь создать в ЮТ? :blink:

                Ты слышал про IoC?

                Добавлено
                Цитата Wound @
                ...
                Верно?

                Нет. Тесты будут разные на все три класса. Линкер твой вообще не будет знать ничего про конкретные классы и в его тестах вместо них будут mock-объекты, реализующие IContainer и IPrincipal, соответственно.

                Добавлено
                Цитата Wound @
                А если тебе до линковки нужно будет вызвать какой нибудь метод, который есть в базовом классе IContainer/IPrincipal, но нет в том, который ты пытаешься протестить?

                Чего? Еще раз, мы о модульных тестах. Для твоего примера будет три отдельных теста. А в тесте linker'а будут использоваться не COrgUnit и Personage, а mock'и, реализующие IContainer и IProncipal, что позволит мне, например, отслеживать вызовы методов этих интерфейсов, проверять, что они вырвались нужное число раз, написать тесты на аргументы и т.д.
                Сообщение отредактировано: D_KEY -
                  Цитата D_KEY @
                  Ты слышал про IoC?

                  Слышал, как это к теме относится?


                  Цитата D_KEY @
                  Нет. Тесты будут разные на все три класса. Линкер твой вообще не будет знать ничего про конкретные классы и в его тестах вместо них будут mock-объекты, реализующие IContainer и IPrincipal, соответственно.

                  Конечно разные на все три класса, меня интересует как ты будешь тестить линкер. Он ежели чего, и так не знает про конкретные классы. Так ты мок объекты тестить будешь или что?
                    Цитата Wound @
                    Так другие конкретные классы - это у тебя всегда сущности, которые ты не можешь создать в ЮТ? :blink:

                    Зачем их там создавать, если можно и нужно работать через интерфейсы?

                    Добавлено
                    Цитата Wound @
                    меня интересует как ты будешь тестить линкер

                    Создам два mock'а, свяжу, проверю связь. Если нужно, чтоб дергались методы интерфейсов, проверю, что дергается нужное число раз и с ожидаемыми параметрами(gmock это позволяет).
                      Цитата D_KEY @
                      Зачем их там создавать, если можно и нужно работать через интерфейсы?

                      Вот теперь я тебя вообще перестал понимать. Ты до этого писал:
                      Цитата D_KEY @
                      А ты часто видишь, чтобы кто-то явно кастил к базовому классу?

                      Цитата D_KEY @
                      Во-вторых, я мало видел тестов, где бы кастили к базовому классу. Возможно, все кастят, а мне попадалось говно. Но это ничего на самом деле не меняет.

                      Теперь ты уже пишешь совершенно противоположное. :-?

                      Добавлено
                      Цитата D_KEY @
                      Создам два mock'а, свяжу, проверю связь. Если нужно, чтоб дергались методы интерфейсов, проверю, что дергается нужное число раз и с ожидаемыми параметрами(gmock это позволяет).

                      Что эти моки будут делать? Зачем их создавать, если у тебя есть возможность уже использовать существующие классы например?
                        Цитата Wound @
                        Цитата D_KEY @
                        Зачем их там создавать, если можно и нужно работать через интерфейсы?

                        Вот теперь я тебя вообще перестал понимать. Ты до этого писал:
                        Цитата D_KEY @
                        А ты часто видишь, чтобы кто-то явно кастил к базовому классу?

                        Цитата D_KEY @
                        Во-вторых, я мало видел тестов, где бы кастили к базовому классу. Возможно, все кастят, а мне попадалось говно. Но это ничего на самом деле не меняет.

                        Теперь ты уже пишешь совершенно противоположное. :-?

                        В первом случае идет речь о тесте самого класса. Я, наверное, никогда не видел, чтобы в тесте класса перед вызовами унаследованных функций объект явно кастили к базовому(а только это спасло бы помимо override в моем примере).

                        Добавлено
                        Цитата Wound @
                        Зачем их создавать, если у тебя есть возможность уже использовать существующие классы например?

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

                        Добавлено
                        Цитата Wound @
                        Зачем их создавать, если у тебя есть возможность уже использовать существующие классы например?

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

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

                          Добавлено
                          Цитата D_KEY @
                          В результате, теперь в случае экземпляра B, выводиться будет A.

                          Так у тебя тесты неправильные, вот ты сам себе и выстрелил в ногу. Тестовый набор для B не должен был включать в себя тесты для родительского метода foo(). В твоём случае такое перекрытие foo в B нарушает контракт (описанный в тесте для A.foo) родительского класса, который гласит, что метод foo() должен возвращать "A". А ты взял и в наследнике нарушил этот контракт. Тесты нельзя оверрайдить. Если ты вдруг это сделал (как в этом примере), тебе стоит тут же ударить себя по рукам, остановиться, подумать и решить: либо класс B не является наследником класса A, т.к. реализует другой контракт, либо контракт в тесте описан некорректно.
                            Цитата korvin @
                            Тестовый набор для B не должен был включать в себя тесты для родительского метода foo(). В твоём случае такое перекрытие foo в B нарушает контракт (описанный в тесте для A.foo) родительского класса, который гласит, что метод foo() должен возвращать "A".

                            С чего ты взял, что у него такой контракт? Пусть это будет метод, возвращающий некое описание класса, например.

                            Цитата
                            либо класс B не является наследником класса A, т.к. реализует другой контракт, либо контракт в тесте описан некорректно.

                            Да не реализует он другой контракт. Ты, по-моему, на ходу выдумываешь.

                            Ну ок, давай уберем тест foo для B. Мой пример остается валидным. Без override код молча скомпилируется при изменении сигнатуры.
                            Сообщение отредактировано: D_KEY -
                              Цитата D_KEY @
                              Я правильно понимаю, что это все потребует нового языка?

                              Не обязательно, существующие могут постепенно эволюционировать. «Внешние» интерфейсы (которые у меня названы protocol) есть в некоторых языках, например, OCaml и Go. Что-то похожее вроде было в Objective-C, возможно, есть и в Swift. Думаю, такие интерфейсы постепенно приобретут широкую популярность и будут постепенно добавлены во все мейнстримные языки. Лямбды ж добавили в консервативную Java =). В некоторм смысле и шаблоны C++ являются таковыми, только compile-time.

                              Цитата D_KEY @
                              Вот тут не понял. Зачем тебе goшные интерфейсый в java?

                              Затем, что если тупые разработчики какой-нибудь библиотеки не предусмотрели общие интерфейсы для sibling-классов, то приходится приседать с бубном, чтобы написать обощённый код. Например, Eclipse'овский SWT: у многих виджетов есть методы `String getText()` и `void setText(String text)`, но при этом они не реализуют какой-нибудь общий интерфейс `HasTextProperty { String getText(); void setText(String) }` и написать какой-нибудь обобщённый код для них просто так нельзя. На выбор такие костыли:

                              – написать свои классы, которые наследую SWT'шные и имплементируют нужные интерфейсы, например:
                              ExpandedWrap disabled
                                public class MyLabel extends swt.Label implements HasText {}

                              слава б-гу не нужно явно перечислять методы и писать @Override (ха-ха). Теперь нужно везде использовать эти свои классы, писать свои фабрики вместо тех, что уже есть в самом swt и т.п.

                              – воспользоваться рефлексией и написать тройку вспомогательных статических методов где-нибудь в своём UIUtil классе или типа того:
                              ExpandedWrap disabled
                                boolean hasText(swt.Widget w) { ... }
                                String getText(swt.Widget w) { ... }
                                void setText(swt.Widget w, String newText) { ... }

                              как ты понимаешь, ООП и статическая типизация тут идут лесом.

                              В Go же мне было бы достаточно определить в своём коде
                              ExpandedWrap disabled
                                type HasText interface {
                                 
                                    GetText() String
                                    SetText(String)
                                }


                              и всё. Все классы с такими методами автоматически годились бы для использования в коде, ожидающем объекты такого интерфейсного типа.

                              То же самое и с объектными типами в OCaml.

                              Цитата D_KEY @
                              Это будет ближе к практике?

                              А до этого что, далековато было? Оба указанных варианта применения интерфейсов выведены исключительно из практических применений. И предложение по их явному разделению продиктовано в том числе и практическими соображениями, а не только тем, что это «концептуально чище».

                              Добавлено
                              Цитата D_KEY @
                              С чего ты взял, что у него такой контракт?

                              С того, что он описан в тесте. Тесты существуют, чтобы описывать контракты, невыразимые языковыми средствами. Т.е. поведенческие контракты.

                              Добавлено
                              Цитата D_KEY @
                              Да не реализует он другой контракт. Ты, по-моему, на ходу выдумываешь.

                              Ты, по-моему, совсем забыл про LSP, например. И про то, что далеко не во всех языках можно описать полноценно контракт чисто системой типов, поэтому она дополняется применяется тестированием.

                              Добавлено
                              D_KEY, может, мы по-разному понимаем слово «контракт»? «Спецификация» тебя больше устроит? Не знаю, «набор инвариантов»?
                              Сообщение отредактировано: korvin -
                                Цитата korvin @
                                С того, что он описан в тесте. Тесты существуют, чтобы описывать контракты, невыразимые языковыми средствами

                                Я тебе привел пример, когда такой код не будет нарушением контракта.
                                Еще пример - класс исключений и метод, возвращающий сообщение об ошибке. У разных классов будут разные значения. Тесты можно не писать на это дело, а можно и написать.
                                Контракт это нарушать не будет.

                                Добавлено
                                И, повторяю еще раз. Тесты не имеют отношения к моему примеру. Их можно вообще убрать.
                                А пример о том, что изменение сигнатуры метода в базовом классе может пройти незаметно без override, а это может являться ошибкой.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0697 ]   [ 15 queries used ]   [ Generated: 28.04.24, 04:47 GMT ]