mcpField
M
matlab-testing

matlab-testing

github.com/matlab测试与质量1.2k76 次安装1 天前更新
代码仓库

关于 matlab-testing

matlab-testing 是一项使用 matlab.unittest 框架编写和运行 MATLAB 单元测试的技能,面向 MATLAB 开发者。内容涵盖类测试、覆盖率、CI/CD 和 App Designer 测试,并通过 MCP 工具执行测试。

主要功能

  1. 01基于类的单元测试结构
  2. 02参数化测试、夹具与模拟对象
  3. 03通过 MCP 运行测试并分析结果
  4. 04覆盖率分析与 CI/CD 指引
  5. 05App Designer 界面测试指引

适用场景

  1. 01为 MATLAB 函数和类编写测试
  2. 02运行测试套件并检查失败项
  3. 03查找覆盖率缺口并配置 CI
  4. 04使用界面操作测试 App Designer 应用

MCP 相关

该技能要求通过 run_matlab_test_file 和 evaluate_matlab_code MCP 工具执行测试。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/matlab/matlab-agentic-toolkit --skill matlab-testing

安装后在 Claude Code 中输入/matlab-testing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

manifest.yaml
reference/
app-testing-guidance.md
constraints-guidance.md
fixtures-guidance.md
mocking-guidance.md
parameterized-tests-guidance.md
test-execution-guidance.md
scripts/
printCoverageGaps.m

详细介绍

测试

使用 matlab.unittest 框架生成、组织和运行 MATLAB 单元测试。涵盖基于类的测试、参数化测试、固定装置、模拟、覆盖率分析、CI/CD 集成,以及通过 MCP 进行应用测试。

适用场景

  • 用户要求为 MATLAB 函数或类编写测试
  • 用户想运行现有测试套件
  • 用户需要覆盖率分析或 CI/CD 配置
  • 测试驱动开发——在实现之前编写测试
  • 使用程序化手势测试 App Designer 应用(参见 reference/app-testing-guidance.md)

不适用场景

  • 测试 Simulink 模型——使用 Simulink 测试技能
  • 性能基准测试——使用性能分析工作流

必须遵守的规则

  • 先提交测试计划 — 对于非简单的测试套件,在编写代码前,提出测试方法和边缘情况供用户批准
  • 始终使用基于类的测试 — 每个测试文件都必须继承 matlab.unittest.TestCase。绝不使用基于脚本的测试
  • 测试方法中不包含逻辑 — 不得使用 if、switch、for 或 try/catch。遵循 Arrange-Act-Assert。如果测试需要条件判断,应拆分为多个方法
  • 测试公共接口,而非实现 — 绝不直接测试私有方法
  • 通过 MCP 执行 — 使用 run_matlab_test_file 或 evaluate_matlab_code 运行测试

工作流

简单测试(行为明确、范围有限)
  1. 简要说明要测试的内容(方法和关键边缘情况)
  2. 用户确认后编写测试文件
标准测试(大型代码库、多个文件)
  1. 收集需求 — 要测试的代码、预期行为、错误条件、范围和依赖项
  2. 提交测试计划 — 列出测试方法、边缘情况和参数化策略,供用户批准
  3. 实现 — 按照以下模式编写测试
  4. 运行 — 使用 run_matlab_test_file MCP 工具执行
  5. 检查覆盖率 — 找出未测试的路径并补充测试

关键函数

类别函数用途
相等性verifyEqual、verifyNotEqual比较值(浮点数使用 AbsTol)
布尔值verifyTrue、verifyFalse检查逻辑条件
大小/类型verifySize、verifyClass、verifyEmpty结构检查
错误verifyError确认抛出具有正确 ID 的错误
警告verifyWarning、verifyWarningFree检查警告行为
基础设施runtests、TestSuite、TestRunner运行和组织测试
覆盖率CodeCoveragePlugin、CoverageResult衡量测试覆盖率
资格级别
级别失败时使用场景
verify继续测试默认——适用于大多数断言
assert停止当前测试验证设置
fatal停止整个套件环境前置条件
assume跳过测试条件执行(例如,检查工具箱)

模式

基本测试类
classdef computeAreaTest < matlab.unittest.TestCase
    %computeAreaTest Tests for the computeArea function.

    methods (Test)
        function testSquare(testCase)
            result = computeArea(5, 5);
            testCase.verifyEqual(result, 25);
        end

        function testFloatingPoint(testCase)
            result = computeArea(1/3, 3);
            testCase.verifyEqual(result, 1, AbsTol=1e-12);
        end

        function testNegativeInputErrors(testCase)
            testCase.verifyError( ...
                @() computeArea(-1, 5), 'computeArea:negativeInput');
        end
    end
end
参数化测试

仅当所有用例的断言逻辑相同时才进行参数化——变化的只有数据。使用 struct 编写易读的测试名称:

classdef unitConverterTest < matlab.unittest.TestCase

    properties (TestParameter)
        conversionCase = struct( ...
            'freezing', struct('input', 0, 'expected', 32), ...
            'boiling',  struct('input', 100, 'expected', 212), ...
            'bodyTemp', struct('input', 37, 'expected', 98.6));
    end

    methods (Test)
        function testCelsiusToFahrenheit(testCase, conversionCase)
            result = celsiusToFahrenheit(conversionCase.input);
            testCase.verifyEqual(result, conversionCase.expected, AbsTol=1e-10);
        end
    end
end

有关高级参数化(组合、动态参数、ClassSetupParameter),请参见 reference/parameterized-tests-guidance.md。

设置、拆解和固定装置

优先使用 addTeardown,而不是 TestMethodTeardown 代码块。使用 PathFixture 添加源文件夹:

classdef fileProcessorTest < matlab.unittest.TestCase

    methods (TestClassSetup)
        function addSourceToPath(testCase)
            srcFolder = fullfile(fileparts(fileparts(mfilename('fullpath'))), 'src');
            testCase.applyFixture(matlab.unittest.fixtures.PathFixture(srcFolder, ...
                IncludingSubfolders=true));
        end
    end

    methods (Test)
        function testProcessFile(testCase)
            tmpDir = string(tempname);
            mkdir(tmpDir);
            testCase.addTeardown(@() rmdir(tmpDir, 's'));

            testFile = fullfile(tmpDir, "data.csv");
            writematrix(rand(10, 3), testFile);

            result = processFile(testFile);
            testCase.verifySize(result, [10 3]);
        end
    end
end

有关内置固定装置、自定义固定装置和共享固定装置,请参见 reference/fixtures-guidance.md。

确定性

设置 RNG 种子,并在拆解时恢复,以确保测试可复现:

methods (TestMethodSetup)
    function resetRandomSeed(testCase)
        originalRng = rng;
        testCase.addTeardown(@() rng(originalRng));
        rng(42, "twister");
    end
end
测试标签

使用 TestTags 进行选择性执行:

methods (Test, TestTags = {'Unit'})
    function testFastCalculation(testCase)
        % ...
    end
end

methods (Test, TestTags = {'Integration', 'Slow'})
    function testFullPipeline(testCase)
        % ...
    end
end

按标签运行:runtests('tests', Tag='Unit'),或 runtests('tests', ExcludeTag='Slow')。

运行测试

通过 MCP

对测试文件使用 run_matlab_test_file MCP 工具。若要内联运行并进行筛选:

results = runtests('tests');                            % all tests in folder
results = runtests('tests', Tag='Unit');                % by tag
results = runtests('tests', Name='*Calculator*');       % by name pattern
results = runtests('tests', UseParallel=true);          % parallel execution
results = runtests('tests', Strict=true);               % warnings = failures
分析结果
disp(results);

for r = results([results.Failed])
    fprintf('\nFAILED: %s\n', r.Name);
    disp(r.Details.DiagnosticRecord.Report);
end

覆盖率分析

import matlab.unittest.TestRunner
import matlab.unittest.plugins.CodeCoveragePlugin
import matlab.unittest.plugins.codecoverage.CoverageResult
import matlab.unittest.plugins.codecoverage.CoverageReport

runner = TestRunner.withTextOutput;
covFormat = CoverageResult;
runner.addPlugin(CodeCoveragePlugin.forFolder('src', ...
    Producing=[covFormat, CoverageReport('coverage-report')]));
results = runner.run(testsuite('tests'));

covResults = covFormat.Result;
disp(covResults);

如需分析覆盖率缺口,请使用 reference/test-execution-guidance.md 中的 printCoverageGaps 脚本。

CI/CD 集成

在 CI 流水线中使用 buildtool 和 buildfile.m。有关 buildfile.m 模板和 CI 配置(GitHub Actions、Azure DevOps、GitLab CI),请参阅 reference/test-execution-guidance.md。

App Designer 测试

有关使用程序化 UI 手势(press、choose、type、drag)测试应用,请参阅 reference/app-testing-guidance.md。

要点:

  • 继承自 matlab.uitest.TestCase(而非 matlab.unittest.TestCase)
  • 创建应用后、执行第一个手势前,调用 drawnow
  • 比较 uilabel.Text 时使用 char('text'),而非 string("text")
  • 使用 matlab.lang.OnOffSwitchState.on/.off 比较 .Enable

参考资料

按需加载——大多数测试只需要本文件中的内容。

加载时机……参考资料
测试需要设置/拆卸、临时目录、路径管理、共享状态reference/fixtures-guidance.md
选择浮点容差、约束对象、自定义约束reference/constraints-guidance.md
多个参数、动态参数、组合策略reference/parameterized-tests-guidance.md
代码依赖外部服务,需要模拟对象或依赖注入reference/mocking-guidance.md
在 CI 中运行测试、配置 buildtool、分析覆盖率缺口reference/test-execution-guidance.md
使用手势、对话框、异步回调测试 App Designer 应用reference/app-testing-guidance.md

约定

  • 始终使用继承自 matlab.unittest.TestCase 的基于类的测试
  • 将测试文件命名为 <functionName>Test.m,并放在 tests/ 目录中
  • 默认使用 verify 断言——即使某项测试失败,也能让所有测试继续运行
  • 每次浮点数比较都使用 AbsTol——绝不依赖精确相等
  • 测试方法中不写逻辑——遵循 Arrange-Act-Assert
  • 使用 addTeardown 进行清理——即使测试失败,也会执行清理
  • 使用基于 struct 的 TestParameter,让参数化测试名称更易读
  • 保持测试方法专注——每个方法测试一种行为
  • 测试必须相互独立,并兼容并行执行
  • 通过 run_matlab_test_file MCP 工具运行测试,以自动捕获结果

Copyright 2026 The MathWorks, Inc.


评论

支持 Markdown