В этой серии статей мы рассмотрели множество новых функций. Некоторыми, если ими воспользуешься сразу. Остальные биты вы подождете.
В любом случае, при обновлении до 12.2 вы захотите протестировать весь свой код, чтобы убедиться, что он работает должным образом. Отсюда возникает вопрос:
«Какая часть моего кода действительно выполнялась при тестировании?»
Показатели охвата очень помогут в этом.
Простого анализа тестов на уровне строк недостаточно. Чтобы понять, почему, рассмотрим следующий код:
У нас есть базовая функция, которая возвращает свой аргумент и вызывает dbms_output.
Процедура вызывает функцию дважды в одном операторе if:
create or replace function f (p int) return int as begin dbms_output.put_line('Executed: ' || p); return p; end; / create or replace procedure p is begin if f(1) = 1 or f(2) = 2 then dbms_output.put_line('this'); else dbms_output.put_line('that'); end if; end p; /
Из-за оценки короткого замыкания f (2) никогда не выполняется! Вы можете увидеть это на выходе:
SQL> exec p; Executed: 1 this
Все, что работает на линейном уровне, будет неправильно сообщать об этом как о полном покрытии.
Чтобы преодолеть это, вам нужно подробно изучить выполнение «базового блока».
Так что же такое «базовый блок»?
Это фрагмент кода, который вы либо выполняете полностью, либо не выполняете совсем. Код всегда принадлежит ровно одному базовому блоку. Например:
if f(1) = 1 or f(2) = 2 then dbms_output.put_line('this'); else dbms_output.put_line('that'); end if;
имеет четыре основных блока. Один для каждого вызова f и два для вызовов dbms_output.put_line.
Новая функция покрытия кода измеряет эти базовые блоки и сообщает о них.
Пользоваться им просто. Для начала нужно создать таблицы покрытия для хранения метрик:
exec dbms_plsql_code_coverage.create_coverage_tables;
Затем вызовите start_coverage перед тестом и stop_coverage после:
declare run_id pls_integer; begin run_id := dbms_plsql_code_coverage.start_coverage('TEST'); p; dbms_plsql_code_coverage.stop_coverage; end; /
Затем вы можете получить метрики, запросив таблицы dbmspcc *, которые содержат эти данные:
select owner, name, type, round( ( sum(covered)/count(*) * 100), 2) pct_covered from dbmspcc_runs r join dbmspcc_units u on r.run_id = u.run_id join dbmspcc_blocks b on r.run_id = b.run_id and u.object_id = b.object_id where r.run_comment = 'TEST' group by owner, name, type; OWNER NAME TYPE PCT_COVERED ----- ----- ---------- ----------- CHRIS P PROCEDURE 50 CHRIS F FUNCTION 100
Это все хорошо. Но всегда есть код, который не покрывают ваши тесты. Возможно, он устарел, поэтому вам не нужно его тестировать. Или это код «на всякий случай», охватывающий теоретически возможные, но практически невозможные случаи. Например, печально известный обработчик исключений «когда другие».
Вы хотите исключить эти разделы из своих отчетов. К счастью, вы можете это сделать с помощью прагмы покрытия. Отметив строки как «NOT_FEASIBLE», вы можете отфильтровать их из своих отчетов:
create or replace procedure p is begin if f(1) = 1 or f(2) = 2 then dbms_output.put_line('this'); else pragma coverage ('NOT_FEASIBLE'); dbms_output.put_line('that'); end if; end p; /
Перезапустите тесты, и вы сможете скрыть непроверяемые части в своем отчете!
select owner, name, type, round( ( sum(covered)/count(*) * 100), 2) pct_covered from dbmspcc_runs r join dbmspcc_units u on r.run_id = u.run_id join dbmspcc_blocks b on r.run_id = b.run_id and u.object_id = b.object_id where r.run_comment = 'TEST' and b.not_feasible = 0 group by owner, name, type; OWNER NAME TYPE PCT_COVERAGE ----- ---- --------- ------------ CHRIS P PROCEDURE 66.67 CHRIS F FUNCTION 100
Если вы действительно хотите, вы можете исключить целые разделы кода, заключив его в две прагмы покрытия. Первый стартовый NOT_FEASIBLE_START, второй NOT_FEASIBLE_END:
begin S pragma coverage ('NOT_FEASIBLE_START'); a_section(); of_untestable_code(); pragma coverage ('NOT_FEASIBLE_END'); end; /
Полная статья изначально опубликована на сайте blogs.oracle.com 10 ноября 2016 г.