public ViewResult About(int param1) {
var model = CreateAboutModel(param1);
return View(model);
}
public ViewResult AboutAjax(int param1) {
var model = CreateAboutModel(param1);
return View("About", model);
}
public AboutViewModel CreateAboutModel(int param1) {
return new AboutViewModel() {/*some calculations go here */}
}
и так на каждый экшен. Вместо одного метода — три.
Накладных расходов, имхо, многовато, и писаться это будет копи-пастой — легко забыть указать имя вьюшки в AboutAjax, например.
Если в большинстве случаев логика аякс и не-аякс запросов одинакова, то имхо лучше всё-таки сократить усилия на экшен. Хотя и ваш подход имеет право на жизнь, не спорю.
А можно еще и вынести проверку на IsAjaxRequest в базовый класс и будет вовсе красота: public ViewResult About()
{
return PartialOrFullView("About");
}
Ну и еще из плюсов «одного метода» — сылка в браузере будет вести на человеческий "/Home/About", а не роботизированный "/Home/AboutAjax".
собственно, подход более-менее очевидный, в своем проекте реализовал очень схожим образом. Разве что Html.PageInfo на Razor section было.
С точки зрения относительно крупного рефакторинга, как мне кажется, интеграционные и приемочные тесты намного полезнее мелких юнит-ТДД-тестов. В процессе рефакторинга важны тесты, которые не надо будет менять/переписывать, которые останутся после рефакторинга нетронутыми. И это обычно таки интеграционные/приемочные тесты (потому что при рефакторинге происходит перераспределение ответственностей между классами, а то и вовсе замена некоторых участков целиком).
Мелкие тдд-юнит-тесты хороши для проверки конкретной локальной логики, они наибольшую пользу приносят как раз при написании — это проверка, что «сейчас всё работает». Ну и если идет мелкий-внутриклассовый-рефакторинг, то да, они тоже хороши.
Но в контексте результатов опроса, спор о том «какие же тесты лучше» можно и не затевать, а остановиться на утверждении, что «тесты нужны» :) А то посмотрят люди, что в стенах сторонников тестов «согласья нет», и не задумаются о тестах вообще :)
Терминология тут не очень устоявшаяся, поэтому и возникают недопонимания. Поэтому и «байки» из-за того, что разные люди под одним и тем же термином подразумевают разные вещи.
«A unit is the smallest testable part of an application.» — это из вики. То есть веб-сервис целиком это в классическом понимании таки не юнит.
Ну и понятие «внешней зависимости» оно тоже слегка неоднозначное.
Для вас интеграционный тест — это когда вся система целиком и полностью реальна, получается. А это тоже не всегда так.
Есть некая статистика, что TDD не помогает :) Но это, конечно, именно о ТДД, а не о тестах в принципе.
А вообще со статистикой сложно, потому что никто в реальной жизни не даст провести два одинаковых длинных проекта с «одинаковыми» командами, но разными методологиями.
Крайности плохи, как и везде. По поводу оптимальности компромисса согласен полностью.
Юнит тест — это тест «минимально тестируемого» участка (функции/метода) в изоляции. То есть в тесте только один класс с реальной реализацией, всё остальное «симуляция».
Под интеграционным тестом я понимаю тест, в котором более чем один класс «реален». Естественно, вся эта система из 2-3-5 или более классов имеет в свою очередь внешние зависимости и они тоже стабятся.
Крайний случай интеграционного теста — это acceptance тест — в нём реальна вся система и стабов нет.
Согласен, для новичков «чистый ТДД», имхо, почти идеален.
Не очень люблю примеры с «катами программиста», но здесь он будет очень к месту. Следуя ТДД легко понять и плюсы тестирования, и обучится Солиду. И уже потом адаптировать ТДД под себя, убирая моменты, на которые тратится черезчур много времени (и которые не окупаются в дальнейшем).
апологеты TDD, конечно, поспорят, вокруг чего крутится TDD :)
английская вики пишет, что BDD включает в себя TDD и расширяет его «тестами на человеческом языке» — по сути некоторым аналогом «среднеинтеграционных» тестов (как я понимаю).
Собственно, плюсы интеграционных тестов как раз в том, что они «более понятны человеку», потому что тестируют не мелкие абстракции, а какие-то слегка более крупные композиции объектов, соответственно, операции с ними (при правильном дизайне) выглядят вполне человечно.
Я более-менее правильно понял идею «поведенческих тестов»?
Блогом я ошибся, да. Причем я сам думал, что выбрал TDD, а оказалось… :)
Я в первых вариантах потому и написал «покрытие стремится к 100%» (а не равно 100%). К слову, геттеры-сеттеры в классическом ТДД у вас тоже будут «покрыты». На них не будет отдельных тестов, но они покроются другими.
Если вещей, которые «не надо тестировать» у вас больше чем просто геттеры/сеттеры, то можно выбрать вариант 3, который подразумевает, что есть некоторые вещи, которые в компании «писать по TDD не принято», по причинам того, что это не окупается. Хорошей иллюстрацией к третьему пункту была бы «классическая» картинка:
Я потому и уточнил, что под «модулем» может подразумеваться и класс, и, допустим, библиотека :) С тех. терминологией в русском языке не все утряслось еще.
За ответ спасибо, хотя по первому пункту и было бы любопытно подискутировать, но будет совсем оффтопик :)
В первом пункте про тесты вы пишете «модульные тесты». Вы имеете в виду юнит-тесты (тестирование каждого класса в изоляции от других классов) или именно модульные тесты (мелко-интеграционные, включающие взаимодействие двух-трех-нескольких классов)?
У нас тут просто жаркие дискуссии по этому поводу :)
Ну и в догонку про технологии — у вас Asp.net MVC? Что майкрософтовская технология — понятно, а какая именно — не очень :)
Даже несмотря на то, что конкретно эти темы не слишком интересны — очень постараюсь прийти. Может, хоть какое-никакое программистское комьюнити появится…
Людям проще что-то делать, если у них есть уверенность, что смогут это сделать. Если появляется неуверенность, что «а вдруг не получится», «а может я всё это делаю зря» — мотивация падает и работать становится сложнее.
Вера в «помощь вселенной» помогает тем, что появляется уверенность — «я это в итоге сделаю», ну, потому что вселенная в случае чего поможет :).
Это я никоим образом не применительно к себе, но всякие ГТД-шные штуки типа «разбейте задания на небольшие и отмечайте каждое сделанное» — по сути способствуют тому же, человек начинает верить, что выполнив эти мелкие шаги добьется большой конечной цели.
Другое дело, что в случае ГТД эта вера более обоснованна :)
> В случае со спецификациями приложение знает про Repository и про все спецификации.
А какие у этого минусы? Число зависимостей (один IQueryFactory или множество репозиториев) само по себе не минус — а инъекция IQueryFactory может слегка напомнить инъекцию IocContainer'a.
В посте — зависимости от интерфейса IQuery<TC,TR>, который, по факту, скрывает в себе множество классов.
Не получается ли, кстати, что Query слегка нарушают SRP самостоятельно осуществляя и доступ к данным, и их обработку\преобразование в модель?
Программистам-команде нужны сформулированные требования, а этого и методология «пиши-код» не отрицает.
Вообще это просто обратная реакция на повышенную модность «гибких методологий», в которых часто идет перегиб на «мы — команда, мы — вместе, давайте больше общаться и обсуждать каждую мелкую деталь все вместе!». Слегка утрирую, но тем не менее.
А в «классике» подразумевается, что по каждому вопросу всегда есть один человек(и понятно, кто это) к которому можно прийти и вопрос этот решить. Что в определенных случаях более удобно.
public ViewResult About(int param1) {
var model = CreateAboutModel(param1);
return View(model);
}
public ViewResult AboutAjax(int param1) {
var model = CreateAboutModel(param1);
return View("About", model);
}
public AboutViewModel CreateAboutModel(int param1) {
return new AboutViewModel() {/*some calculations go here */}
}
и так на каждый экшен. Вместо одного метода — три.
Накладных расходов, имхо, многовато, и писаться это будет копи-пастой — легко забыть указать имя вьюшки в AboutAjax, например.
Если в большинстве случаев логика аякс и не-аякс запросов одинакова, то имхо лучше всё-таки сократить усилия на экшен. Хотя и ваш подход имеет право на жизнь, не спорю.
public ViewResult About(){
return PartialOrFullView("About");
}
Ну и еще из плюсов «одного метода» — сылка в браузере будет вести на человеческий "/Home/About", а не роботизированный "/Home/AboutAjax".
собственно, подход более-менее очевидный, в своем проекте реализовал очень схожим образом. Разве что
Html.PageInfoна Razor section было.Но статья всё равно неплохая :)
Мелкие тдд-юнит-тесты хороши для проверки конкретной локальной логики, они наибольшую пользу приносят как раз при написании — это проверка, что «сейчас всё работает». Ну и если идет мелкий-внутриклассовый-рефакторинг, то да, они тоже хороши.
Но в контексте результатов опроса, спор о том «какие же тесты лучше» можно и не затевать, а остановиться на утверждении, что «тесты нужны» :) А то посмотрят люди, что в стенах сторонников тестов «согласья нет», и не задумаются о тестах вообще :)
«A unit is the smallest testable part of an application.» — это из вики. То есть веб-сервис целиком это в классическом понимании таки не юнит.
Ну и понятие «внешней зависимости» оно тоже слегка неоднозначное.
Для вас интеграционный тест — это когда вся система целиком и полностью реальна, получается. А это тоже не всегда так.
А вообще со статистикой сложно, потому что никто в реальной жизни не даст провести два одинаковых длинных проекта с «одинаковыми» командами, но разными методологиями.
Крайности плохи, как и везде. По поводу оптимальности компромисса согласен полностью.
Под интеграционным тестом я понимаю тест, в котором более чем один класс «реален». Естественно, вся эта система из 2-3-5 или более классов имеет в свою очередь внешние зависимости и они тоже стабятся.
Крайний случай интеграционного теста — это acceptance тест — в нём реальна вся система и стабов нет.
Не очень люблю примеры с «катами программиста», но здесь он будет очень к месту. Следуя ТДД легко понять и плюсы тестирования, и обучится Солиду. И уже потом адаптировать ТДД под себя, убирая моменты, на которые тратится черезчур много времени (и которые не окупаются в дальнейшем).
английская вики пишет, что BDD включает в себя TDD и расширяет его «тестами на человеческом языке» — по сути некоторым аналогом «среднеинтеграционных» тестов (как я понимаю).
Собственно, плюсы интеграционных тестов как раз в том, что они «более понятны человеку», потому что тестируют не мелкие абстракции, а какие-то слегка более крупные композиции объектов, соответственно, операции с ними (при правильном дизайне) выглядят вполне человечно.
Я более-менее правильно понял идею «поведенческих тестов»?
Как мне кажется, наиболее близкий к BDD вариант в опросе — второй. Поясните, пожалуйста, различия?
Я в первых вариантах потому и написал «покрытие стремится к 100%» (а не равно 100%). К слову, геттеры-сеттеры в классическом ТДД у вас тоже будут «покрыты». На них не будет отдельных тестов, но они покроются другими.
Если вещей, которые «не надо тестировать» у вас больше чем просто геттеры/сеттеры, то можно выбрать вариант 3, который подразумевает, что есть некоторые вещи, которые в компании «писать по TDD не принято», по причинам того, что это не окупается. Хорошей иллюстрацией к третьему пункту была бы «классическая» картинка:
А у вас хрупкими тесты не получаются? То есть если какая-нибудь функция перешла из одного класса в соседний, это не влечет массовый тестоповал? :)
За ответ спасибо, хотя по первому пункту и было бы любопытно подискутировать, но будет совсем оффтопик :)
У нас тут просто жаркие дискуссии по этому поводу :)
Ну и в догонку про технологии — у вас Asp.net MVC? Что майкрософтовская технология — понятно, а какая именно — не очень :)
Людям проще что-то делать, если у них есть уверенность, что смогут это сделать. Если появляется неуверенность, что «а вдруг не получится», «а может я всё это делаю зря» — мотивация падает и работать становится сложнее.
Вера в «помощь вселенной» помогает тем, что появляется уверенность — «я это в итоге сделаю», ну, потому что вселенная в случае чего поможет :).
Это я никоим образом не применительно к себе, но всякие ГТД-шные штуки типа «разбейте задания на небольшие и отмечайте каждое сделанное» — по сути способствуют тому же, человек начинает верить, что выполнив эти мелкие шаги добьется большой конечной цели.
Другое дело, что в случае ГТД эта вера более обоснованна :)
А какие у этого минусы? Число зависимостей (один IQueryFactory или множество репозиториев) само по себе не минус — а инъекция IQueryFactory может слегка напомнить инъекцию IocContainer'a.
В посте — зависимости от интерфейса IQuery<TC,TR>, который, по факту, скрывает в себе множество классов.
Не получается ли, кстати, что Query слегка нарушают SRP самостоятельно осуществляя и доступ к данным, и их обработку\преобразование в модель?
Программистам-команде нужны сформулированные требования, а этого и методология «пиши-код» не отрицает.
Вообще это просто обратная реакция на повышенную модность «гибких методологий», в которых часто идет перегиб на «мы — команда, мы — вместе, давайте больше общаться и обсуждать каждую мелкую деталь все вместе!». Слегка утрирую, но тем не менее.
А в «классике» подразумевается, что по каждому вопросу всегда есть один человек(и понятно, кто это) к которому можно прийти и вопрос этот решить. Что в определенных случаях более удобно.
Больше 100МБ меня как-то не очень радует…