Верификация программного обеспечения

Документация, сопровождающая процесс верификации и тестирования (отчеты)

Разбить на страницы
Показывать лекцию целиком

13.1. Отчеты о покрытии программного кода

13.1.1. Технологические цепочки и роли участников проекта, использующих отчеты о покрытии. Связь отчетов о покрытии с другими типами проектной документации

Степень покрытия программного кода тестами - важный количественный показатель, позволяющий оценить качество системы тестов, а в некоторых случаях - и качество тестируемой программной системы. Данные о степени покрытия помещаются в отчеты о покрытии, которые генерируются при выполнении тестов инструментальными средствами, поддерживающими процесс тестирования, т.е. по сути, генерируются средой тестирования (Рис 13.1). Формат отчетов о покрытии обычно единый внутри проекта или нескольких проектов и часто зависит от особенностей инструментальных средств тестирования.

В отчете о покрытии в стандартизированной форме указываются участки программного кода тестируемой системы (или ее части), которые не были выполнены во время выполнения тестовых примеров, т.е. не были покрыты тестами. Причины непокрытия анализируются тестировщиками, по результатам анализа составляются отчеты о проблемах и запросы на изменение - документы, где описываются объекты разработки, которые необходимо изменить, и причины этих изменений.

(рис 13.1) Генерация отчета о покрытии и изменения по результатам его анализа

Недостаточное покрытие может свидетельствовать о неполноте системы тестов или тест-требований, в этом случае в запросе об изменении указывается на необходимость расширения системы тестов или тест-требований. Другой причиной недостаточного покрытия могут быть участки защитного кода, которые никогда не выполнятся даже в случае нештатной работы системы. В этом случае в запросе на изменения указывается на необходимость модификации исходных текстов либо отмечается, что для этого участка программной системы не требуется покрытие. В качестве третьей причины недостаточного покрытия может выступать рассогласование требований и программного кода системы, в результате которого в коде могут остаться неиспользуемые более участки либо, наоборот, появиться участки, рассчитанные на будущее (и реализующие функциональность, не описанную в требованиях). В этом случае в запросе на изменение указывается на необходимость модификации требований и/или кода системы для приведения их в согласованное состояние.

13.1.2. Возможные формы отчетов о покрытии

Типичный отчет о покрытии представляет собой список структурных элементов покрываемого программного кода (функций или методов), содержащий для каждого структурного элемента следующую информацию:

  • Название функции или метода
  • Тип покрытия (по строкам, по ветвям, MC/DC или иной)
  • Количество покрываемых элементов в функции или методе (строк, ветвей, логических условий)
  • Степень покрытия функции или метода (в процентах или в абсолютном выражении)
  • Список непокрытых элементов (в виде участков непокрытого программного кода с номерами строк)
  • Кроме того, отчет о покрытии содержит заголовочную информацию, позволяющую идентифицировать отчет, и общий итог - общую степень покрытия всех функций, для которых собирается информация о покрытии.

    Пример такого отчета о покрытии приведен ниже.

    Coverage Report
    Generated 10/07/2006 for file Testing_Facilities.cpp
    ----------------------------------------------------
    1) function main_Menu()
    Coverage: Instructions
    Elements: 25 structured lines of code (SLOCs)
    Covered: 22 lines (88%)
    Not covered:
       291 default:
       292 return -1;
       293 break;
    
    Coverage: Branches
    Elements: 5 branches
    Covered: 4 branches (80%)
    Not covered (starting and ending lines only):
    default:
    break;
    
    ----------------------------------------------------
    2) function item_Help()
    Coverage: Instructions
    Elements: 180 structured lines of code (SLOCs)
    Covered: 180 lines (100%)
    
    Coverage: Branches
    Elements: 2 branches
    Covered: 2 branches (80%)
    ----------------------------------------------------
    Total functions: 2
    Total instructions coverage: 98.5%
    Total branches coverage: 86%

    Отчет о покрытии может создаваться либо для всех функций программного модуля или всего проекта, либо выборочно для определенных функций.

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

    Пример такого отчета приведен ниже:

    Зеленым цветом отмечены выполненные в результате тестирования участки метода, красным - не выполненные.

    Конкретная форма отчета о покрытии определяется инструментарием и технологическими процессами проекта.

    Рассмотрим, например, отчет о структурном покрытии, генерируемый при помощи средства для анализа программного кода CodeTEST компании Metrowerks.

    Сбор покрытия производится по определенному уровню покрытия, информация об этом входит в состав заголовка отчета о покрытии. В данном случае програмный код покрывался по MC/DC.

    CodeTEST Advanced Coverage Tools
    Modified Condition Decision Coverage Report (MCDC), DO-178B Level A
    CodeTEST Report Generator 2.2.04
    Report generated on Sun Aug 21 14:28:16 2005
    
    IDB File:
        <Path_to_IDB_file>
        42963330-1C0 Thu May 26 21:36:00 2005

    Далее выводится информация о проценте покрытия по всем модулям в совокупности (в данном случае, это 33 модуля):

    Overall Summary (MCDC): 33 Files
     1405 true-false decisions
          674  48.0%  covered
          494  35.2%  partially covered
          237  16.9%  not covered
     1928 conditions in the decisions
         1068  55.4%  covered
          571  29.6%  partially covered
          289  15.0%  not covered
      278 case branches
          154  55.4%  covered
          124  44.6%  not covered
      581 coverage events
          504  86.7%  covered
           77  13.3%  not covered

    Рассмотрим более подробно каждую из характеристик.

    True-false decisions - количество логических выражений, в данном случае их 1405. Из этого числа на оба возможных значения ( True и False ) покрыто лишь 674, еще 494 покрыто на какое-то одно из значений, а 237 не покрыто вообще.

    Conditions in the decisions - количество логических условий внутри логических выражений. Как можно догадаться, их количество не может быть меньше количества логических выражений. Непокрытие логических условий явным образом влечет за собой непокрытие логических выражений. Факт, что если все условия будут покрыты, то все выражения также будут покрыты.

    Case branches - количество веток ветвления операторов выбора ( select ). Ветка считается покрытой, если выражение, стоящее в условии оператора select, принимает значение, соответствующее данному варианту выбора ( case ), в результате чего ветка выполняется.

    Coverage events - в данном случае, это количество точек входа / выхода в функциях. Точка входа в функцию считается покрытой, если эта функция была вызвана хотя бы один раз. Точками выхода являются точка окончания функции ( } ), когда управление передается в место вызова этой функции, а также операторы возврата ( return ), после выполнения которых управление также передается в место вызова функции.

    Затем выводится информация для первого модуля, а именно: имя модуля, путь к файлу на диске, дата последнего изменения, контрольная сумма. После этого выводится суммарная информация о покрытии только для этого модуля (для всех его функций, количество которых также указывается). Структура этой информации аналогична структуре, описанной выше:

    1. File <Module_1_name.cpp> in <Path_to_module_1>
        Last Modified: Fri Oct 15 18:34:14 2004
        Checksum: CEDBAB67
    
        File Summary (Extended MCDC): 6 Functions
           24 true-false decisions
               10  41.7%  covered
               11  45.8%  partially covered
                3  12.5%  not covered
           39 conditions in the decisions
               20  51.3%  covered
               15  38.5%  partially covered
                4  10.3%  not covered
            0 case branches
           12 coverage events
               12 100.0%  covered
                0   0.0%  not covered

    После этого происходит поочередный вывод суммарной информации для каждой из функций в отдельности и также всех ключевых участков функции, влияющих на покрытие, а именно: точки входа / выхода, логические выражения, логические условия, операторы выбора. При этом для каждого из этих ключевых участков выводится информация о степени покрытия, где возможными значениями могут быть:

    COVERED - участок полностью покрыт в понятиях типа, к которому он приписан;

    PARTIALLY covered - участок частично покрыт. Применимо только к логическим выражениям и условиям и указывает на то, что выражение (условие) покрыто на какое-то одно из двух возможных значений;

    NOT covered - участок не покрыт. Это означает, что данный участок не выполнялся в процессе работы скомпилированного программного кода.

    Ниже представлен типичный результат покрытия для функции.

    1.1 Function <Function_1>
            void Function_1(void)
    
            Function Summary (MCDC):
                3 true-false decisions
                    0   0.0%  covered
                    2  66.7%  partially covered
                    1  33.3%  not covered
                5 conditions in the decisions
                    1  20.0%  covered
                    3  60.0%  partially covered
                    1  20.0%  not covered
                0 case branches
                2 coverage events
                    2 100.0%  covered
                    0   0.0%  not covered
    
            coverage line 266: function entry
                COVERED
    
            decision line 267: if statement
                if ((A == B)  (...
    
                 T     F
             1: *ttt  *fxx  ((A == ...)    COVERED
             2: *ttt   tfx  ((C...)        PARTIALLY covered
             3: *ttt   ttf  ((D == 0)        PARTIALLY covered
    
            decision line 271: if statement
                if (E <= 0)
    
                 T   F
             1:  t  *f  (E <= 0)   PARTIALLY covered
    
            decision line 276: if statement
                if (D == 0)
    
                 T   F
             1:  t   f  (D...)   NOT covered
    
            coverage line 291: function end
                }
                COVERED

    Следует обратить внимание на то, каким образом происходит разбор логических выражений. Предположим, что у нас имеется выражение вида:

    if ((A==B)  (C > 0)  (D == 0))

    и пусть результат покрытия для него такой, как приведен выше ( decision line 267: if statement ). Для этого выражения строится таблица, где в каждой строке помещается информация для каждого из логических условий, входящих в это логическое выражение. Нумерация логических условий начинается с 1, в нашем случае их 3.

    В первом столбце указывается комбинация значений логических условий (с участием рассматриваемого условия), которую необходимо выставить, чтобы логическое выражение приняло значение True. В данном случае, так как все условия соединены логическим оператором "И" ( ), такой комбинацией может быть только TTT. Если указанная комбинация была сформирована в процессе тестирования программы, то она помечается символом ( * ).

    Во втором столбце указывается комбинация значений логических условий (с участием рассматриваемого условия), которую необходимо выставить, чтобы логическое выражение приняло значение False. В данном случае достаточно, чтобы хотя бы одно условие приняло значение False, при этом значения всех последующих условий не учитываются (это отображается символом X ).

    Третий столбец - это вырезка текста логического условия, позволяющая легче ориентироваться в коде при анализе покрытия.

    Из получившейся таблицы видно, что второе и третье логическое условие в процессе выполнения не принимали значения False. Определение причины этого и является задачей анализа структурного покрытия.

    После того, как в рамках данного модуля будут рассмотрены все функции, рассматривается следующий модуль, и так далее. Мы видим, что структура отчетного файла, получаемого в результате работы CodeTEST, достаточно проста и имеет вложенную структуру.

    Отчеты о покрытиях, создаваемые Microsoft Visual Studio Team Edition, будут рассмотрены на семинарских занятиях.

    13.1.3. Покрытие на уровне исходных текстов и на уровне машинных кодов

    В некоторых случаях инструментальные средства сбора покрытия анализируют покрытие программного кода тестами не на уровне исходных текстов системы, а на уровне машинных инструкций. В этом случае степень покрытия зависит и от того, какой исполняемый код генерируется компилятором. Отчеты о покрытии в этом случае выглядят следующим образом (отчет о покрытии сгененирован при помощи отладчика Microtec XRAY для Motorola 680x0):

    ******* INSTRUCTION EXECUTION COVERAGE - Analyze Unit: Menu_Display
    Function: DATA_PROCESSING\Menu_Display.  Instruction(s) not executed:
      5668             switch (Key) 
    0004A0F6 0352              BCHG    D1,(A2)                            
    0004A102 0466 0466         SUBI.W  #$466,-(A6)
    0004A106 0466 0466         SUBI.W  #$466,-(A6)
    0004A10A 0466 0466         SUBI.W  #$466,-(A6)
    0004A10E 0466 0466         SUBI.W  #$466,-(A6)
    0004A112 0466 0466         SUBI.W  #$466,-(A6)
    0004A116 0466 0474         SUBI.W  #$474,-(A6)
      5751                       i = 1; 
    0004A4A6 7401              MOVEQ   #$1,D2
       Executed     Total   Percent  Analyze-unit
            467       475     98.32  DATA_PROCESSING\Menu_Display
                    0 unit(s) excluded.
    
    ******* BRANCH EXECUTION COVERAGE - Analyze Unit: Menu_Display
    Function: DATA_PROCESSING\Menu_Display.  Branch(es) not executed:
      5612      if ( First_Call == TRUE ) {  /* Only execute this block during th
    00049E3A 6600 0722         BNE.W   $4A55E               Branch not taken.
      5613              if ( MP_Rd_Config_Straps ( RAW_STRAPS, Strap_Config ) ==
    00049E52 664A              BNE.B   $49E9E               Branch not taken.
      5750                    if (i == 17) 
    0004A4A4 6602              BNE.B   $4A4A8               Fall thru not taken.
       Executed     Total   Percent  Analyze-unit
             74        77     96.10  DATA_PROCESSING\Menu_Display
                    0 unit(s) excluded.

    Поскольку степень покрытия может меняться в зависимости от оптимизации при генерации кода, в некоторых случаях даже при полном выполнении всех операторов языка высокого уровня, на котором написана программная система, не удается достичь полного покрытия на уровне исполняемого кода.

    Например, в случае покрытия следующей конструкции на языке C:

    typedef enum
    {
    CC1 = 250,
    CC2 = 251,
    CC3 = 252
    } E_CC;
       … 
    E_CC key;
       …
    switch (key) {
       case CC1: printf("CC1"); break; 
       case CC2: printf("CC2"); break; 
       case CC3: printf("CC3"); break; 
    }

    компилятор Microtec C для Motorola 680x0 создаст таблицу возможных значений переменной key, в которой будут присутствовать все элементы от 0 до 255. Реально в программной системе возможно передать только значения констант CC1 - CC3, и в результате покрытыми окажутся только три ветки из 255 возможных в исполняемом коде. Никакими стандартными средствами увеличить степень такого покрытия нельзя. В этом случае отчет о покрытии сопровождается дополнительной информацией о причинах невозможности обеспечить полное покрытие.

    Сбор информации о покрытии на уровне исполняемого кода наиболее часто применяется в высококритичных программных системах, где не допускается наличия "мертвого" исполняемого кода, который потенциально может привести к сбою или отказу во время работы системы. К таким системам в первую очередь можно отнести авиационные бортовые системы, медицинские системы и системы обеспечения безопасности информации.

    13.2. Отчеты о проблемах

    13.2.1. Технологические цепочки и роли участников проекта, использующих отчеты о проблемах. Связь отчетов о проблемах с другими типами проектной документации

    Каждое несоответствие с требованиями, найденное тестировщиком, должно быть задокументировано в виде отчета о проблеме. Вероятность обнаружения и исправления ошибки, вызвавшей это несоответствие, зависит от того, насколько качественно она задокументирована. Отчеты о проблемах могут поступать не только от тестировщиков, но и от специалистов технической поддержки или пользователей, однако их общая цель - указать на наличие проблемы в системе, которая должна быть устранена. Если отчет составлен некорректно, разработчик не сможет устранить проблему, поэтому можно считать этот отчет одним из самых важных документов в цепочке тестовой документации.

    Главное, что должно быть включено в отчет об ошибке, - это:

  • Способ воспроизведения проблемы. Для того, чтобы разработчик смог устранить проблему, он должен разобраться в ее причинах, самостоятельно воспроизведя ее (и, возможно, не один раз). Один из самых тяжелых случаев в процессе разработки возникает при невоспроизводимой проблеме, т.е. проблеме, у которой точно не известен способ ее вызывать. Нахождение такого способа - одна из самых нетривиальных задач в работе тестировщика.
  • Анализ проблемы с кратким ее описанием. Лучше всего приводить описание в тех же терминах, в которых составлены требования на часть системы, в которой обнаружена проблема. В этом случае минимизируется вероятность недопонимания сути проблемы.
  • Любой отчет о проблеме должен быть составлен немедленно после ее обнаружения. Если отчет будет составлен спустя значительное время, повышается вероятность того, что в него не попадет какая-либо важная информация, которая поможет устранить причину проблемы в кратчайшие сроки.

    13.2.2. Структура отчетов о проблемах, их трассировка на программный код и документацию

    Структура отчета о проблеме в целом мало различается в различных проектах, изменения обычно касаются только порядка и имен следования полей. Некоторые поля могут отражать специфику данного конкретного проекта, однако обычно эти поля следующие:

  • Объект, в котором найдена проблема. Здесь помещается максимально полная информация - для документации это название документа, раздел, автор, версия. Для исходных текстов это имя модуля, имя функции/метода или номера строк, версия.
  • Выпуск и версия системы. Определяет место, откуда был взят объект с обнаруженной проблемой. Обычно требуется отдельная идентификация версии системы (а не только версии исходных текстов), поскольку может возникнуть путаница с повторно выявленными проблемами. В этом случае, если проблема уже была когда-то выявлена разработчиком и потом вновь появилась из-за того, что в систему попала не самая последняя версия программного модуля, разработчик может решить, что ему пришел старый отчет и проблемы на самом деле не существует.
  • Тип отчета
  • Ошибка кодирования - код не соответствует требованиям.
  • Ошибка проектирования - тестировщик не согласен с проектной документацией.
  • Предложение - у тестировщика возникла идея, как можно усовершенствовать код.
  • Расхождение с документацией - поведение ПО не соответствует руководству пользователя или проектной документации либо вообще нигде не описано. При этом у тестировщика нет оснований объявлять, где именно находится ошибка.
  • Взаимодействие с аппаратурой - неверная диагностика плохого состояния устройства, ошибка в интерфейсе с устройством.
  • Вопрос - тестировщик не уверен, что это проблема, и ему требуется дополнительная информация.
  • Степень важности. Строгого критерия определения степени важности не существует, и обычно это поле кодируют от 1 (незначительно) до 10 (фатально). Однако способов обоснованной оценки нет - очень сложно определить, насколько фатальной может оказаться, например, опечатка в один символ в руководстве пользователя.
  • Суть проблемы. Краткое (не более 2 строчек) определение проблемы. Даже если две проблемы очень похожи, их описания должны различаться.
  • Можно ли воспроизвести проблемную ситуацию? Ответ - Да, Нет, Не всегда. Последнее - если проблема носит нерегулярный характер. Нужно описывать, когда она проявляется, а когда - нет (например, если не вовремя нажать не ту клавишу).
  • Подробное описание проблемы и способ ее воспроизведения. При этом нужны подробности - и в описании условий воспроизведения, и в описании причины объявления получившейся реакции ошибкой.
  • Обычный вид отчета о проблеме, соответствующего данной структуре, следующий:

    Отчет о проблеме
    
    Порядковый номер отчета:
    
    Автор отчета:  ___________________    Дата создания отчета: __ __ __
    
    Документы/разделы, связанные с проблемой:
      ……………………………………..
    Идентификация объекта/процесса, где проявляется проблема:
    ………………………………………………………………………………………….
    
    Определение проблемы:
    ………………………………………………………………………………………….
    
    Автор решения: ___________________  Дата формирования решения __ __ __
    
    Принятое решение: (возможно, ссылки на изменяемые компоненты/запросы на изменения)
    ………………………………………………………………………………………….
    
    Результаты анализа, определяющие, на содержание каких компонент влияет решение:
    ………………………………………………………………………………………….
    
    План проверок, восстанавливающих текущее состояние документов разработки
    ………………………………………………………………………………………….
    
    Оценка принятого автором отчета решения о проблеме: _
    ………………………………………………………………………………………….
     ( 0 = полностью согласен
      1 = не все аспекты проблемы учтены/разрешены
      2 = основная часть проблемы осталась неразрешенной
      3 = решение не адекватно проблеме - не устраняет ее)

    13.3. Трассировочные таблицы

    13.3.1. Технологические цепочки и роли участников проекта, использующих трассировочные таблицы. Связь трассировочных таблиц с другими типами проектной документации

    На каждом этапе жизненного цикла разработки программной системы создается различного рода проектная документация. Как правило, документация каждого последующего этапа создается на базе документации предыдущего этапа. Для упрощения навигации по различным документам и в т.ч. упрощения верификации документации и самой системы часто используются перекрестные ссылки между разделами документов.

    Так, например, часто применяемая практика заключается в том, что каждое требование в документах помечается уникальным идентификатором - якорем ( anchor ). Якоря в требованиях могут иметь, например, следующий формат:

    [ANCHOR: код]

    Здесь код записывается в виде AAA_RR_NNNNNN, где AAA - тип документа (SYS, ORD и т.п.), RR - номер раздела верхнего уровня, в котором содержится якорь, и NNNNNN - номер ссылки с ведущими нулями.

    Требование в таком виде будет выглядеть следующим образом:

    Для каждого вычислимого атрибута должна быть определена роль, 
    от которой производится вычисления. [ANCHOR: SYS_02_000084].

    Если возникает необходимость сослаться на требование из того же самого документа или из любого другого, то в ссылке указывается код якоря для соответствующего требования. Так, например, если ссылка записывается в тексте и имеет следующий формат:

    [REF: код]

    где код имеет тот же формат, что и для якоря, ссылка на требования будет иметь следующий вид:

    Для доступа к названию роли в формуле расчета 
    значения вычислимого атрибута 
    должна использоваться мнемоника 
    [RoleName]. [ANCHOR: SRD_02_000058] [REF: SYS_02_000084].

    Система якорей и ссылок использует те же самые идеи, что и обычный гипертекст, однако, часто возникает необходимость не только в указании самого факта связи между требованиями или разделами документов, но и дополнительно указать тип связи. Например, можно выделить следующие типы связей:

  • обычная гиперссылка;
  • ссылка требований нижнего уровня на требования верхнего уровня;
  • ссылка на различные варианты одного и того же требования, предназначенного для разных вариантов системы (например, для разных платформ).
  • В этом случае можно указывать тип ссылки рядом с кодом якоря, на который она ссылается. Однако, часто применяется и другой метод организации типизированных ссылок между документами - трассировочные таблицы.

    В общем случае в строках и столбцах трассировочной таблицы указаны идентификаторы якорей, на которые и из которых идет ссылка, а в ячейке на пересечении строк и столбцов отмечается либо факт наличия ссылки, либо ее тип.

    Трассировочные таблицы могут использоваться для машинного анализа ссылочной целостности проектной документации или для быстрой навигации в больших объемах документов.

    13.3.2. Возможные формы трассировочных таблиц

    Как уже было сказано в предыдущем разделе, одна из форм трассировочных таблиц подразумевает указание идентификаторов якорей в строках и столбцах и типа связи в ячейках на их пересечении. Такая таблица будет выглядеть следующим образом:

    SYS_01_0001 SYS_01_0002 SYS_01_0003 SYS_01_0003
    SRD_01_0001 cross-ref variant
    SRD_01_0002 based on variant
    SRD_01_0003 based on variant
    SRD_01_0004 cross-ref variant

    В первом столбце перечислены якоря требований к программному обеспечению, в первой строке - якоря системных требований. На пересечении указаны типы ссылок: cross-ref - обычная информационная перекрестная ссылка; based on - требование к ПО, основанное на данном системном требовании; variant - может использоваться либо одно, либо другое требование к ПО в зависимости от варианта системы.

    Также часто используется более простая форма трассировочных таблиц. В первом столбце перечисляются якоря или номера разделов документа, который ссылается на другие. В строке - названия документов, на которые идет ссылка, а в ячейках - якоря или номера разделов, на которые идет ссылка. Трассировочная таблица в этом случае будет выглядеть следующим образом:

    РД СВТ Protection Profile Protection Profile глава 6 Protection Profile главы 1-4 Комментарии
    2.2.2 КСЗ должен требовать от пользователей идентифицировать себя при запросах на доступ. 5.2.2.4 FIA_UID.1.2 286, 288 82 O.USER_AUTHENTICATION, O.USER_IDENTIFICATION, 57 IdentificationAuthentication, 80 P.I_AND_A, 58 Non-bypassability
    2.2.2 КСЗ должен подвергать проверке подлинность идентификации - осуществлять аутентификацию. 5.2.2.3 FAI_UAU.1.2 277, 280 В названии трассировочного тега опечатка. Правильно - FIA_UAU.1.2
    2.2.2 КСЗ должен препятствовать доступу к защищаемым ресурсам неидентифицированных пользователей и пользователей, подлинность идентификации которых при аутентификации не подтвердилась. 5.1.3.1 286, 287 5.1.3.1 - необходимые данные для аутентификации - атрибуты учетной записи пользователя

    Здесь РД СВТ - документ Гостехкомиссии РФ, включающий в себя требования по защищенности средств вычислительной техники [5], Protection Profile - один из аналогичных документов, используемых в США. Таблица представляет собой трассировку требований РД СВТ на требования различных глав Protection Profile. В первой строке указаны главы, а в ячейчах - конкретные разделы.

    Страницы:

    13.1. Отчеты о покрытии программного кода

    13.1.1. Технологические цепочки и роли участников проекта, использующих отчеты о покрытии. Связь отчетов о покрытии с другими типами проектной документации

    Степень покрытия программного кода тестами - важный количественный показатель, позволяющий оценить качество системы тестов, а в некоторых случаях - и качество тестируемой программной системы. Данные о степени покрытия помещаются в отчеты о покрытии, которые генерируются при выполнении тестов инструментальными средствами, поддерживающими процесс тестирования, т.е. по сути, генерируются средой тестирования (Рис 13.1). Формат отчетов о покрытии обычно единый внутри проекта или нескольких проектов и часто зависит от особенностей инструментальных средств тестирования.

    В отчете о покрытии в стандартизированной форме указываются участки программного кода тестируемой системы (или ее части), которые не были выполнены во время выполнения тестовых примеров, т.е. не были покрыты тестами. Причины непокрытия анализируются тестировщиками, по результатам анализа составляются отчеты о проблемах и запросы на изменение - документы, где описываются объекты разработки, которые необходимо изменить, и причины этих изменений.

    (рис 13.1) Генерация отчета о покрытии и изменения по результатам его анализа

    Недостаточное покрытие может свидетельствовать о неполноте системы тестов или тест-требований, в этом случае в запросе об изменении указывается на необходимость расширения системы тестов или тест-требований. Другой причиной недостаточного покрытия могут быть участки защитного кода, которые никогда не выполнятся даже в случае нештатной работы системы. В этом случае в запросе на изменения указывается на необходимость модификации исходных текстов либо отмечается, что для этого участка программной системы не требуется покрытие. В качестве третьей причины недостаточного покрытия может выступать рассогласование требований и программного кода системы, в результате которого в коде могут остаться неиспользуемые более участки либо, наоборот, появиться участки, рассчитанные на будущее (и реализующие функциональность, не описанную в требованиях). В этом случае в запросе на изменение указывается на необходимость модификации требований и/или кода системы для приведения их в согласованное состояние.

    13.1.2. Возможные формы отчетов о покрытии

    Типичный отчет о покрытии представляет собой список структурных элементов покрываемого программного кода (функций или методов), содержащий для каждого структурного элемента следующую информацию:

  • Название функции или метода
  • Тип покрытия (по строкам, по ветвям, MC/DC или иной)
  • Количество покрываемых элементов в функции или методе (строк, ветвей, логических условий)
  • Степень покрытия функции или метода (в процентах или в абсолютном выражении)
  • Список непокрытых элементов (в виде участков непокрытого программного кода с номерами строк)
  • Кроме того, отчет о покрытии содержит заголовочную информацию, позволяющую идентифицировать отчет, и общий итог - общую степень покрытия всех функций, для которых собирается информация о покрытии.

    Пример такого отчета о покрытии приведен ниже.

    Coverage Report
    Generated 10/07/2006 for file Testing_Facilities.cpp
    ----------------------------------------------------
    1) function main_Menu()
    Coverage: Instructions
    Elements: 25 structured lines of code (SLOCs)
    Covered: 22 lines (88%)
    Not covered:
       291 default:
       292 return -1;
       293 break;
    
    Coverage: Branches
    Elements: 5 branches
    Covered: 4 branches (80%)
    Not covered (starting and ending lines only):
    default:
    break;
    
    ----------------------------------------------------
    2) function item_Help()
    Coverage: Instructions
    Elements: 180 structured lines of code (SLOCs)
    Covered: 180 lines (100%)
    
    Coverage: Branches
    Elements: 2 branches
    Covered: 2 branches (80%)
    ----------------------------------------------------
    Total functions: 2
    Total instructions coverage: 98.5%
    Total branches coverage: 86%

    Отчет о покрытии может создаваться либо для всех функций программного модуля или всего проекта, либо выборочно для определенных функций.

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

    Пример такого отчета приведен ниже:

    Зеленым цветом отмечены выполненные в результате тестирования участки метода, красным - не выполненные.

    Конкретная форма отчета о покрытии определяется инструментарием и технологическими процессами проекта.

    Рассмотрим, например, отчет о структурном покрытии, генерируемый при помощи средства для анализа программного кода CodeTEST компании Metrowerks.

    Сбор покрытия производится по определенному уровню покрытия, информация об этом входит в состав заголовка отчета о покрытии. В данном случае програмный код покрывался по MC/DC.

    CodeTEST Advanced Coverage Tools
    Modified Condition Decision Coverage Report (MCDC), DO-178B Level A
    CodeTEST Report Generator 2.2.04
    Report generated on Sun Aug 21 14:28:16 2005
    
    IDB File:
        <Path_to_IDB_file>
        42963330-1C0 Thu May 26 21:36:00 2005

    Далее выводится информация о проценте покрытия по всем модулям в совокупности (в данном случае, это 33 модуля):

    Overall Summary (MCDC): 33 Files
     1405 true-false decisions
          674  48.0%  covered
          494  35.2%  partially covered
          237  16.9%  not covered
     1928 conditions in the decisions
         1068  55.4%  covered
          571  29.6%  partially covered
          289  15.0%  not covered
      278 case branches
          154  55.4%  covered
          124  44.6%  not covered
      581 coverage events
          504  86.7%  covered
           77  13.3%  not covered

    Рассмотрим более подробно каждую из характеристик.

    True-false decisions - количество логических выражений, в данном случае их 1405. Из этого числа на оба возможных значения ( True и False ) покрыто лишь 674, еще 494 покрыто на какое-то одно из значений, а 237 не покрыто вообще.

    Conditions in the decisions - количество логических условий внутри логических выражений. Как можно догадаться, их количество не может быть меньше количества логических выражений. Непокрытие логических условий явным образом влечет за собой непокрытие логических выражений. Факт, что если все условия будут покрыты, то все выражения также будут покрыты.

    Case branches - количество веток ветвления операторов выбора ( select ). Ветка считается покрытой, если выражение, стоящее в условии оператора select, принимает значение, соответствующее данному варианту выбора ( case ), в результате чего ветка выполняется.

    Coverage events - в данном случае, это количество точек входа / выхода в функциях. Точка входа в функцию считается покрытой, если эта функция была вызвана хотя бы один раз. Точками выхода являются точка окончания функции ( } ), когда управление передается в место вызова этой функции, а также операторы возврата ( return ), после выполнения которых управление также передается в место вызова функции.

    Затем выводится информация для первого модуля, а именно: имя модуля, путь к файлу на диске, дата последнего изменения, контрольная сумма. После этого выводится суммарная информация о покрытии только для этого модуля (для всех его функций, количество которых также указывается). Структура этой информации аналогична структуре, описанной выше:

    1. File <Module_1_name.cpp> in <Path_to_module_1>
        Last Modified: Fri Oct 15 18:34:14 2004
        Checksum: CEDBAB67
    
        File Summary (Extended MCDC): 6 Functions
           24 true-false decisions
               10  41.7%  covered
               11  45.8%  partially covered
                3  12.5%  not covered
           39 conditions in the decisions
               20  51.3%  covered
               15  38.5%  partially covered
                4  10.3%  not covered
            0 case branches
           12 coverage events
               12 100.0%  covered
                0   0.0%  not covered

    После этого происходит поочередный вывод суммарной информации для каждой из функций в отдельности и также всех ключевых участков функции, влияющих на покрытие, а именно: точки входа / выхода, логические выражения, логические условия, операторы выбора. При этом для каждого из этих ключевых участков выводится информация о степени покрытия, где возможными значениями могут быть:

    COVERED - участок полностью покрыт в понятиях типа, к которому он приписан;

    PARTIALLY covered - участок частично покрыт. Применимо только к логическим выражениям и условиям и указывает на то, что выражение (условие) покрыто на какое-то одно из двух возможных значений;

    NOT covered - участок не покрыт. Это означает, что данный участок не выполнялся в процессе работы скомпилированного программного кода.

    Ниже представлен типичный результат покрытия для функции.

    1.1 Function <Function_1>
            void Function_1(void)
    
            Function Summary (MCDC):
                3 true-false decisions
                    0   0.0%  covered
                    2  66.7%  partially covered
                    1  33.3%  not covered
                5 conditions in the decisions
                    1  20.0%  covered
                    3  60.0%  partially covered
                    1  20.0%  not covered
                0 case branches
                2 coverage events
                    2 100.0%  covered
                    0   0.0%  not covered
    
            coverage line 266: function entry
                COVERED
    
            decision line 267: if statement
                if ((A == B)  (...
    
                 T     F
             1: *ttt  *fxx  ((A == ...)    COVERED
             2: *ttt   tfx  ((C...)        PARTIALLY covered
             3: *ttt   ttf  ((D == 0)        PARTIALLY covered
    
            decision line 271: if statement
                if (E <= 0)
    
                 T   F
             1:  t  *f  (E <= 0)   PARTIALLY covered
    
            decision line 276: if statement
                if (D == 0)
    
                 T   F
             1:  t   f  (D...)   NOT covered
    
            coverage line 291: function end
                }
                COVERED

    Следует обратить внимание на то, каким образом происходит разбор логических выражений. Предположим, что у нас имеется выражение вида:

    if ((A==B)  (C > 0)  (D == 0))

    и пусть результат покрытия для него такой, как приведен выше ( decision line 267: if statement ). Для этого выражения строится таблица, где в каждой строке помещается информация для каждого из логических условий, входящих в это логическое выражение. Нумерация логических условий начинается с 1, в нашем случае их 3.

    В первом столбце указывается комбинация значений логических условий (с участием рассматриваемого условия), которую необходимо выставить, чтобы логическое выражение приняло значение True. В данном случае, так как все условия соединены логическим оператором "И" ( ), такой комбинацией может быть только TTT. Если указанная комбинация была сформирована в процессе тестирования программы, то она помечается символом ( * ).

    Во втором столбце указывается комбинация значений логических условий (с участием рассматриваемого условия), которую необходимо выставить, чтобы логическое выражение приняло значение False. В данном случае достаточно, чтобы хотя бы одно условие приняло значение False, при этом значения всех последующих условий не учитываются (это отображается символом X ).

    Третий столбец - это вырезка текста логического условия, позволяющая легче ориентироваться в коде при анализе покрытия.

    Из получившейся таблицы видно, что второе и третье логическое условие в процессе выполнения не принимали значения False. Определение причины этого и является задачей анализа структурного покрытия.

    После того, как в рамках данного модуля будут рассмотрены все функции, рассматривается следующий модуль, и так далее. Мы видим, что структура отчетного файла, получаемого в результате работы CodeTEST, достаточно проста и имеет вложенную структуру.

    Отчеты о покрытиях, создаваемые Microsoft Visual Studio Team Edition, будут рассмотрены на семинарских занятиях.

    13.1.3. Покрытие на уровне исходных текстов и на уровне машинных кодов

    В некоторых случаях инструментальные средства сбора покрытия анализируют покрытие программного кода тестами не на уровне исходных текстов системы, а на уровне машинных инструкций. В этом случае степень покрытия зависит и от того, какой исполняемый код генерируется компилятором. Отчеты о покрытии в этом случае выглядят следующим образом (отчет о покрытии сгененирован при помощи отладчика Microtec XRAY для Motorola 680x0):

    ******* INSTRUCTION EXECUTION COVERAGE - Analyze Unit: Menu_Display
    Function: DATA_PROCESSING\Menu_Display.  Instruction(s) not executed:
      5668             switch (Key) 
    0004A0F6 0352              BCHG    D1,(A2)                            
    0004A102 0466 0466         SUBI.W  #$466,-(A6)
    0004A106 0466 0466         SUBI.W  #$466,-(A6)
    0004A10A 0466 0466         SUBI.W  #$466,-(A6)
    0004A10E 0466 0466         SUBI.W  #$466,-(A6)
    0004A112 0466 0466         SUBI.W  #$466,-(A6)
    0004A116 0466 0474         SUBI.W  #$474,-(A6)
      5751                       i = 1; 
    0004A4A6 7401              MOVEQ   #$1,D2
       Executed     Total   Percent  Analyze-unit
            467       475     98.32  DATA_PROCESSING\Menu_Display
                    0 unit(s) excluded.
    
    ******* BRANCH EXECUTION COVERAGE - Analyze Unit: Menu_Display
    Function: DATA_PROCESSING\Menu_Display.  Branch(es) not executed:
      5612      if ( First_Call == TRUE ) {  /* Only execute this block during th
    00049E3A 6600 0722         BNE.W   $4A55E               Branch not taken.
      5613              if ( MP_Rd_Config_Straps ( RAW_STRAPS, Strap_Config ) ==
    00049E52 664A              BNE.B   $49E9E               Branch not taken.
      5750                    if (i == 17) 
    0004A4A4 6602              BNE.B   $4A4A8               Fall thru not taken.
       Executed     Total   Percent  Analyze-unit
             74        77     96.10  DATA_PROCESSING\Menu_Display
                    0 unit(s) excluded.

    Поскольку степень покрытия может меняться в зависимости от оптимизации при генерации кода, в некоторых случаях даже при полном выполнении всех операторов языка высокого уровня, на котором написана программная система, не удается достичь полного покрытия на уровне исполняемого кода.

    Например, в случае покрытия следующей конструкции на языке C:

    typedef enum
    {
    CC1 = 250,
    CC2 = 251,
    CC3 = 252
    } E_CC;
       … 
    E_CC key;
       …
    switch (key) {
       case CC1: printf("CC1"); break; 
       case CC2: printf("CC2"); break; 
       case CC3: printf("CC3"); break; 
    }

    компилятор Microtec C для Motorola 680x0 создаст таблицу возможных значений переменной key, в которой будут присутствовать все элементы от 0 до 255. Реально в программной системе возможно передать только значения констант CC1 - CC3, и в результате покрытыми окажутся только три ветки из 255 возможных в исполняемом коде. Никакими стандартными средствами увеличить степень такого покрытия нельзя. В этом случае отчет о покрытии сопровождается дополнительной информацией о причинах невозможности обеспечить полное покрытие.

    Сбор информации о покрытии на уровне исполняемого кода наиболее часто применяется в высококритичных программных системах, где не допускается наличия "мертвого" исполняемого кода, который потенциально может привести к сбою или отказу во время работы системы. К таким системам в первую очередь можно отнести авиационные бортовые системы, медицинские системы и системы обеспечения безопасности информации.

    13.2. Отчеты о проблемах

    13.2.1. Технологические цепочки и роли участников проекта, использующих отчеты о проблемах. Связь отчетов о проблемах с другими типами проектной документации

    Каждое несоответствие с требованиями, найденное тестировщиком, должно быть задокументировано в виде отчета о проблеме. Вероятность обнаружения и исправления ошибки, вызвавшей это несоответствие, зависит от того, насколько качественно она задокументирована. Отчеты о проблемах могут поступать не только от тестировщиков, но и от специалистов технической поддержки или пользователей, однако их общая цель - указать на наличие проблемы в системе, которая должна быть устранена. Если отчет составлен некорректно, разработчик не сможет устранить проблему, поэтому можно считать этот отчет одним из самых важных документов в цепочке тестовой документации.

    Главное, что должно быть включено в отчет об ошибке, - это:

  • Способ воспроизведения проблемы. Для того, чтобы разработчик смог устранить проблему, он должен разобраться в ее причинах, самостоятельно воспроизведя ее (и, возможно, не один раз). Один из самых тяжелых случаев в процессе разработки возникает при невоспроизводимой проблеме, т.е. проблеме, у которой точно не известен способ ее вызывать. Нахождение такого способа - одна из самых нетривиальных задач в работе тестировщика.
  • Анализ проблемы с кратким ее описанием. Лучше всего приводить описание в тех же терминах, в которых составлены требования на часть системы, в которой обнаружена проблема. В этом случае минимизируется вероятность недопонимания сути проблемы.
  • Любой отчет о проблеме должен быть составлен немедленно после ее обнаружения. Если отчет будет составлен спустя значительное время, повышается вероятность того, что в него не попадет какая-либо важная информация, которая поможет устранить причину проблемы в кратчайшие сроки.

    13.2.2. Структура отчетов о проблемах, их трассировка на программный код и документацию

    Структура отчета о проблеме в целом мало различается в различных проектах, изменения обычно касаются только порядка и имен следования полей. Некоторые поля могут отражать специфику данного конкретного проекта, однако обычно эти поля следующие:

  • Объект, в котором найдена проблема. Здесь помещается максимально полная информация - для документации это название документа, раздел, автор, версия. Для исходных текстов это имя модуля, имя функции/метода или номера строк, версия.
  • Выпуск и версия системы. Определяет место, откуда был взят объект с обнаруженной проблемой. Обычно требуется отдельная идентификация версии системы (а не только версии исходных текстов), поскольку может возникнуть путаница с повторно выявленными проблемами. В этом случае, если проблема уже была когда-то выявлена разработчиком и потом вновь появилась из-за того, что в систему попала не самая последняя версия программного модуля, разработчик может решить, что ему пришел старый отчет и проблемы на самом деле не существует.
  • Тип отчета
  • Ошибка кодирования - код не соответствует требованиям.
  • Ошибка проектирования - тестировщик не согласен с проектной документацией.
  • Предложение - у тестировщика возникла идея, как можно усовершенствовать код.
  • Расхождение с документацией - поведение ПО не соответствует руководству пользователя или проектной документации либо вообще нигде не описано. При этом у тестировщика нет оснований объявлять, где именно находится ошибка.
  • Взаимодействие с аппаратурой - неверная диагностика плохого состояния устройства, ошибка в интерфейсе с устройством.
  • Вопрос - тестировщик не уверен, что это проблема, и ему требуется дополнительная информация.
  • Степень важности. Строгого критерия определения степени важности не существует, и обычно это поле кодируют от 1 (незначительно) до 10 (фатально). Однако способов обоснованной оценки нет - очень сложно определить, насколько фатальной может оказаться, например, опечатка в один символ в руководстве пользователя.
  • Суть проблемы. Краткое (не более 2 строчек) определение проблемы. Даже если две проблемы очень похожи, их описания должны различаться.
  • Можно ли воспроизвести проблемную ситуацию? Ответ - Да, Нет, Не всегда. Последнее - если проблема носит нерегулярный характер. Нужно описывать, когда она проявляется, а когда - нет (например, если не вовремя нажать не ту клавишу).
  • Подробное описание проблемы и способ ее воспроизведения. При этом нужны подробности - и в описании условий воспроизведения, и в описании причины объявления получившейся реакции ошибкой.
  • Обычный вид отчета о проблеме, соответствующего данной структуре, следующий:

    Отчет о проблеме
    
    Порядковый номер отчета:
    
    Автор отчета:  ___________________    Дата создания отчета: __ __ __
    
    Документы/разделы, связанные с проблемой:
      ……………………………………..
    Идентификация объекта/процесса, где проявляется проблема:
    ………………………………………………………………………………………….
    
    Определение проблемы:
    ………………………………………………………………………………………….
    
    Автор решения: ___________________  Дата формирования решения __ __ __
    
    Принятое решение: (возможно, ссылки на изменяемые компоненты/запросы на изменения)
    ………………………………………………………………………………………….
    
    Результаты анализа, определяющие, на содержание каких компонент влияет решение:
    ………………………………………………………………………………………….
    
    План проверок, восстанавливающих текущее состояние документов разработки
    ………………………………………………………………………………………….
    
    Оценка принятого автором отчета решения о проблеме: _
    ………………………………………………………………………………………….
     ( 0 = полностью согласен
      1 = не все аспекты проблемы учтены/разрешены
      2 = основная часть проблемы осталась неразрешенной
      3 = решение не адекватно проблеме - не устраняет ее)

    13.3. Трассировочные таблицы

    13.3.1. Технологические цепочки и роли участников проекта, использующих трассировочные таблицы. Связь трассировочных таблиц с другими типами проектной документации

    На каждом этапе жизненного цикла разработки программной системы создается различного рода проектная документация. Как правило, документация каждого последующего этапа создается на базе документации предыдущего этапа. Для упрощения навигации по различным документам и в т.ч. упрощения верификации документации и самой системы часто используются перекрестные ссылки между разделами документов.

    Так, например, часто применяемая практика заключается в том, что каждое требование в документах помечается уникальным идентификатором - якорем ( anchor ). Якоря в требованиях могут иметь, например, следующий формат:

    [ANCHOR: код]

    Здесь код записывается в виде AAA_RR_NNNNNN, где AAA - тип документа (SYS, ORD и т.п.), RR - номер раздела верхнего уровня, в котором содержится якорь, и NNNNNN - номер ссылки с ведущими нулями.

    Требование в таком виде будет выглядеть следующим образом:

    Для каждого вычислимого атрибута должна быть определена роль, 
    от которой производится вычисления. [ANCHOR: SYS_02_000084].

    Если возникает необходимость сослаться на требование из того же самого документа или из любого другого, то в ссылке указывается код якоря для соответствующего требования. Так, например, если ссылка записывается в тексте и имеет следующий формат:

    [REF: код]

    где код имеет тот же формат, что и для якоря, ссылка на требования будет иметь следующий вид:

    Для доступа к названию роли в формуле расчета 
    значения вычислимого атрибута 
    должна использоваться мнемоника 
    [RoleName]. [ANCHOR: SRD_02_000058] [REF: SYS_02_000084].

    Система якорей и ссылок использует те же самые идеи, что и обычный гипертекст, однако, часто возникает необходимость не только в указании самого факта связи между требованиями или разделами документов, но и дополнительно указать тип связи. Например, можно выделить следующие типы связей:

  • обычная гиперссылка;
  • ссылка требований нижнего уровня на требования верхнего уровня;
  • ссылка на различные варианты одного и того же требования, предназначенного для разных вариантов системы (например, для разных платформ).
  • В этом случае можно указывать тип ссылки рядом с кодом якоря, на который она ссылается. Однако, часто применяется и другой метод организации типизированных ссылок между документами - трассировочные таблицы.

    В общем случае в строках и столбцах трассировочной таблицы указаны идентификаторы якорей, на которые и из которых идет ссылка, а в ячейке на пересечении строк и столбцов отмечается либо факт наличия ссылки, либо ее тип.

    Трассировочные таблицы могут использоваться для машинного анализа ссылочной целостности проектной документации или для быстрой навигации в больших объемах документов.

    13.3.2. Возможные формы трассировочных таблиц

    Как уже было сказано в предыдущем разделе, одна из форм трассировочных таблиц подразумевает указание идентификаторов якорей в строках и столбцах и типа связи в ячейках на их пересечении. Такая таблица будет выглядеть следующим образом:

    SYS_01_0001 SYS_01_0002 SYS_01_0003 SYS_01_0003
    SRD_01_0001 cross-ref variant
    SRD_01_0002 based on variant
    SRD_01_0003 based on variant
    SRD_01_0004 cross-ref variant

    В первом столбце перечислены якоря требований к программному обеспечению, в первой строке - якоря системных требований. На пересечении указаны типы ссылок: cross-ref - обычная информационная перекрестная ссылка; based on - требование к ПО, основанное на данном системном требовании; variant - может использоваться либо одно, либо другое требование к ПО в зависимости от варианта системы.

    Также часто используется более простая форма трассировочных таблиц. В первом столбце перечисляются якоря или номера разделов документа, который ссылается на другие. В строке - названия документов, на которые идет ссылка, а в ячейках - якоря или номера разделов, на которые идет ссылка. Трассировочная таблица в этом случае будет выглядеть следующим образом:

    РД СВТ Protection Profile Protection Profile глава 6 Protection Profile главы 1-4 Комментарии
    2.2.2 КСЗ должен требовать от пользователей идентифицировать себя при запросах на доступ. 5.2.2.4 FIA_UID.1.2 286, 288 82 O.USER_AUTHENTICATION, O.USER_IDENTIFICATION, 57 IdentificationAuthentication, 80 P.I_AND_A, 58 Non-bypassability
    2.2.2 КСЗ должен подвергать проверке подлинность идентификации - осуществлять аутентификацию. 5.2.2.3 FAI_UAU.1.2 277, 280 В названии трассировочного тега опечатка. Правильно - FIA_UAU.1.2
    2.2.2 КСЗ должен препятствовать доступу к защищаемым ресурсам неидентифицированных пользователей и пользователей, подлинность идентификации которых при аутентификации не подтвердилась. 5.1.3.1 286, 287 5.1.3.1 - необходимые данные для аутентификации - атрибуты учетной записи пользователя

    Здесь РД СВТ - документ Гостехкомиссии РФ, включающий в себя требования по защищенности средств вычислительной техники [5], Protection Profile - один из аналогичных документов, используемых в США. Таблица представляет собой трассировку требований РД СВТ на требования различных глав Protection Profile. В первой строке указаны главы, а в ячейчах - конкретные разделы.

    Вернуться к учебному плану