Модульне тестування в Eclipse, Різне, Програмування, статті

Фіктивні об’єкти імітують поведінку класів, написаних з єдиною метою – управління виконанням коду під час тестування. З часом кількість фіктивних об’єктів може зрости одночасно з кількістю класів програми. Такі інтегровані середовища як jMock, RMock і навіть EasyMock усувають потреба в окремому фізично існуючому наборі фіктивних об’єктів.


Істотним недоліком інтегрованого середовища EasyMock є можливість імітувати лише інтерфейси, а не реальні класи. У даній статті я розповім, як можна використовувати інтегровану середу jMock для імітації реальних класів та інтерфейсів, а також як виконувати тестування за допомогою RMock в деяких неясних ситуаціях.







 



Примітка

Платформа Eclipse надає простий у використанні механізм роботи з інтегрованими середовищами jMock і RMock.


Налаштування jMock і RMock в Eclipse IDE


Спочатку запустіть інтегроване середовище розробки Eclipse (integrated development environment – IDE). Потім створіть базовий Java-проект, в який ви виконаєте імпорт JAR-бібліотек JUnit, jMock і RMock. Назвіть Java-проект TestingExample. У перспективі Java виберіть Project > Properties, А потім перейдіть в закладку Libraries, Як показано нижче.


Рисунок 1. Редагування властивостей проекту TestingExample в Eclipse
Рисунок 1. Редагування властивостей проекту TestingExample в Eclipse


Використовуйте кнопку Add JARs, Якщо JAR-файли вказані в Java classpath (Java Runtime Environment (JRE), налаштована в Eclipse). Кнопка Add Variable працює з конкретним каталогом файлової системи (локальної або віддаленої), де розміщені ресурси (включаючи JAR-файли), на які можна послатися. Використовуйте кнопку Add Library, Якщо потрібно послатися на такі спеціалізовані ресурси, які використовуються в Eclipse за замовчуванням або налаштовані на спеціалізовану середу робочої області Eclipse. Натисніть кнопку Add Class Folder, Щоб додати ресурс з однієї з папок існуючих проектів, уже налаштованих як частина проекту.


Для даного прикладу натисніть Add External JARs і знайдіть JAR-файли jMock і RMock, які вже завантажили. Додайте їх у проект. Натисніть кнопку OK, Коли з’явиться вікно властивостей, зображене на малюнку 2.


Рисунок 2. JAR-файли jMock і RMock, додані в проект TestingExample
Рисунок 2. JAR-файли jMock і RMock, додані в проект TestingExample

Вихідний код TestExample


В TestExample Project ви будете працювати з вихідним кодом чотирьох класів:



Тестованим класом є ServiceClass, Який містить один метод: runService(). Метод service приймає об’єкт Collaborator, Який реалізує простий інтерфейс ICollaborator. Один метод реалізований у конкретному класі Collaborator: executeJob(). Collaborator – Це клас, який ви повинні імітувати відповідним чином.


Четвертий клас – це тестовий клас ServiceClassTest (Реалізація максимально спрощена). У лістингу 1 показаний початковий код цього четвертого класу.


Лістинг 1. Код прикладу класу Service





public class ServiceClass {
public ServiceClass(){ / / Конструктор без аргументів
}
public boolean runService(ICollaborator collaborator){
if(“success”.equals(collaborator.executeJob())){
return true;
}
else
{
return false;
}
}
}

У класі ServiceClass блок коду if…else є простим логічним переходом, що допомагає відобразити, чому тест завершиться невдало або успішно при виборі одного (а не іншого) шляхи, відповідно до очікуваними результатами. Вихідний код класу Collaborator показаний нижче.


Лістинг 2. Код прикладу класу Collaborator





public class Collaborator implements ICollaborator{
public Collaborator(){ / / Конструктор без аргументів
}
public String executeJob(){
return “success”;
}
}

Клас Collaborator з конструктором без аргументів і простий змінної String, Що повертається з методу executeJob(), Теж не складний. Нижче показаний код класу ICollaborator.






public interface ICollaborator {
public abstract String executeJob();
}

Інтерфейс ICollaborator має один метод, який повинен бути реалізований в класі Collaborator.


Маючи наведений вище код, давайте перейдемо до розгляду того, як можна успішно виконати ваш тест класу ServiceClass в різних сценаріях.


Сценарій 1: Використання jMock для імітації інтерфейсів


Тестувати метод service в класі ServiceClass просто. Припустимо, що предметом тестування є твердження, що метод runService() не виконувався, або, іншими словами, що повернений Boolean-результат дорівнює false. В цьому випадку імітується передається в метод runService() об’єкт ICollaborator для очікування виклику його методу executeJob() і повернення рядка, відмінній від “success”. Таким чином, ви гарантуєте, що Boolean-рядок false повертається в тест.


Код класу ServiceClassTestНаведений нижче, містить логіку тесту.


Лістинг 3. Код прикладу класу ServiceClassTest для сценарію 1





import org.jmock.Mock;
import org.jmock.cglib.MockObjectTestCase;
public class ServiceClassTest extends MockObjectTestCase {
private ServiceClass serviceClass;
private Mock mockCollaborator;
private ICollaborator collaborator;

public void setUp(){
serviceClass = new ServiceClass();
mockCollaborator = new Mock(ICollaborator.class);
}

public void testRunServiceAndReturnFalse(){
mockCollaborator.expects(once()).method (“executeJob”).will(returnValue(“failure”));
collaborator = (ICollaborator)mockCollaborator.proxy();
boolean result = serviceClass.runService(collaborator);
assertFalse(result);
}
}






 



Коли потрібно писати власні тести

Кращим способом виконання своїх власних експериментів з будь інтегрованої середовищем імітаційного тестування є динамічний підхід test-first. Спочатку створіть тест і встановіть очікувані результати. Тільки після невдалого виконання тесту необхідно написати реалізацію для коригування тесту. Якщо тест працює, пишіть інший тест для перевірки функціональності, що додається вами в тестований клас пізніше.


Зазвичай гарною ідеєю є включення в тести методу setUp(), Якщо в різних прикладах тестів виконуються спільні операції. Метод tearDown() теж годиться, але він не настільки необхідний до тих пір, поки ви не будете виконувати інтегровані тести.


Також зверніть увагу на те, що в jMock і RMock середу перевіряє всі очікувані результати по всіх фіктивним об’єктах в кінці (або під час) виконання тесту. Немає реальної необхідності включати метод verify() для кожного очікуваного результату. При виконанні тесту як JUnit, тест завершується успішно, як показано нижче.


Рисунок 3. Успішне виконання тесту сценарію 1
Рисунок 3. Успішне виконання тесту сценарію 1


Клас ServiceTestClass розширює клас org.jmock.cglib.MockObjectTestCase jMock CGLIB. mockCollaborator – Це простий клас org.jmock.JMock. Зазвичай є два способи створення фіктивних об’єктів в jMock:



Важливо відзначити, як імітованим proxy передається в метод runService() класу ServiceClass. В jMock можна витягти реалізації proxy із створених фіктивних об’єктів, для яких очікувані результати вже були встановлені. Це буде важливо в наступних сценаріях цієї статті, особливо при роботі з RMock.


Сценарій 2: Використання jMock для імітації конкретного класу з конструктором за умовчанням


Припустимо, що метод runService() в класі ServiceClass приймає тільки конкретні реалізації класу Collaborator. Чи буде достатньо jMock для перевірки того, що попередній тест виконався успішно без зміни очікуваних результатів? Так, оскільки ви можете створити клас Collaborator просто за умовчанням.


Змініть метод runService() в класі ServiceClass, Як показано нижче.


Лістинг 4. Змінений клас ServiceClass для сценарію 2





public class ServiceClass {
public ServiceClass(){ / / Конструктор без аргументів
}
public boolean runService(Collaborator collaborator){
if(“success”.equals(collaborator.executeJob())){
return true;
}
else{
return false;
}
}
}

Логічне розгалуження if…else класу ServiceClass залишається без змін (для ясності). Конструктор без аргументів також все ще на місці. Зверніть увагу на те, що не завжди є необхідність в таких логічних конструкціях, як цикли while…do або for, Для відповідного тестування методів класу. Оскільки є виконання методів об’єктів, використовуваних класом, досить простих очікуваних результатів імітації для тестування цих виконань.


Необхідно також змінити клас ServiceClassTest для даного сценарію, як показано нижче.


Лістинг 5. Змінений клас ServiceClassTest для сценарію 2






private ServiceClass serviceClass;
private Mock mockCollaborator;
private Collaborator collaborator;

public void setUp(){
serviceClass = new ServiceClass();
mockCollaborator = mock(Collaborator.class, “mockCollaborator”);
}

public void testRunServiceAndReturnFalse(){
mockCollaborator.expects(once()).method(“executeJob”).will(returnValue(“failure”));
collaborator = (Collaborator)mockCollaborator.proxy();
boolean result = serviceClass.runService(collaborator);
assertFalse(result);
}
}


Тут слід відзначити кілька моментів. По-перше, сигнатура методу runService() змінилася. Замість прийому інтерфейсу ICollaborator він приймає тепер реалізацію конкретного класу (класу Collaborator). Це важливо для роботи тестової інтегрованого середовища (приклад по своїй природі є анти-поліморфним, і ми передаємо конкретний клас тільки в цьому прикладі; так не можна робити при об’єктно-орієнтованому підході).


По-друге, змінився спосіб імітації класу Collaborator. CGLIB-бібліотека jMock надає можливість імітувати конкретний клас. Додатковий String-параметр для методу mock() jMock CGLIB використовується в якості ідентифікатора створюваного фіктивного об’єкта. При використанні jMock (і, звичайно ж, RMock) унікальні ідентифікатори необхідні для кожного імітованого об’єкта в одному контрольному прикладі. Це вірно для фіктивних об’єктів, визначених у загальному методі setUp() або в реальному методі test.


По-третє, оригінальні очікувані результати методу test не змінилися. Помилкове твердження все ще необхідно для проходження тесту. Це важливо, оскільки демонструє, що використовуються інтегровані середовища тестування досить гнучкі для того, щоб підлаштуватися під різні вхідні параметри, одночасно забезпечуючи постійні результати тестування. Їх істинні обмеження проявляються, коли вхідні параметри не можна підлаштувати для формування таких же результатів.


Тепер, перезапустіть тест як JUnit-тест. Тест завершується успішно, як показано нижче.


Рисунок 4. Виконання тесту сценарію 2
Рисунок 4. Виконання тесту сценарію 2


Наступний сценарій трохи ускладнюється. Щоб полегшити ситуацію, яка може здатися важкої, використовується інтегрована середа RMock.


Сценарій 3: Використання jMock і RMock для імітації конкретного класу з конструктором не за замовчуванням


Почніть, як і раніше, зі спроби використовувати jMock для імітації об’єкта Collaborator, Тільки на цей раз Collaborator не має конструктора без аргументів за замовчуванням. Зверніть увагу на те, що підтримується очікуваний результат тесту Boolean false.


Також припустимо, що об’єкт Collaborator вимагає рядок і примітивний тип int в якості параметрів, переданих в конструктор. У лістингу 6 показані зміни в об’єкті Collaborator.


Лістинг 6. Змінений клас Collaborator для сценарію 3





public class Collaborator{
private String collaboratorString;
private int collaboratorInt;

public Collaborator(String string, int number){
collaboratorString = string;
collaboratorInt = number;
}
public String executeJob(){
return “success”;
}
}


Конструктор класу Collaborator все ще досить простий. Поля класу встановлюються рівними вхідним параметрам. Інший логіки тут не потрібно, і функція executeJob() залишається такою ж.


Перезапустіть тест з незмінними іншими компонентами прикладу. Результат – фатальна помилка виконання тесту, як показано нижче.


Рисунок 5. Помилка тесту сценарію 3
Рисунок 5. Помилка тесту сценарію 3


Наведений вище тест був виконаний як простий JUnit-тест без покриття коду (code coverage). Ви можете виконати будь-які тести, наведені в цій статті, в інструментальних системах з покриттям коду (наприклад, Cobertura або EclEmma). Однак існують деякі проблеми при виконанні RMock-тестів з покриттям коду всередині Eclipse (див. таблицю 1). Нижче показаний фрагмент коду, що демонструє реальну трасування стека.


Лістинг 7. Трасування стека для невдалого тесту в сценарії 3





…Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:718)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:660)
…..
…..

Причина невдалого виконання полягає в тому, що jMock не може створити життєздатний фіктивний об’єкт з визначення класу, в якому немає конструктора без аргументів. Єдиним способом створення примірника об’єкта Collaborator є надання двох аргументів. Вам тепер доведеться знайти спосіб надання аргументів у процес створення екземпляра фіктивного об’єкта для досягнення аналогічного ефекту. Саме тому використовується RMock.


Коригування невдалого тесту з використанням інтегрованого середовища тестування RMock


Для коригування тесту потрібно зробити кілька змін. Вони можуть здатися значними, але, по суті, це відносно проста робота для використання можливостей обох інтегрованих середовищ в наших цілях.


Першим необхідним зміною є створення тестового класу як RMock TestCase, А не jMock CGLIB TestCase. Мета – можливість більш легкого налаштування фіктивних об’єктів, що належать RMock, в самих тестах, а також (що більш важливо) під час їх обслуговування. Досвід показує, що легше створити і використовувати фіктивні об’єкти з обох інтегрованих середовищ, коли весь об’єкт TestCase, З якого розширюється тестовий клас, належить RMock. Більш того, на перший погляд дещо легше швидко визначити потік (flow) фіктивних об’єктів (потік тут застосовується для опису ситуації, в якій фіктивний об’єкт використовується як параметр або навіть як повертається тип з інших фіктивних об’єктів).


Друга необхідна зміна – створити (як мінімум) масив об’єктів, що містить реальні значення параметрів, переданих в конструктор класу Collaborator. Також можливо (для ясності) включити class-types масив типів, прийнятих конструктором, і передати цей масив, так само як і тільки що описаний масив об’єктів, як параметри для створення примірника фіктивного об’єкта Collaborator.


Третє зміна зачіпає створення одного або декількох очікуваних результатів у фіктивному об’єкті RMock з коректним синтаксисом. І четвертим, останнім необхідним зміною є переклад фіктивного об’єкта RMock зі стану record в стан ready.


Реалізація змін RMock


У лістингу 9 показані остаточні зміни в класі ServiceClassTest. Також показано використання RMock і її функціональності.


Лістинг 9. Коригування класу ServiceClassTest для сценарію 3






import com.agical.rmock.extension.junit.RMockTestCase;
public class ServiceClassTest extends RMockTestCase {
private ServiceClass serviceClass;
private Collaborator collaborator;

public void setUp(){
serviceClass = new ServiceClass();
Object[] objectArray = new Object[]{“exampleString”, 5};
collaborator =
(Collaborator)intercept(Collaborator.class, objectArray, “mockCollaborator”);
}

public void testRunServiceAndReturnFalse(){
collaborator.executeJob();
modify().returnValue(“failure”);
startVerification();
boolean result = serviceClass.runService(collaborator);
assertFalse(result);
}
}


Перш за все, зверніть увагу на те, що очікувані результати тесту не змінилися. Імпорт класу RMockTestCase сповіщає про появу функціональності інтегрованого середовища RMock. Далі тестовий клас розширює RMockTestCase, А не MockObjectTestCase. Пізніше я покажу вам повторне поява MockObjectTestCase в контрольному прикладі, в якому об’єкт TestClass має тип об’єкта RMockTestCase.







 



Альтернатива використання методу intercept ()

Використовуючи RMock, можна застосувати метод intercept() для імітації тільки конкретних класів. Метод RMock mock() можна застосовувати для імітації конкретних класів та інтерфейсів. Використовуйте interface(), Коли потрібно імітувати не багато методів – тільки ті, які дійсно мають значення. Вважайте цей метод поліпшеним методом mock().


У методі setUp() створюється екземпляр масиву об’єктів з реальними значеннями, які потрібні конструктору класу Collaborator. Цей масив передається повністю в метод intercept() RMock, для того щоб допомогти створити екземпляр фіктивного об’єкта. Сигнатура методу аналогічна сигнатурі методу jMock CGLIB mock(), Оскільки обидва методи приймають як аргументи унікальні ідентифікатори фіктивних об’єктів. Необхідно приведення типів класу фіктивного об’єкта в тип Collaborator, Оскільки метод intercept() повертає тип Object.


Усередині самого тестового методу testRunServiceAndReturnFalse() можна побачити трохи більше змін. Викликається метод executeJob() фіктивного об’єкта Collaborator. На цьому етапі фіктивний метод знаходиться в стані record, тобто, ви просто визначаєте виклики методів, які він буде очікувати при виконанні. Відповідно фіктивний об’єкт записує очікувані результати. Наступний рядок – це повідомлення фіктивному об’єкту при появі методу executeJob() повернути строкове значення failure. Отже, використовуючи RMock, ви встановлюєте очікуваний результат простим викликом методу поза фіктивного об’єкта (і передаючи всі параметри, які можуть знадобитися), потім змінюєте цей очікуваний результат для підстроювання всіх повертаються типів відповідним чином.


Нарешті, викликається метод startVerification() RMock для перекладу фіктивного об’єкта Collaborator в стан ready. Фіктивний об’єкт тепер готовий для використання в класі ServiceClass в якості реального об’єкта. Метод абсолютно необхідний і повинен викликатися, для того щоб уникнути помилок ініціалізації тесту.


Тестування змін


Знову перезапустіть ServiceClassTest для отримання остаточного позитивного результату: надані вами під час створення екземпляра фіктивного об’єкта параметри зробили все необхідне. На малюнку 6 показано позитивний зелений колір JUnit.


Малюнок 6. Успішне завершення тесту в сценарії 3 з використанням RMock
Малюнок 6. Успішне завершення тесту в сценарії 3 з використанням RMock


Рядок коду assertFalse(result) представляє такий же очікуваний результат, що і в сценарії 1, а RMock забезпечує успіх виконання тесту, як це раніше робила середу jMock. З багатьох причин це важливо, але більш важливим моментом тут є те, що динамічний (agile) принцип коригування невдалого тесту застосовується без зміни очікуваних результатів тесту. Єдиним розходженням є використання альтернативної інтегрованої середовища.


У наступному сценарії ви будете використовувати обидві середовища jMock і RMock в особливій ситуації. Жодна середу сама по собі не забезпечила б коректного результату. Потрібно буде організувати в тесті певного роду союз обох середовищ.


Сценарій 4: Спільна робота jMock і RMock


Як уже згадувалося, я хотів розглянути ситуацію, в якій дві інтегровані середовища повинні працювати спільно для досягнення певного результату. В іншому випадку правильно сформований тест буде постійно завершуватися невдало. Існує декілька випадків, в яких не має значення, яке середовище використовувати (jMock або RMock), наприклад, коли інтерфейс або клас, який ви хочете імітувати, існує в підписаному JAR-архіві. Це рідкісна ситуація, але вона може виникнути при тестуванні коду, написаного з використанням API для захищених ліцензованих продуктів (зазвичай готове програмне забезпечення якого або роду).


У лістингу 10 показаний приклад, в якому обидві інтегровані середовища працюють в одному контрольному прикладі.


Лістинг 10. Приклад тесту для сценарію 4





public class MyNewClassTest extends RMockTestCase{
private MyNewClass myClass;
private MockObjectTestCase testCase;
private Collaborator collaborator;
private Mock mockClassB;
public void setUp(){
myClass = new MyNewClass();
testCase = new MyMockObjectTestCase();
mockClassB = testCase.mock(ClassB.class, “mockClassB”);
mockClassB.expects(testCase.once()).method(“wierdMethod”).
will(testCase.returnValue(“passed”));
Class[] someClassArray = new Class[]{String.class, ClassA.class, ClassB.class};
Object[] someObjectArray = new Object[]
{“someArbitraryString”, new ClassA(), (ClassB)mockClassB.proxy()};
collaborator = (Collaborator)intercept
(Collaborator.class, someClassArray, someObjectArray, “mockCollaborator”);
}
public void testRMockAndJMockInCollaboration(){
startVerification();
assertTrue(myClass.executeJob(collaborator));
}
private class MyMockObjectTestCase extends MockObjectTestCase{}
private class MyNewClass{
public boolean executeJob(Collaborator collaborator){
collaborator.executeSomeImportantFunction();
return true;
}
}
}

У методі setUp() створюється екземпляр нового “testcase” на основі private inner класу, створеного для розширення об’єкта jMock-CGLIB MockObjectTestCase. Ця невелика додаткова робота необхідна для зберігання всього тестового класу як об’єкта RMock TestCase, Одночасно володіє всією функціональністю jMock. Наприклад, ви встановите очікувані результати jMock як testCase.once(), А не як once(), Оскільки об’єкт TestClass розширює RMockTestCase.


Створюється фіктивний об’єкт, заснований на класі ClassB і надає очікуваний результат. Потім ви використовуєте його для допомоги у створенні екземпляра фіктивного об’єкта RMock Collaborator. Тестованим класом є MyNewClass (Показаний тут як private inner клас). Знову ж, його метод executeJob() приймає об’єкт Collaborator і виконує метод executeSomeImportantFunction().


У лістингах 11 і 12 показаний код ClassA і ClassB відповідно. ClassA – Це простий клас без реалізації, в той час як ClassB демонструє мінімум деталей, що ілюструють ситуацію.


Лістинг 11. Клас ClassA





public class ClassA{}

Цей клас є просто фіктивними (dummy) класом, який я використовую, щоб підкреслити необхідність RMock для імітують класів, конструктори яких беруть об’єктні параметри.


Лістинг 12. Клас ClassB





public class ClassB{
public ClassB(){}
public String wierdMethod(){
return “failed”;
}
}

Метод wierdMethod класу ClassB повертає failed. Це важливо, оскільки клас повинен повертати інший рядок для успішного проходження тесту.


У лістингу 13 показаний найбільш важливий фрагмент прикладу тесту – клас Collaborator.


Лістинг 13. Клас Collaborator





public class Collaborator {
private String _string;
private ClassA _classA;
private ClassB _classB;
public Collaborator(String string, ClassA classA, ClassB classB) throws Exception{
_string = string;
_classA = classA;
if(classB.wierdMethod().equals(“passed”)){
_classB =classB;
}
else{
throw new Exception(“Something bad happened”);
}
}
public void executeSomeImportantFunction(){
}
}

По-перше, зверніть увагу на те, що ви імітували клас ClassB, Використовуючи інтегровану середу jMock. В RMock не існує реального способу отримати і використовувати proxy з фіктивного об’єкта для застосування де-небудь в тестовому методі setUp(). В RMock proxy-об’єкт з’являється тільки після виклику методу startVerification(). Перевага тут на боці jMock, оскільки ви можете отримати все, що треба, для налаштування інших фіктивних об’єктів, коли вони повинні повернути об’єкти, які самі є фіктивними.


По-друге, зверніть увагу на те, що, з іншого боку, ви не могли б використовувати інтегровану середу jMock для імітації класу Collaborator. Причина полягає в тому, що цей клас не має конструктора без аргументів. Більш того, в його конструкторі є певна логіка, яка визначає, чи може, перш за все, бути отриманий примірник класу. Фактично для наших цілей метод wierdMethod() В ClassB повинен повертати passed для створення екземпляра об’єкта Collaborator. Однак зверніть увагу на те, що за замовчуванням метод завжди повертає failed. Існує очевидна необхідність імітувати ClassB для успішного виконання тесту.


Також, на відміну від попередніх прикладів, масив класів в даному сценарії включений як додатковий параметр методу intercept(). Це не є гострою необхідністю, але він служить ключем для швидкої ідентифікації використовуваних вами об’єктних класів при створенні екземпляра тестового об’єкта RMock.


Виконайте новий контрольний приклад. На цей раз результати будуть успішними. Малюнок 7 демонструє щасливе завершення.


Малюнок 7. Успішне виконання тесту для сценарію 4 з використанням спільної роботи RMock і jMock
Малюнок 7. Успішне виконання тесту для сценарію 4 з використанням спільної роботи RMock і jMock


Фіктивний об’єкт Collaborator налаштований коректно і виконання об’єкта mockClassB приносить очікуваний результат.


Короткий огляд відмінностей інструментальних засобів тестування


Як можна помітити, в розглянутих сценаріях обидві середовища (jMock і RMock) є потужними інструментами для тестування Java-коду. Однак завжди існують обмеження у разі використання інших інструментальних програм, які використовуються в процесі розробки і тестування. Крім того, доступні інші програми тестування, але жодна з них не працює так добре (в Java-технології), як RMock і jMock. Мій особистий досвід показав, що інтегрована середа Microsoft. NET теж має деякі потужні інструменти (наприклад, TypeMock), але її розгляд виходить за рамки цієї статті і, більше того, платформи.


У таблиці 1 наведені деякі відмінності двох інтегрованих середовищ і можливі проблеми, що виникають час від часу, зокрема в середовищі Eclipse.


Таблиця 1. Відмінності між інтегрованими середовищами тестування RMock і jMock





























Стиль імітації тесту


jMock


RMock

Можна імітувати інтерфейси

Так: Новий метод Mock()  Так: Метод mock() 

Можна імітувати конкретні класи

Так: Метод mock() з CGLIB Так: Метод mock() або intercept ()

Можна імітувати будь-який конкретний клас

Ні: Повинен бути присутнім конструктор без аргументів Та

Можна отримати проксі в будь-який час

Та Ні: Тільки після стану ready startVerification() 

Проблеми з іншими модулями Eclipse

Ні: Не виявлено проблем Так: Конфлікти оперативної пам’яті з підключається модулем CoverClipse для Eclipse


Резюме


Я закликаю вас використовувати ці інтегровані середовища через їх потужних можливостей щодо формування результатів модульного тестування. У своїй більшості Java-розробники не звикли писати тести. Якщо тести і пишуться, то найчастіше вони є дуже простими, що охоплюють основну функціональну мета методу. Для тестування деяких “важкодоступних” секцій коду середовища jMock і RMock є відмінним вибором.


Їх використання значно зменшує кількість помилок в коді і удосконалює ваші навички у використанні перевірених методів тестування програмної логіки. Також у нагоді вашій майстерності розробника (зменшує вашу можливу толерантність до невдало спроектованому коду) буде читання документації і експерименти з вдосконаленими версіями цих та інших інтегрованих середовищ.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*