Проект DO-178C включает в себя пример среды, показывающей, как можно разработать задания сборки Jenkins, которые используют непрерывное интегрирование (CI), чтобы полностью автоматизировать выполнение операций верификации программного обеспечения. Среда Jenkins CI поставляется с готовым к запуску заданием, которое выполняет следующие задачи:
Создание отчета о требованиях из каждого набора требований в папке DO_02_Requirements.
Генерирует отчет описания разработки системы из каждой модели в папке DO_03_Design.
Проверяет каждую модель на соответствие требованиям к программному обеспечению высокого уровня, которые она реализует.
Проверяет каждую модель на соответствие стандартам модели ПО (DO_01_Planning>standards>MB_11_23_SMS>MB_11_23_SMS.docx
).
Анализирует каждую модель для поиска ошибок проектирования.
Генерирует код из каждой модели.
Просматривает сгенерированный код.
Проверяет, что сгенерированный код соответствует стандартам Программного кода (DO_01_Planning>standards>MB_11_08_SCS>MB_11_08_SCS.docx
).
Анализирует сгенерированный код на дефекты программного обеспечения.
Проверяет сгенерированный код на соответствие требованиям к программному обеспечению высокого уровня, которые он реализует.
Генерирует низкоуровневые тесты из каждой модели, когда охват высокоуровневых тестов неполен.
Проверяет сгенерированный код на соответствие требованиям низкоуровневого программного обеспечения, которые не покрываются высокоуровневыми тестами.
Оценивает общий охват тестов, которые используются для проверки сгенерированного кода.
Примечание
Если вы хотите запустить CI на нескольких хостах или в облаке, свяжитесь с командой MathWorks CI. Продукты компилятора и продукты преобразования, такие как Embedded Coder®, Simulink® Design Verifier™, и Simulink Code Inspector™, могут потребоваться клиентские лицензии доступа (CAL).
Для получения дополнительной информации об использовании среды Jenkins™ CI в проекте DO-178C, смотрите:
Шаблон DO-178C и демонстрационный проект обеспечивают готовый к использованию файл сборки задания Дженкинса, DODemoTask.m
, который можно использовать для выполнения операций верификации и валидации в рабочем процессе Модельно-ориентированное проектирование. Используя существующий файл задания сборки Jenkins, можно легко настроить операции верификации и валидации для вашего проекта.
Для создания пользовательского задания сборки требуется:
В continuous_integation>job
папка, DODemoTask.m
файл задает задания, которые выполняются сборкой Jenkins. Этот файл также используется для определения проекта DO-178C и моделей, по которым выполняются задания.
Метод setupJob()
, который выполняет в начале и конце каждого задания, выполняет следующие функции:
Функция loadProject()
загружает проект.
Функция getModelNames()
восстанавливает путь для модели (моделей), против которой задачи работы выполняют.
Использует дополнительные функции для выполнения фоновых задач, таких как регистрация директории задания сборки, очистка задачи и задания и очистка кэша.
methods function setupJob(this) % Equivalent to (TestClassSetup) of matlab.unittest.TestCase. this.JobDir = fileparts(mfilename('fullpath')); this.ReportDir = regexprep(this.JobDir, 'job$', 'reports'); addpath(this.JobDir); this.clearCache(); this.loadProject(); this.getModelNames(); end function setupTask(this) % Equivalent to (TestMethodSetup) of matlab.unittest.TestCase. end function cleanupTask(this) % Equivalent to (TestMethodTeardown) of matlab.unittest.TestCase. end function cleanupJob(this) % Equivalent to (TestClassTeardown) of matlab.unittest.TestCase. this.closeProject(); this.restoreDir(); end end methods % For use by setupJob. function clearCache(this) % The MATLAB Compiler Runtime (MCR) cache can cause errors with % Polyspace in certain installations. Delete the entire cache % to avoid running into this problem. cacheDir = fullfile(tempdir, getenv('username')); if exist(cacheDir, 'dir') rmdir(cacheDir, 's'); end end function loadProject(this) prj = dir(fullfile(this.JobDir, '..', '..', '*.prj')); this.ProjectDir = prj.folder; this.ProjectName = prj.name; this.Project = matlab.project.loadProject(fullfile(this.ProjectDir, this.ProjectName)); end function getModelNames(this) this.ModelNames = find_mdlrefs('Flight_Control'); end end methods % For use by setupTask. end methods % For use by cleanupTask. end methods % For use by cleanupJob. function closeProject(this) this.Project.close(); end function restoreDir(this) cd(this.JobDir); end end
Можно использовать функцию getModelNames()
для извлечения имен модели из модели верхнего уровня или из определенных папок проекта.
Чтобы извлечь имена модели из модели верхнего уровня:
Все модели в вашем проекте рассматриваются как модели-ссылки, если вы не зарегистрируете их как модели верхнего уровня. Определение местоположения isTopModel
и введите имя модели верхнего уровня в проекте. Обратите внимание, что модель верхнего уровня может быть:
Ссылка только на одну модель проекта.
Ссылка на модель в тестовой обвязке.
В этом примере Flight_Control
определяется как модель верхнего уровня.
methods function result = isTopModel(this, model) allTopModels = {'Flight_Control'}; result = any(strcmpi(allTopModels, model)); end end
Найдите getModelNames() функции
и для find_mdlrefs
введите имя модели верхнего уровня. Обратите внимание, что модель верхнего уровня соответствует той, которая предусмотрена для isTopModel
.
function getModelNames(this) this.ModelNames = find_mdlrefs('Flight_Control'); end
Задание сборки Дженкинса выполняет задания на всех моделях в модели верхнего уровня.
Чтобы получить имена модели из папки директории проекта:
В функциональном getModelNames()
введите имя папки проекта, в которой сохраняются модели. В этом примере имена модели извлекаются из папки DO_03_Design
.
function getModelNames(this) designDir = fullfile(this.ProjectDir, 'DO_03_Design'); dirList = dir(designDir); end
Задание сборки Дженкинса выполняет задания на всех моделях в папке директории проекта.
Можно также принять решение исключить извлечение имен моделей из определенных папок проекта, а также имен моделей, которые содержат определенные символы, такие как ".
«и» .svn
". В этом примере функция не возвращает имена моделей в папках проекта common
и sample_model
или имена моделей, которые содержат ".
".
function getModelNames(this) %Ignore common, sample_model, and names that are not a folder such as ".", "..", and ".svn". ignoreDir = arrayfun(@(x) (x.isdir == 0) || strcmpi(x.name, 'sample_model') || strcmpi(x.name, 'common') || contains(x.name, '.'), dirList); dirList = dirList(~ignoreDir); this.ModelNames = arrayfun(@(x) (x.name), dirList, 'UniformOutput', false); end
The TaskSequence
свойство DODemoTasks
класс определяет задания верификации и валидации и порядок, в котором они выполняются во время задания сборки Jenkins. Можно добавлять и удалять задания и изменять порядок выполнения заданий. Успешное выполнение задания зависит от вашего лицензирования продукта. Ошибка возникает, когда у вас нет лицензии на продукт.
Чтобы настроить задание сборки Дженкинса для выполнения подмножества заданий:
Найдите TaskSequence
свойство, которое определяет задачи задания и порядок, в котором они выполняются во время задания сборки. В этом примере taskGenReqReport
выполняет сначала и taskMergeCodeCoverage
выполняется последним.
properties TaskSequence = ["taskGenReqReport" "taskGenSDD" "taskVerifyModel2Reqs" "taskCheckModelStds" "taskDetectDesignErrs" "taskGenSrcCode" "taskVerifySrcCode2Model" "taskCheckCodeStds" "taskProveCodeQuality" "taskVerifyObjCode2Reqs" "taskGenLowLevelTests" "taskVerifyObjCode2LowLevelTests" "taskMergeCodeCoverage"]; end
Задания в TaskSequence
свойство соответствует этим методам задачи:
taskGenReqReport()
taskGenSDD()
taskVerifyModel2Reqs()
taskCheckModelStds()
taskDetectDesignErrs()
taskGenSrcCode()
taskVerifySrcCode2Model()
taskCheckCodeStds()
taskProveCodeQuality()
taskVerifyObjCode2Reqs()
taskGenLowLevelTests()
taskVerifyObjCode2LowLevelTests()
taskMergeCodeCoverage()
При необходимости измените TaskSequence
свойство так, что остаются только эти задания:
taskVerifyModel2Reqs
- Запускает симуляцию, чтобы проверить модели на соответствие требованиям. Требует Simulink Test™ и Simulink Coverage™.
taskGenSrcCode
- Генерирует код из моделей.
taskVerifyObjCode2Reqs
- Запускает симуляции программа-в цикле (SIL) и процессор-в-цикле (PIL), чтобы проверить сгенерированный код на соответствие требованиям.
properties TaskSequence = ["taskVerifyModel2Reqs" "taskGenSrcCode" "taskVerifyObjCode2Reqs"]; end
(Необязательно) Найти и удалить следующие методы задачи:
taskGenReqReport()
taskGenSDD()
taskCheckModelStds()
taskDetectDesignErrs()
taskVerifySrcCode2Model()
taskCheckCodeStds()
taskProveCodeQuality()
taskGenLowLevelTests()
taskVerifyObjCode2LowLevelTests()
taskMergeCodeCoverage()
Проверьте оставшиеся методы задачи, которые соответствуют задачам, заданным в TaskSequence
свойство. Эти задачи выполняются для каждой модели в проекте.
taskVerifyModel2Reqs ()
Проверяет каждую зарегистрированную модель на соответствие требованиям к программному обеспечению высокого уровня, которые она реализует, вызывая либо:
Все модели в образце модели
verifyModel2Reqs('MODEL', [], [], 'CI')
Все модели в модели верхнего уровня
verifyModel2Reqs('MODEL', 'TreatAsTopMdl', [], 'CI')
Результат каждой итерации определяется на основе возвращенных результатов верификации, и Simulink Test и Simulink Coverage Model Coverage сообщают о покрытии:
Результат следующий -1
(FAIL), когда в тесте есть ошибка или отказ, 0
(WARN), когда в тестовом примере есть предупреждение, или 1
(PASS).
Общий результат -1
(FAIL), когда отчет Simulink Test или отчет о покрытии модели не генерируется успешно. В противном случае это 1
(PASS).
function taskVerifyModel2Reqs(this) % This test point checks if Simulink Test and Model Coverage % Reports generated from models are successfully created by % "verifyModel2Reqs". outcome = 1; exception = ''; counter = 0; try % Test generation of Simulink Test and Model Coverage % Reports (for HLR Simulation Tests) from models in the % project. title = 'HLR Simulation Tests'; headers = {'Model Name', 'Num Pass', 'Num Warn', 'Num Fail', 'Outcome'}; data = {}; for i = 1:numel(this.ModelNames) if exist(fullfile(this.ProjectDir, 'DO_03_Design', this.ModelNames{i}, 'test_cases', 'HLR', [this.ModelNames{i}, '_REQ_Based_Test.mldatx']), 'file') if this.isTopModel(this.ModelNames{i}) res = verifyModel2Reqs(this.ModelNames{i}, 'TreatAsTopMdl', [], 'CI'); else res = verifyModel2Reqs(this.ModelNames{i}, [], [], 'CI'); end data(i,:) = {this.ModelNames{i}, res.NumPass, res.NumWarn, res.NumFail, res.Outcome}; msg = ['One or more high-level tests failed on ', this.ModelNames{i}, '.']; [outcome, exception, counter] = this.verifyOutcome (res.Outcome, msg, exception, outcome, counter); file = fullfile(this.ProjectDir, 'DO_03_Design', this.ModelNames{i}, 'verification_results', 'simulation_results', 'HLR', [this.ModelNames{i}, '_REQ_Based_Test_Report.pdf']); msg = ['Simulation Test Report not created: ', this.ModelNames{i}, '_REQ_Based_Test_Report.pdf.']; [outcome, exception, counter] = this.verifyFile(file, msg, exception, outcome, counter); file = fullfile(this.ProjectDir, 'DO_03_Design', this.ModelNames{i}, 'verification_results', 'model_coverages', 'HLR', [this.ModelNames{i}, '_REQ_Based_Model_Coverage_Report.html']); msg = ['Model Coverage Report not created: ', this.ModelNames{i}, '_REQ_Based_Model_Coverage_Report.html.']; [outcome, exception, counter] = this.verifyFile(file, msg, exception, outcome, counter); else data(i,:) = {this.ModelNames{i}, [], [], [], []}; end end % Capture summary table data. this.TaskResults('taskVerifyModel2Reqs') = {title, headers, data}; % Capture task execution outcome. this.TaskOutcomes('taskVerifyModel2Reqs') = outcome; this.TaskExceptions('taskVerifyModel2Reqs') = exception; catch ME % Throw exception if an error occurs. rethrow(ME); end end
taskGenSrcCode ()
Генерирует код из каждой зарегистрированной модели путем вызова либо:
Все модели в образце модели
genSrcCode('MODEL')
Все модели в модели верхнего уровня
genSrcCode('MODEL', 'TreatAsTopMdl')
Результат каждой итерации -1
(FAIL), если отчет генерации кода не был успешно сгенерирован. В противном случае это 1
(PASS).
function taskGenSrcCode(this) % This test point checks if Code Generation Reports generated % from models are successfully created by "genSrcCode". outcome = 1; exception = ''; counter = 0; try % Test generation of Code Generation Reports from models in % the project. for i = 1:numel(this.ModelNames) if this.isTopModel(this.ModelNames{i}) genSrcCode(this.ModelNames{i}, 'TreatAsTopMdl'); file = fullfile(this.ProjectDir, 'DO_04_Code', 'specification', [this.ModelNames{i}, '_ert_rtw'], 'html', [this.ModelNames{i}, '_codegen_rpt.html']); else genSrcCode(this.ModelNames{i}); file = fullfile(this.ProjectDir, 'DO_04_Code', 'specification', 'slprj', 'ert', this.ModelNames{i}, 'html', [this.ModelNames{i}, '_codegen_rpt.html']); end msg = ['Code Generation Report not created: ', this.ModelNames{i}, '_codegen_rpt.html.']; [outcome, exception, counter] = this.verifyFile (file, msg, exception, outcome, counter); end % Capture execution outcome. this.TaskOutcomes('taskGenSrcCode') = outcome; this.TaskExceptions('taskGenSrcCode') = exception; catch ME % Throw exception if an error occurs. rethrow(ME); end end
taskVerifyObjCode2Reqs ()
Проверяет код, сгенерированный из каждой зарегистрированной модели, на соответствие требованиям к программному обеспечению высокого уровня, которые она реализует, вызывая либо:
Все модели в образце модели
verifyObjCode2Reqs('MODEL', 'SIL', [], [], [], 'CI')
Все модели в модели верхнего уровня
verifyObjCode2Reqs('MODEL', 'SIL', [], 'TreatAsTopMdl', [], 'CI')
Результат каждой итерации определяется на основе возвращенных результатов верификации, и Simulink Test и Simulink Coverage Model Coverage сообщают о покрытии:
Результат следующий -1
(FAIL), когда в тесте есть ошибка или отказ, 0 (WARN), когда в тестовом примере есть предупреждение, или
1
(PASS).
Общий результат -1
(FAIL), когда отчет Simulink Test или отчет о покрытии модели не генерируется успешно. В противном случае это 1
(PASS).
function taskVerifyObjCode2Reqs(this) % This test point checks if Simulink Test and Code Coverage % Reports generated from models are successfully created by % "verifyObjCode2Reqs". outcome = 1; exception = ''; counter = 0; try % Test generation of Simulink Test and Code Coverage % Reports (for HLR EOC Tests) from models in the project. title = 'HLR SIL Tests'; headers = {'Model Name', 'Num Pass', 'Num Warn', 'Num Fail', 'Outcome'}; data = {}; for i = 1:numel(this.ModelNames) if exist(fullfile(this.ProjectDir, 'DO_03_Design', this.ModelNames{i}, 'test_cases', 'HLR', [this.ModelNames{i}, '_REQ_Based_Test.mldatx']), 'file') if this.isTopModel(this.ModelNames{i}) res = verifyObjCode2Reqs(this.ModelNames{i}, 'SIL', [], 'TreatAsTopMdl', [], 'CI'); else res = verifyObjCode2Reqs(this.ModelNames{i}, 'SIL', [], [], [], 'CI'); end data(i,:) = {this.ModelNames{i}, res.NumPass, res.NumWarn, res.NumFail, res.Outcome}; msg = ['High-level SIL test cases failed on ', this.ModelNames{i}, '.']; [outcome, exception, counter] = this.verifyOutcome (res.Outcome, msg, exception, outcome, counter); file = fullfile(this.ProjectDir, 'DO_04_Code', 'verification_results', 'eoc_test_results', this.ModelNames{i}, 'host', 'HLR', 'instrumented', [this.ModelNames{i}, '_INSTR_SIL_REQ_Based_Test_Report.pdf']); msg = ['EOC Test Report not created: ', this.ModelNames{i}, '_INSTR_SIL_REQ_Based_Test_Report.pdf.']; [outcome, exception, counter] = this.verifyFile (file, msg, exception, outcome, counter); file = fullfile(this.ProjectDir, 'DO_04_Code', 'verification_results', 'code_coverages', this.ModelNames{i}, 'host', 'HLR', [this.ModelNames{i}, '_REQ_Based_Code_Coverage_Report.html']); msg = ['Code Coverage Report not created: ', this.ModelNames{i}, '_REQ_Based_Code_Coverage_Report.html.']; [outcome, exception, counter] = this.verifyFile (file, msg, exception, outcome, counter); else data(i,:) = {this.ModelNames{i}, [], [], [], []}; end end % Capture summary table data. this.TaskResults('taskVerifyObjCode2Reqs') = {title, headers, data}; % Capture execution outcome. this.TaskOutcomes('taskVerifyObjCode2Reqs') = outcome; this.TaskExceptions('taskVerifyObjCode2Reqs') = exception; catch ME % Throw exception if an error occurs. rethrow(ME); end end
Чтобы определить новый метод задачи, рекомендуется изменить существующую задачу в DODemoTasks.m
для достижения намеченной цели работы. При создании новой задачи важно, чтобы вы:
Задайте уникальное имя задания. Для примера:
function taskCustomNamingStandards(this)
Захват результатов анализа при помощи:
TaskResults
для результатов каждой итерации задачи.
TaskOutcomes
для общих результатов выполнения, если применимо.
TaskExceptions
для исключений при возникновении ошибки.
% Capture summary table data. this.TaskResults('taskCustomNamingStandards') = {title, headers, data}; % Capture execution outcome. this.TaskOutcomes('taskCustomNamingStandards') = outcome; this.TaskExceptions('taskCustomNamingStandards') = exception; catch ME % Throw exception if an error occurs. rethrow(ME); end end
Добавьте новую задачу к TaskSequence
свойство.
properties TaskSequence = ["taskVerifyModel2Reqs" "taskCheckModelStds" "taskGenSrcCode" "taskVerifyObjCode2Reqs" "taskCustomNamingStandards"]; end
После настройки файла задания сборки важно протестировать задание перед настройкой проекта сборки в Jenkins. В этом примере вы используете runJob()
для тестирования сборки.
Чтобы протестировать все задание сборки, в MATLAB® в командной строке введите:
runJob(DODemoTasks)
Чтобы протестировать одну задачу в задании сборки, включите имя задачи как вход в runJob()
. Для примера, чтобы протестировать VerifyModel2Reqs()
, в командной строке MATLAB введите:
runJob(DODemoTasks, 'taskVerifyModel2Reqs')
Результаты задания сборки отображаются в командном окне MATLAB. Убедитесь, что задание выполнено успешно.
Теперь можно установить Jenkins, создать проект сборки Jenkins, выполнить сборку в Jenkins и просмотреть результаты.
Для использования среды CI в вашем DO-178C проекте требуется Jenkins. Для установки Jenkins:
В веб-браузере перейдите в www.jenkins.io и запустите загруженный инсталлятор. Чтобы завершить установку, следуйте инструкциям мастера настройки.
На панели управления Jenkins откройте Manage Jenkins > Manage Plugins.
На вкладке Available выберите и установите эти плагины, характерные для MathWorks:
MATLAB
Отображение сводки
Jenkins устанавливает как Windows® сервис. По умолчанию служба Jenkins запускается с использованием локальной системной учетной записи, которая не имеет разрешения на запуск MATLAB. Чтобы использовать учетную запись, имеющую соответствующие права, необходимо перезапустить службу Jenkins. Чтобы запустить сервис Jenkins с необходимыми полномочиями:
Откройте приложение Windows Services и найдите сервис Jenkins.
Щелкните правой кнопкой мыши по Jenkins и выберите Properties.
В диалоговом окне « Свойствах Jenkins» откройте вкладку Log On и выберите This account.
Введите данные учетной записи пользователя. В зависимости от настройки системы, вы можете только предоставить свой пароль.
Нажмите OK. Закройте диалоговое окно свойств Jenkins и перезагрузите компьютер.
Теперь можно создать проект сборки Дженкинса.
При создании проекта Jenkins управление применимыми данными должно осуществляться с помощью системы управления строением. Работа с системным администратором для интеграции файлов проекта в систему управления строением.
Чтобы создать проект Дженкинса для запуска задания сборки:
Убедитесь, что проект добавлен в систему управления строением.
Откройте инструментальную панель Jenkins и нажмите New Item. В поле Enter an item name укажите имя проекта. В данном примере введите DODemoTasks
.
Выберите Freestyle project и нажмите OK.
(Необязательно) На вкладке General предоставьте описание проекта.
На вкладке Source Code Management выберите Subversion и выполните следующее:
В поле Repository URL укажите местоположение репозитория системы контроля версий. Можно получить эту информацию из проекта DO-178C, щелкнув вкладку Project и просматривая содержимое Source Control. Для примера, если вы использовали Subversion™ Apache в качестве системы управления строения, нажмите SVN Details, чтобы получить URL-адрес репозитория subversion.
(Необязательно) При необходимости используйте Credentials для добавления пользователей, которые могут получить доступ к репозиторию subversion.
В поле Local module directory проверьте, что значение равно ".
"- не включать предложения. Это значение извлекает проект непосредственно в рабочую область Jenkins.
(Необязательно) Используйте опции на вкладке Build Triggers , чтобы указать, как вы хотите начать задание сборки. В данном примере не выбирайте опцию, поскольку вы вручную выполняете задание. Если вы не выбираете одну из опций, необходимо вручную запустить задание сборки.
Откройте вкладку Build Environment и выберите:
Delete workspace before build starts
Add timestamps to the Console Output
Use MATLAB version. Для этого MATLAB root укажите полный путь к папке установки MATLAB. Чтобы определить путь, в командной строке MATLAB введите:
matlabroot()
Откройте вкладку Build и выберите Add build step > Run MATLAB Command. В Command поле введите:
cd('.\continuous_integration\job'); runJob(DODemoTasks);
Если применимо, замените DODemoTasks
с именем вашего Дженкинса построить работу.
Откройте вкладку Post-build Actions и задайте следующие действия после сборки:
Чтобы архивировать программные продукты, выберите Add post-build action > Archive the artifacts. В Files to archive поле введите:
**\*.slxc, continuous_integration\reports\*.xml
Чтобы опубликовать сводные отчеты XML, щелкните Add post-build action > Publish XML Summary Reports. В Files to parse поле введите:
continuous_integration\reports\*.xml
Нажмите Save. The DODemoTasks
проект указан на панели управления Jenkins. Чтобы внести изменения в проект, выберите проект и нажатие кнопки Configure.
Теперь можно выполнить сборку в Jenkins и просмотреть результаты.
Чтобы выполнить задание сборки и просмотреть результаты:
На панели управления Jenkins нажмите DODemoTasks
проект.
Нажмите кнопку Build Now, чтобы вручную выполнить задание.
Завершенные задания добавляются на панель Build History. Выберите только что выполненную сборку и проверьте результаты.
Результаты сохраняются в continuous_integration>reports
папка проекта:
Сводные данные сборки - общие результаты для каждой задачи задания сборки Дженкинса.
Сводные данные результатов верификации - результаты для отдельных итераций задач с детализированными результатами в табличном формате.
Непрерывное интегрирование для верификации моделей Simulink | Разрабатывайте и интегрируйте программное обеспечение с непрерывным интегрированием | Рабочий процесс непрерывного интегрирования (Simulink Check)