Я уже несколько недель пишу модульные тесты для программного обеспечения, и сейчас у меня возникают некоторые сомнения относительно конструкции моего UT, их надежности и удобства обслуживания.
Я написание моего UT для кода в Java с JUnit и EasyMock, потому что некоторые объекты, вызываемые и используемые в функциях, имеют большой уровень сложности.
Вот мои проблемы:
- У меня такое ощущение, что мой тест - это просто копия функций, которые я тестирую, в основном потому, что я использую макеты, которые необходимо настроить в соответствии с алгоритмами
- Мои тесты довольно повторяющиеся потому что, когда я начал работать над тестами, я не учитывал части настройки mocks, которые я использовал в нескольких тестах, но также потому, что я настраивал различные параметры и mocks для каждого теста моего UT (например, Я тестирую функцию foo (A, B, C), и я нашел 5 тестовых примеров, которые интересны для этой функции, мне нужно настроить 15 mocks)
I ' м а Учитывая, что факторизация и повторное использование макетов для каждого теста UT являются хорошим решением для решения этих проблем, и я написал некоторые из них с помощью этих методологий, но я чувствую, что это приводит к снижению в надежности и удобочитаемости UT.
Есть ли у вас какие-либо l aws или советы, которые вы пытаетесь учитывать при написании UT, которые могут оказаться эффективными для решения этих проблем.
Редактировать
Для пояснения приведем несколько примеров кода:
public class functionsToTest{
public static int getProperQuantity(Object A){
int returnValue = 0;
if(A != null && A.getQuantity() != null && A.getQuantity() > 0){
returnValue = A.getQuantity();
}
return returnValue;
}
}
Вот класс, который я хочу проверить с помощью UT. Объект A является сложным объектом / объектом, созданным с использованием данных из БД, поэтому я должен смоделировать его, чтобы написать свой UT. Я должен написать мои тесты UT:
1 / Создать макеты и настроить их для каждого теста
public void myTest(){
int expectedValue = 0;
int output = 0;
/** Setting up the mocks **/
// Case 1 : A is null
// Case 2 : A.getQuantity() is null
Object A_case2 = createMock(A.class);
EasyMock.expect(A_case2.getQuantity()).andReturn(null).anyTimes();
// Case 3 : A.getQuantity() is negative
Object A_case3 = createMock(A.class);
EasyMock.expect(A_case3.getQuantity()).andReturn(-1).anyTimes();
// Case 4 : nominal case
Object A_case4 = createMock(A.class);
EasyMock.expect(A_case4.getQuantity()).andReturn(5).anyTimes();
// End Set Up
EasyMock.replay(A_case2, A_case3, A_case4);
/** Executing the tests **/
// Case 1 : A is null
expectedValue = 0;
output = functionsToTest.getProperQuantity(null);
assertEquals(expectedValue, output);
// Case 2 : A.getQuantity() is null
expectedValue = 0;
output = functionsToTest.getProperQuantity(A_case2);
assertEquals(expectedValue, output);
// Case 3 : A.getQuantity() is negative
expectedValue = 0;
output = functionsToTest.getProperQuantity(A_case3);
assertEquals(expectedValue, output);
// Case 4 : nominal case
expectedValue = 5;
output = functionsToTest.getProperQuantity(A_case4);
assertEquals(expectedValue, output);
}
Если найти это решение достаточно надежным и гибкий, потому что, если функция getProperQuantity изменится в будущем, ее довольно просто изменить. Плюс, это читабельно. Основным недостатком является длина (в моем случае настройки макетов намного длиннее, тестовых случаев гораздо больше, а класс, который я тестирую, имеет 130 функций), тот факт, что он избыточен, и что он явно следует функции, которую я тестирую.
2 / Создать набор макетов для всего модульного теста
public void myTest(){
int expectedValue = 0;
int output = 0;
/** Setting up the mocks **/
Object A_default = createMock(A.class);
// Case 1 : A is null
// Case 2 : A.getQuantity() is null
EasyMock.expect(A_default.getQuantity()).andReturn(null).times(1);
// Case 3 : A.getQuantity() is negative
EasyMock.expect(A_default.getQuantity()).andReturn(-1).times(2);
// Case 4 : nominal case
EasyMock.expect(A_default.getQuantity()).andReturn(5).times(3);
// End Set Up
EasyMock.replay(A_default);
/** Executing the tests **/
// Case 1 : A is null
expectedValue = 0;
output = functionsToTest.getProperQuantity(null);
assertEquals(expectedValue, output);
// Case 2 : A.getQuantity() is null
expectedValue = 0;
output = functionsToTest.getProperQuantity(A_default);
assertEquals(expectedValue, output);
// Case 3 : A.getQuantity() is negative
expectedValue = 0;
output = functionsToTest.getProperQuantity(A_default);
assertEquals(expectedValue, output);
// Case 4 : nominal case
expectedValue = 5;
output = functionsToTest.getProperQuantity(A_default);
assertEquals(expectedValue, output);
}
Это решение намного короче, проще и Это тоже вполне читабельно, но у меня такое ощущение, что в надежности и гибкости огромные потери: если функция, которую я тестирую, изменится (даже немного), все тесты завершатся сбоем, и их нужно будет полностью переделать. Кроме того, здесь также следует код, который он должен проверить.