О чем речьМногие реальные проекты уже сегодня используют методологию TDD (Test-Driven Development). Вместе с тем количество интересующихся данным вопросом постоянно увеличивается, а это будет способствовать тому, что и в будущем количество таких проектов будет неуклонно расти. Причины этому достаточно очевидны – использование методологии способствует улучшению качества кода на самом раннем этапе проектов, снижая количество ошибок, в том числе и архитектурных, и существенно уменьшает затраты на поддержку проекта в дальнейшем.
Вместе с тем, использование TDD для новичков и для тех, кому написание юнит-тестов в диковинку, сопряжено с некоторыми проблемами и вопросами, возникающими на этапе создания этих самых тестов. К примеру, абсолютно очевидно, что некоторый код, который используется в проекте, не может быть покрыт тестами. Например, в случае, когда необходимо осуществлять непосредственную работу с базами данных или обращаться к «железу». Здесь на помощь приходят средства прототипирования, иначе известные как mock-фреймворки. Именно о них я и хочу поговорить в своей статье и показать, как их можно использовать на примере объектов, работающего с устройствами, известными как Smart Cards, или, говоря проще, с идентификационными пластиковыми карточками и считывающими устройствами (кард-ридерами).
В повседневной жизни я имею дело с платформой .NET и использую ее в своих проектах, соответственно здесь и далее речь будет идти о средствах и подходах в первую очередь применительно к .NET.
Два слова о MockMock-фреймворков для целевой платформы существует большое количество. К числу наиболее распространенных можно отнести TypeMock Isolator, Rhino Mock, NMock и Moq. У каждого из них есть свои достоинства и недостатки. Поскольку это вопрос отдельной статьи – я не буду на этом останавливаться сейчас. Для статьи я выбрал Moq (официальный сайт: http://code.google.com/p/moq/), как наиболее легковесный и интуитивный. Отмечу, что тот же TypeMock Isolator или же Rhine – продукты куда более мощные и
содержат в себе гораздо больше возможностей. Однако для большинства случаев, как в частности и в рассматриваемом примере, функциональности Moq – больше чем достаточно.
Еще один момент, на который хотелось бы обратить внимание перед рассмотрением реального примера – это принцип работы mock-фреймворков. Как они помогают в написании тестов для кода, который невозможно оттестировать? Как известно, чудес не бывает, и если код должен обращаться к железу напрямую, то никакие фреймворки не избавят от этой необходимости. Однако в данном случае из компонента, который работает с железом можно выделить интерфейс, в котором будут определены методы подключения, отключения, чтения и записи данных устройства. Далее с помощью Mock-фреймворка на основании полученного интерфейса можно создать объект, который будет использоваться остальным кодом, и будет эмулировать работу с железом, замещая вызовы API методов своими переопределенными методами, которые в точности эмулируют логику работы с железом. В результате для всего остального кода можно беспрепятственно написать юнит-тесты. Таким образом, непокрытым останется только реализация объекта, которая обращается к реальному устройству. А так как основную часть кода такого объекта составляют вызовы API методов, то этим можно пренебречь – так как, по сути, подобная логика не может быть оттестирована без реального обращения к реальному устройству.
Как быть со Smart CardsИтак, перед нами стоит задача – создать прототипы для объектов, которые будут работать cо Smart Card и соответственно с кард-ридерами. Прототипы будут созданы с помощью mock-фреймворка Moq.
Прежде всего, нужно определиться с тем, что мы будем делать со Smart Cards в нашем примере и соответственно иерархией объектов, с которой мы будем иметь дело. При использовании Smart Cards нам, очевидно, понадобиться, собственно, сама карточка и считывающее устройство (кард-ридер), которое необходимо подключить к компьютеру. Обращение к карточке из нашего кода может быть возможным только в том случае, если она находится в считывающем устройстве. После того как мы убедились что, карточка доступна мы должны иметь возможность:
· Считать из нее идентификационную информацию (предположим, в качестве таковой будет служить серийный номер карточки, который прописывается при прошивке карточки)
· Проверить на правильность PIN-код который введет пользователь (PIN-код так же прописывается при прошивке)
· После того как введен правильный PIN-код, должны быть доступны операции записи некоторых данных (предполагается что операции чтения могут быть доступны и без PIN кода, так как иначе могут возникнуть сложности с чтением серийного номера), которые будут храниться на карточке и представляют для нас первоочередной интерес.
· Если PIN-код не введен, или введен, но неправильный – доступ к этим данным должен быть запрещен.Проектирование иерархииТаким образом, собрав воедино все требования, которые предъявляются к нашим объектам, которые будут работать с карточками, можно остановиться на интерфейсе, похожем на этот:
public interface ISmartCard
{
string ReadSerial();
string ReadData();
void WriteData(string data);
bool CheckPinCode(string pin);
}Read more: My revelation. sharcUs
Вместе с тем, использование TDD для новичков и для тех, кому написание юнит-тестов в диковинку, сопряжено с некоторыми проблемами и вопросами, возникающими на этапе создания этих самых тестов. К примеру, абсолютно очевидно, что некоторый код, который используется в проекте, не может быть покрыт тестами. Например, в случае, когда необходимо осуществлять непосредственную работу с базами данных или обращаться к «железу». Здесь на помощь приходят средства прототипирования, иначе известные как mock-фреймворки. Именно о них я и хочу поговорить в своей статье и показать, как их можно использовать на примере объектов, работающего с устройствами, известными как Smart Cards, или, говоря проще, с идентификационными пластиковыми карточками и считывающими устройствами (кард-ридерами).
В повседневной жизни я имею дело с платформой .NET и использую ее в своих проектах, соответственно здесь и далее речь будет идти о средствах и подходах в первую очередь применительно к .NET.
Два слова о MockMock-фреймворков для целевой платформы существует большое количество. К числу наиболее распространенных можно отнести TypeMock Isolator, Rhino Mock, NMock и Moq. У каждого из них есть свои достоинства и недостатки. Поскольку это вопрос отдельной статьи – я не буду на этом останавливаться сейчас. Для статьи я выбрал Moq (официальный сайт: http://code.google.com/p/moq/), как наиболее легковесный и интуитивный. Отмечу, что тот же TypeMock Isolator или же Rhine – продукты куда более мощные и
содержат в себе гораздо больше возможностей. Однако для большинства случаев, как в частности и в рассматриваемом примере, функциональности Moq – больше чем достаточно.
Еще один момент, на который хотелось бы обратить внимание перед рассмотрением реального примера – это принцип работы mock-фреймворков. Как они помогают в написании тестов для кода, который невозможно оттестировать? Как известно, чудес не бывает, и если код должен обращаться к железу напрямую, то никакие фреймворки не избавят от этой необходимости. Однако в данном случае из компонента, который работает с железом можно выделить интерфейс, в котором будут определены методы подключения, отключения, чтения и записи данных устройства. Далее с помощью Mock-фреймворка на основании полученного интерфейса можно создать объект, который будет использоваться остальным кодом, и будет эмулировать работу с железом, замещая вызовы API методов своими переопределенными методами, которые в точности эмулируют логику работы с железом. В результате для всего остального кода можно беспрепятственно написать юнит-тесты. Таким образом, непокрытым останется только реализация объекта, которая обращается к реальному устройству. А так как основную часть кода такого объекта составляют вызовы API методов, то этим можно пренебречь – так как, по сути, подобная логика не может быть оттестирована без реального обращения к реальному устройству.
Как быть со Smart CardsИтак, перед нами стоит задача – создать прототипы для объектов, которые будут работать cо Smart Card и соответственно с кард-ридерами. Прототипы будут созданы с помощью mock-фреймворка Moq.
Прежде всего, нужно определиться с тем, что мы будем делать со Smart Cards в нашем примере и соответственно иерархией объектов, с которой мы будем иметь дело. При использовании Smart Cards нам, очевидно, понадобиться, собственно, сама карточка и считывающее устройство (кард-ридер), которое необходимо подключить к компьютеру. Обращение к карточке из нашего кода может быть возможным только в том случае, если она находится в считывающем устройстве. После того как мы убедились что, карточка доступна мы должны иметь возможность:
· Считать из нее идентификационную информацию (предположим, в качестве таковой будет служить серийный номер карточки, который прописывается при прошивке карточки)
· Проверить на правильность PIN-код который введет пользователь (PIN-код так же прописывается при прошивке)
· После того как введен правильный PIN-код, должны быть доступны операции записи некоторых данных (предполагается что операции чтения могут быть доступны и без PIN кода, так как иначе могут возникнуть сложности с чтением серийного номера), которые будут храниться на карточке и представляют для нас первоочередной интерес.
· Если PIN-код не введен, или введен, но неправильный – доступ к этим данным должен быть запрещен.Проектирование иерархииТаким образом, собрав воедино все требования, которые предъявляются к нашим объектам, которые будут работать с карточками, можно остановиться на интерфейсе, похожем на этот:
public interface ISmartCard
{
string ReadSerial();
string ReadData();
void WriteData(string data);
bool CheckPinCode(string pin);
}Read more: My revelation. sharcUs
0 comments:
Post a Comment