Почему модульное тестирование важно для разработчиков?

Источник: SearchSoftwareQuality Давайте обсудим, почему модульное тестирование важно и ценно, а также как оно облегчает процесс отладки. Модульное тестирование — мощный инструмент для повышения качества программного обеспечения. Модульные тесты обеспечивают фундаментальную проверку того, что приложение соответствует спецификациям программного обеспечения и ведет себя так, как задумано. Кофе-брейк #87. Почему модульное тестирование важно для разработчиков? 5 способов скопировать массив в Java - 1Когда все сделано хорошо, модульные тесты:
  • уменьшают количество дефектов и выявляют их на ранних этапах жизненного цикла разработки;
  • улучшают читаемость кода;
  • допускают повторное использование кода;
  • повышают скорость развертывания.
Давайте разберемся, почему модульное тестирование важно, как возник этот тип тестирования и какие существуют препятствия на пути его внедрения.

История модульного тестирования

Ошибка, обнаруженная на ранней стадии, — это экономия времени и усилий. В течение первых 50 лет истории компьютеров модульное тестирование и отладка были по сути одним и тем же. Но к 1990-м годам код стал настолько сложным, что часто было невозможно разделить систему на мелкие части для их изолированного запуска. В 1997 году программист по имени Кент Бек создал JUnit — плагин среды разработки для тестирования небольших фрагментов кода. Тестовый код, оценивающий исходный код, назвали модульными тестами. Эта разновидность модульного тестирования стала основной на долгие годы. После того, как Бек создал JUnit, Мартин Фаулер написал книгу “Рефакторинг”, в которой предложил способы преобразования кода, чтобы сделать его более изолированным и тестируемым. Комбинация рефакторинга кода и модульного тестирования привела к разработке, основанной на тестировании, где создание модульных тестов имеет важное значение для процесса программирования. В ней код должен быть тестируемым еще до своего создания. Таким образом, процесс программирования не завершается до запуска модульных тестов. Затем проект может перейти к стадии исследования на системном или человеческом уровне.

Пример модульного тестирования

Этот пример демонстрирует важность модульного тестирования. Здесь JUnit оценивает простую функцию, которая преобразует температуру из Фаренгейта в Цельсий. Формула преобразования: C = (F-32) * 5/9. Всего несколько строк, включая сигнатуру функции и фигурные скобки, можно реализовать в коде как библиотечную функцию. Однако из функции не ясно, что это критерии. Эти параметры могут включать в себя округление значений в большую или меньшую сторону, действительные числа или верхний и нижний пределы. Давайте создадим примеры модульных тестов для этой функции преобразования температуры в Perl, используя модуль Test :: More. Первая строка — это комментарий, который сообщает программисту, чего ожидать от оставшегося кода.

# is (input, expected result, comment)
is( FtoC(32),0,'Freezing point is F32, C 0');
is( FtoC(212),100,'Boiling point is F212, C 100');
is( FtoC(59038),32767, 'Upper limit of C is 32767'); 
is( FtoC(59039),undefined, 'One past upper limit is error');
Фреймворк JUnit опирается на объектно-ориентированные системы и объекты тестирования, но концепция аналогична.

Изолированные модульные тесты

Одно из преимуществ модульных тестов заключается в том, что они изолируют функцию, класс или метод и тестируют только этот фрагмент кода. Более качественные отдельные компоненты обеспечивают общую отказоустойчивость системы. Таким образом, получается надежный код. Модульные тесты также меняют характер процесса отладки. Чтобы попытаться исправить ошибку, программисты просто пишут неудачный тест, а затем повторяют его, чтобы он прошел, не нарушая предыдущие ожидания. Этот процесс исключает ручной цикл традиционной отладки с помощью настройки, повторного создания, приостановки и проверки. Для изменения кода, чтобы сделать его пригодным для модульного тестирования, программисты должны изменить процесс своей работы. Любые фрагменты кода, написанные без модульных тестов, скорее всего, будут считаться непроверенными, по крайней мере, как отдельные модули.

Адаптация модульных тестов

Устаревшее (Legacy) программное обеспечение — это софт, который работает в течение длительного времени и, скорее всего, написан без модульных тестов. Legacy-код имеет ценность для компании. Он стабильно работает долгие годы. Некоторые программы, созданные без использования модульных тестов, обрабатывают транзакции на миллион долларов в день. Но код, в котором нет модульных тестов, со временем превращается в большой комок грязи, поскольку в течение многих лет к нему прикасались многие программисты, занимающиеся обслуживанием кода. Рефакторинг позволяет программистам постепенно вносить в систему изменения, чтобы сделать ее тестируемой. Однако эти изменения требуют времени. Несколько лет назад я обсуждал со своим коллегой Бобом Реселманом вопрос об использовании модульных тестов для устаревших приложений. Реселман утверждал, что внедрять модульное тестирование в приложения, созданные без них, слишком дорого и даже глупо. Вместо этого он рекомендовал организации начать новую разработку с модульных тестов и оставить устаревшие приложения в покое. Возможно, это верно для COBOL, генераторов программ отчетов и других приложений, но я утверждаю, что в приложения, написанные на современных языках — C ++, C #, Java и Ruby — добавлять модульные тесты задним числом довольно просто. Вместо того, чтобы писать их для всего приложения, просто добавьте модульные тесты к текущему изменению и выполняйте рефакторинг по мере продвижения.

Повышение скорости, качества и тестируемости

Руководители проектов говорят, что планирование предполагает компромисс между качеством, объемом выполненной работы, ресурсами и временем. Чтобы добавить что-то к одной области, вы должны отнять что-то от другой. Эффективные модульные тесты нарушают это правило. Вот почему модульное тестирование важно и ценно для организаций. Хорошие модульные тесты создают тестируемый код, который улучшает качество. В этом коде будет меньше дефектов, а значит, меньше исправлений ошибок для более быстрого завершения проекта. Когда в программном обеспечении возникают ошибки, модульные тесты ускоряют отладку, исправление и написание кода. И это происходит таким образом, что вероятность повторения дефекта значительно снижается — одновременно улучшается качество и скорость кода. Хотя в разработке программного обеспечения нет волшебной палочки, эффективные модульные тесты могут ускорить разработку, тестирование и даже часть разработки функциональных требований.

5 способов скопировать массив в Java

Источник: Dev.to Итак, у вас есть два массива A и B и вам нужно скопировать элементы из A в B. Что ж, есть разные способы сделать это на Java, и сейчас я вам их покажу.

Метод первый: ForLoop

Здесь нам на помощь приходит старый-добрый цикл for:

int[] A = {1,2,4,4};
int[] B = new int[];

 for (int i = 0; i < A.length; i++){
      B[i] = A[i];
}

Метод второй: .clone()

Метод клонирования массива также может помочь добиться желаемого результата:

int[] A = {1,2,4,4};
int[] B = A.clone();//the clone method copies the content of A into B;

Метод третий: System.arraycopy()

Следующий способ — использование метода System.arraycopy(), который есть в пакете java.lang. Прежде чем мы перейдем к его применению, давайте обсудим его подпись:

public static void arraycopy(
    Object src, //:source array, in this case A
    int srcPos, //:the start index for copy, typically 0
    Object dest, //:destination object in this case B. 
    int destPos, //:the index to place the copied elements
    int length //:the length of the contents to be copied
);
Применение:

int[] A = {1,2,4,4};
int[] B = new int[];

System.arraycopy(A, 0, B, 0, A.length);

Метод четвертый: Arrays.copyOf()

Следующий вариант копирования, который мы обсудим, относится к классу Arrays из пакета java.utils. Обратите внимание на его подпись:

public static int[] copyOf( 
    int[] original, // :source array in this case A
    int newLength // :the length of the contents to be copied
);
Применение:

int[] A = {1,2,4,4};
int[] B = Arrays.copyOf(A, 3);

Метод пятый: Arrays.copyOfRange()

Итак, это будет последний вариант, на который мы обратим внимание в этой публикации. Он тоже из класса Arrays, присутствующего в пакете java.utils. Еще раз посмотрим его подпись:

public static int[] copyOfRange​(
    int[] original, // :source array in this case A
    int from,  //:the start index for copy, typically 0
    int to // the end index exclusive
);
Применение:

int[] A = {1,2,3,4,5,6,7};
int[] B = Arrays.copyOfRange(A, 0, A.length);