воскресенье, 7 декабря 2008 г.

Как тестировать приватные функции класса?

Знакомый вопрос? И какие у нас есть решения
1. Использовать рефлекшн
2. Директивы компиляции #if DEBUG - ужас
3. friend и его альтернативы
4. Возможности встроенного xUnit фреймвока в IDE который делает чёрную магию (см VS.Net)
5. Ваше любимое :)

Если первое решение смерть всему поколению поддержки, а второе ужас на крыльях ночи, то стоит вопрос - а чего делать-то?

TDD нас учит - пишите тесты и всё будет пучком. Действительно будет, но жизнь не идеальна. И появляются приватные методы и конечно же возникает желание их потестить.

Почему многие бьются, но не находят решения? А потому как мы находимся в такой парадигме программирования, которые не предполагает решения. Там его просто нет. Спросите, а что не так с нашей парадигмой? Да всё просто - мы со своей теорией знания ООП лезем в бизнес-разработку. Теория ООП - это академически дисцеплина. А наш код - это бизнес-реальность.

Что говорит теория - инкапсулируй, скрывай и т.п.

А что говорит бизнес? Гони нам качественное и дешевое решений! А почему же теория делает нам решение не дешёвым? А все просто - нету тестов, запутанный код, неясная логика, неадекватные называния и огромная связанность даёт прибавки в стоимости нашего кода в части поддержки и развития. Мы платим огромные сумма за поддержку и развитие кода, нежели его создания. Пусть икает тот разработчик, который первый породил тот или инной класс. И получил свои 10$ за него. Теперь мы дни тратим понимая, почему он вызывает отъезжание в другом месте и днями на пролёт эксперементируем как к этому делу прикрутить чуть больше функций. И платим за это сотни, а может быть даже тысячи баксов.

То есть задача бизнес кода - получить дешевое решение. Которое легко развивать, сопровождать, читать, анализировать и оно обладает минимальной связанностью. Конечно же TestFirst, TDD, Refactoring, Patterns, Continuous Integration здесь наше спасение. Но вернёмся к приватам.

Парадигма "бизнес разработки" такова, что нужно посмотреть, кто является клиентами нашего кода. Кто использует продукт нашего творчества? Мы должны сделать все возможное и невозможное, нарушая теоретические полёты мысле теоретиков от ООП, с целью удешевления поддержки и развития.

А клиентами нашего кода являются: конечные пользователи и разработчики. Причем ещё не ясно, кто больше наш код использует. Пользователи тыкают конечно приложение. Но кто вас чаще вспоминать будет, если вы нагородили подлянок на каждом шагу, не проводили рефакторинги и вообще оставили тучу смеллов не покрытых тестами?

Итог. Клиенты кода - это заказчик + разработчики. Причем последний в большей мере. Так какого мы тресёмся за теоретическую инкапсуляцию и забиваем на тесты открывая нужные функции, делая их protected (шунтируя для теста класс, например) или даже public? Кончайте голову себе и другим пудрить! Делайте дело и используйте всё многообразие подходов, чтобы качество кода было 101% и его цена минимальна!

Я выделил 3 парадигмы разработки, который порождает рассматриваемый случай
1. "Теоретическая" (когда неуклонно следуем ООП и придумываем обходные манёвры о которых в ООП ничего не говорится и считаем их хорошими — см. п.1-п.5 выше). Максимальное количество private.
2. TDD — уже смещает парадигму мышления и на выходе получаем изолированные модули. Но и там проскакивает приват. Который приводит к одному из п.1-п.5
3. "Бизнес-программирование". Используем TDD + открываем (protected|public) методы для нужд тестирования. Так как я являюсь пользователем своего кода и мне важно его качество выраженное через 1) покрытие тестами, 2) простоте чтения.

Я работаю по методу 3.

Выбранный мною подход разработки делает мой код дешевле и качественнее.

5 комментариев:

  1. Кхм, Денис, что-то непонятно, что же конкретно Вы предлагаете для тестирования приватных методов? :)

    P.S.

    И кто такой "коучер"? Это тренерер? :)

    ОтветитьУдалить
  2. Сейчас дописываю.

    В некотором смысле коучер - это тренер. Кстати, замечу, это не преподаватель.

    В Agile командах такой человек должен быть на постоянной или временной основе. Ну а в начале, когда народ переходит на Agile такой человек нанимается, чтобы разогнать поезд. А потом такая роль появляется в самой команде.

    ОтветитьУдалить
  3. можно использовать следующий прием:
    создается интерфейс [MyClass]WhiteBox
    который позволяет добраться до приватных функций
    тестируемый класс реализует этот интерфейс, используются директивы условной компиляции чтобы это происходило только в режиме DEBUG
    пишутся обычные unit тесты, которые через WhiteBox могут трогать приватные методы

    ОтветитьУдалить