尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Windows Terminal(OpenConsole)的 TAEF 测试实战:编写、运行与调试 C++ 单元测试

Windows Terminal(OpenConsole)的 TAEF 测试实战:编写、运行与调试 C++ 单元测试 Windows TerminalOpenConsole的 TAEF 测试实战编写、运行与调试 C 单元测试【免费下载链接】terminalThe new Windows Terminal and the original Windows console host, all in the same place!项目地址: https://gitcode.com/GitHub_Trending/term/terminal本文基于仓库文档 doc/TAEF.md 展开讲解 Windows Terminal 及其原生控制台宿主OpenConsole 项目所使用的 TAEFTest Authoring and Execution Framework测试框架如何用TEST_CLASS/TEST_METHOD宏编写 C 测试、如何通过razzle.cmd准备开发环境并用te.exe运行与过滤测试、如何用 PowerShell 模块批量执行全套单元测试以及使用/waitForDebugger附加调试器的完整调试流程。读完本文你可以在该仓库中独立编写、定位并调试一个 TAEF 测试用例。一、为什么 Windows 控制台项目选择 TAEFTAEF 是微软 Windows 组织内部广泛使用的统一测试框架用于以同一套体系测试系统、驱动与应用代码。由于控制台Console本身是 Windows 操作系统的组成部分该项目延续使用 TAEF 的核心动机是测试的统一性同一批测试既能在微软官方构建/测试系统OS Build/Test system中运行也能在外部开源仓库克隆环境以一致的方式运行。从仓库中可以看到这一点的具体体现测试元数据以TESTLIST文件形式与代码放在一起Source Is Truth 思路例如 src/testlist/ 目录下的Microsoft.Console.Tests.testlist等文件它们把各组件的单元测试打包描述串联起来。更完整的内部测试打包机制TESTMD/TESTLIST/TESTPASSES/TREX见 doc/UniversalTest.md本文不展开。TAEF 的使用方式与 Visual Studio Test 类似但更通用、更灵活。其架构与功能在微软官方的 TAEF 文档中有完整描述属于 Windows 硬件驱动文档体系本文按仓库文档指引不再外链。二、编写 TAEF 测试用例2.1 基本结构宏驱动的测试类与测试方法TAEF 测试用 C 编写核心是WexTestClass.h提供的一组宏。以仓库中真实存在的 TextBuffer 单元测试 src/buffer/out/ut_textbuffer/TextAttributeTests.cpp 为例#include precomp.h #include WexTestClass.h #include ../../inc/consoletaeftemplates.hpp #include ../TextAttribute.hpp using namespace WEX::Common; using namespace WEX::Logging; using namespace WEX::TestExecution; class TextAttributeTests { TEST_CLASS(TextAttributeTests); // 声明测试类 TEST_CLASS_SETUP(ClassSetup); // 类级别的初始化钩子 TEST_METHOD(TestRoundtripLegacy); // 声明一个测试方法 TEST_METHOD(TestRoundtripMetaBits); TEST_METHOD(TestRoundtripExhaustive); // ... }; bool TextAttributeTests::ClassSetup() { _renderSettings.SetColorAlias(ColorAlias::DefaultForeground, _defaultFgIndex, _defaultFg); _renderSettings.SetColorAlias(ColorAlias::DefaultBackground, _defaultBgIndex, _defaultBg); return true; } void TextAttributeTests::TestRoundtripLegacy() { WORD expectedLegacy FOREGROUND_BLUE | BACKGROUND_RED; auto attr TextAttribute(expectedLegacy); VERIFY_IS_TRUE(attr.IsLegacy()); // 断言为真 VERIFY_ARE_EQUAL(expectedLegacy, attr.GetLegacyAttributes()); // 断言两值相等 }从源码结构看各宏的分工为宏作用TEST_CLASS(Name)声明一个测试类TAEF 据此发现并枚举类中所有测试TEST_METHOD(Name)声明一个可被te.exe执行的测试方法对应/name:过滤中的方法名TEST_CLASS_SETUP(Func)指定类级初始化函数在所有测试方法执行前运行一次返回bool表示成功与否TEST_METHOD_SETUP/TEST_METHOD_CLEANUP方法级前后置钩子TAEF 通用能力写法同上述宏族仓库文档 doc/TAEF.md 特别提示了一个常见困惑官方文档中#include WexTestClass.h的头文件名看起来像是要求你手动拷贝 TAEF 头文件实际上并不需要——该头文件由 NuGet 包Microsoft.Taef提供包含在项目的 include 搜索路径中即可仓库中 src/cascadia/LocalTests_TerminalApp/pch.h 使用WexTestClass.h尖括号形式src/buffer/out/ut_textbuffer/TextAttributeTests.cpp 使用引号形式两者都依赖包提供的头文件无需复制进项目目录。2.2 验证宏Verify Macros断言统一使用 TAEF 的 Verify 宏族完成在上面的示例中可以看到两类典型用法VERIFY_ARE_EQUAL(expected, actual)比较两个值是否相等失败时报告会输出两者的实际值VERIFY_IS_TRUE(condition)断言布尔条件为真VERIFY_SUCCEEDED(hresult)断言 HRESULT 成功SUCCEEDED语义仓库的测试模板头 src/inc/consoletaeftemplates.hpp 中即有VERIFY_SUCCEEDED(TestData::TryGetValue(...))的实际用法。此外还有VERIFY_IS_FALSE、VERIFY_THROWS等同族宏具体列表以 TAEF 官方文档中的 Verify Macros for C 一节为准仓库文档指引读者动手前先阅读该章节。2.3 仓库自有的测试模板头consoletaeftemplates.hpp为了让控制台相关类型COORD、SMALL_RECT等能在 Verify 宏里正确打印仓库提供了公共模板头 src/inc/consoletaeftemplates.hpp其中包含VerifyOutputTraitsT的各类特化使 Verify 宏失败时能输出可读的类型表示INIT_TEST_PROPERTY(type, identifier, description)宏用于声明并初始化一个TEST_METHOD_PROPERTY元数据变量见文件开头注释L24-L27面向数据驱动测试的适配器例如ArrayIndexTaefAdapterRow继承WEX::TestExecution::IDataRow配合 TAEF 的IDataSource接口可以把数组、表格数据作为TEST_DATA_ROW的参数化数据源。该文件头部还有一段值得注意的“踩坑注释”L29-L46为某个新类型添加VerifyOutputTraits特化时必须确保每个使用对应 Verify 宏的 cpp 文件都包含了该头文件至少包含相关定义否则可能触发 ODR单一定义规则违例链接器会从多个 obj 中任选一份定义导致运行期行为与源码不一致的诡异现象。三、准备开发环境tools/razzle.cmd在普通 CMD 环境中te.exeTAEF 测试运行器并不在 PATH 上。仓库文档给出的入口命令是.\tools\razzle.cmdtools/razzle.cmd 的实际动作逐行阅读脚本可以确认若环境变量OpenConBuild已设置则直接跳过避免重复初始化把仓库根目录工具目录OPENCON_TOOLS与仓库根OPENCON相关路径加入 PATH并把dep\nuget加入 PATH执行nuget restore针对OpenConsole.slnx和 dep/nuget/packages.config确保Microsoft.Taef等包已还原从而可以使用vswhere优先复用 PATH 上已有的msbuild.exe否则通过vswhere定位 VS版本范围[17.0,19.0)即 VS 2022 17.x 与 VS 18接受预发布版下的 MSBuild并将其目录加入 PATH找不到时会提示先打开 Developer 命令行或用Set-MsbuildDevEnvironment按处理器架构设置ARCHx64/x86与PLATFORMx64/Win32默认配置DEFAULT_CONFIGURATIONDebug设置关键变量TAEF%OPENCON%\packages\Microsoft.Taef.10.100.251104001\build\Binaries\%ARCH%\TE.exeL133即“与测试构建架构匹配的te.exe”若存在tools\.razzlerc.cmd则调用它做个人化环境定制否则自动创建模板文件支持位置参数razzle dbg/rel切换默认配置为 Debug/Releaserazzle x86切换架构。脚本头部注释也点明了它的定位把 msbuild 加进 PATH、把 tools 目录加进 PATH“重现真实 Windows 开发者的体验”。执行完成后你就可以把%TAEF%当作te.exe的别名使用。前置条件已安装 Visual Studio 及相应 C 组件且 NuGet 包还原成功Microsoft.Taef包还原后te.exe才在本地可用。四、运行测试4.1 直接用 te.exe 运行在准备好环境%TAEF%可用后最基本的运行方式是执行与测试 DLL 架构一致x86/x64的te.exete.exe Console.Unit.Tests.dll仓库文档中使用的Console.Unit.Tests.dll是示例占位名你可以替换为任何需要运行的测试二进制名。te.exe还支持通配符与多二进制一次指定多个测试 DLL 或通配模式找到的所有测试都会被执行。这正是 tools/runut.cmd 的做法——一次性把仓库全部单元测试二进制传给%TAEF%%TAEF% ^ %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\Conhost.Unit.Tests.dll ^ %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\TextBuffer.Unit.Tests.dll ^ %OPENCON%\bin\%PLATFORM%\%_LAST_BUILD_CONF%\UnitTests_TerminalCore\Terminal.Core.Unit.Tests.dll ^ ...types、til、terminal、adapter、control 等/name:过滤只运行匹配“类名::方法名”模式的测试支持通配符te.exe Console.Unit.Tests.dll /name:*BufferTests*这是排查单个失败用例时最常用的手段调试章节的示例/name:TextBufferTests::TestInsertCharacter即基于精确的“类::方法”形式。内置帮助te.exe /!输出 TAEF 运行器自带的功能说明更多细节以 TAEF 官方文档的 Executing Tests 一节为准。4.2 用 PowerShell 模块批量运行Invoke-OpenConsoleTests仓库文档推荐的 PowerShell 入口Import-Module .\tools\OpenConsole.psm1 Invoke-OpenConsoleTeststools/OpenConsole.psm1 中的Invoke-OpenConsoleTests默认只运行单元测试完整参数如下可用Invoke-OpenConsoleTests -?查看帮助参数类型默认值说明-AllTestsswitch关运行 tests.xml 中定义的全部测试unit ft-FTOnlyswitch关只运行功能测试ft-Teststring无只运行指定的一组测试取值限定为host、interactivityWin32、terminal、adapter、feature、uia、textbuffer、til、types、terminalCore、terminalApp、localTerminalApp、unitSettingsModel、unitControl、winconpty-TaefArgsstring[]无透传给te.exe的附加参数例如/name:...-Platformstringx64x64或x86内部映射为输出目录Win32-ConfigurationstringDebugDebug或Release三个选择开关-AllTests/-FTOnly/-Test互斥同时给出多个会直接报错退出psm1 L192-L196。其内部实现有几个值得了解的细节psm1 L206-L256测试清单来自 tools/tests.xml与runut.cmd/runft.cmd保持同步tests.xml 头部注释要求同步维护。当前清单为nametypebinaryhostunitConhost.Unit.Tests.dlltextBufferunitTextBuffer.Unit.Tests.dllterminalCoreunitUnitTests_TerminalCore\Terminal.Core.Unit.Tests.dllterminalAppunitUnitTests_TerminalApp\Terminal.App.Unit.Tests.dlllocalTerminalAppunitTestHostApp\TerminalApp.LocalTests.dllunitSettingsModelunitUnitTests_SettingsModel\SettingsModel.Unit.Tests.dllisolatedTaeftrueunitControlunitUnitTests_Control\Control.Unit.Tests.dllinteractivityWin32unitConhost.Interactivity.Win32.Unit.Tests.dllterminalunitConParser.Unit.Tests.dlladapterunitConAdapter.Unit.Tests.dlltypesunitTypes.Unit.Tests.dlltilunittil.unit.tests.dllfeatureftConhost.Feature.Tests.dlluiaftConhost.UIA.Tests.dllwinconptyftwinconpty.Feature.Tests.dllunit 与 ft 的执行方式不同typeunit的测试直接在当前进程执行 $currentTaefExe $BinDir\$($t.binary)typeft功能测试通过Invoke-TaefInNewWindow启动一个新的 OpenConsole 窗口来跑脚本注释特别说明uia 测试会移动鼠标测试期间不能操作鼠标。WinAppDriver 的自动启停当选择-AllTests、-FTOnly或-Test uia时模块会自动拉起 dep/WinAppDriver/ 中的WinAppDriver.exe测试结束后Stop-Process停掉它。isolatedTaef的特殊处理标记为isolatedTaeftrue的条目当前是 SettingsModel 单元测试不使用共享的%TAEF%而是用其输出目录自带的te.exetools/runut.cmd 中也用同一目录的te.exe单独执行SettingsModel.Unit.Tests.dll并保证即使前面的测试失败_EarlyTestFail也执行完它后再按最早的错误码退出。te.exe 的定位路径为%root%\packages\Microsoft.Taef.10.100.251104001\build\Binaries\$Platform\te.exe与 razzle 设置的%TAEF%一致。模块还顺带提供Invoke-OpenConsoleBuildnuget restore msbuild 构建解决方案、Start-OpenConsole、Debug-OpenConsole启动并附加默认调试器、Invoke-CodeFormat/Test-XamlFormat等辅助函数构成完整的开发工作流。另外两个传统 CMD 入口与 tests.xml 对应tools/runut.cmd全部单元测试与 tools/runft.cmd功能测试call %TAEF% ... ConHost.Feature.Tests.dll。注意runft会call而不是直接返回且依赖TAEF/ARCH等变量因此通常先执行razzle.cmd。4.3 在 Visual Studio 里直接跑测试仓库文档明确提醒不建议直接通过 Visual Studio 运行 TAEF 测试。Microsoft.Taef包自带一个适配器允许在 VS 中浏览并执行 TAEF 测试但其性能与可靠性不足以被推荐。日常开发应以te.exe命令行或 PowerShell 模块为准。4.4 NuGet 包的版本与集成点te.exe与 TAEF 头文件都来自Microsoft.TaefNuGet 包当前仓库锁定版本为10.100.251104001可从以下文件互相印证dep/nuget/packages.config声明package idMicrosoft.Taef version10.100.251104001 targetFrameworknative /src/common.nugetversions.props定义TAEFPackagePathRoot指向packages\Microsoft.Taef.10.100.251104001src/common.nugetversions.targets当 MSBuild 属性TerminalTAEF为true时导入Microsoft.Taef.targets把 TAEF 链接/构建逻辑注入测试工程并在包缺失时报错。也就是说测试工程是否走 TAEF 构建管线由TerminalTAEF属性控制包还原之后头文件、te.exe与 targets 都齐备——这也是“必须先成功还原 NuGet”这一前提的来源。五、调试测试TAEF 提供/waitForDebugger标志用于让测试“先挂起、等调试器附加”。仓库文档给出的完整流程runut *Tests.dll /name:TextBufferTests::TestInsertCharacter /waitForDebugger把测试名替换成你要调试的“类::方法”*Tests.dll为对应的测试二进制通配。执行后 TAEF 会开始执行测试并输出类似TAEF: Waiting for debugger - PID some PID IP some IP address此时在任意调试器中附加到该 PIDVisual StudioDebug - Attach To Process选择输出中的进程或 WinDbg 等任意调试器。附加完成后测试才会真正开始执行断点即可生效。这种方式特别适合“测试在 CI 中失败、本地偶现”的场景先用/name:过滤到唯一用例再挂起等待附加逐行观察测试初始化TEST_CLASS_SETUP与被测代码的执行路径。六、小结回到 doc/TAEF.md 的核心脉络TAEF 让 Windows 控制台组件的测试在内部 OS 构建系统与普通开发者环境中“同一套方式”运行开发者侧的日常闭环是在src/组件/ut_*或src/cascadia/UnitTests_*等目录中用TEST_CLASS/TEST_METHOD Verify 宏编写测试复用 src/inc/consoletaeftemplates.hpp 的模板能力运行.\tools\razzle.cmd建立环境获得%TAEF%即架构匹配的te.exe用te.exe 测试DLL /name:类::方法或Invoke-OpenConsoleTests参数见 tools/OpenConsole.psm1 与清单 tools/tests.xml运行遇到疑难用例时用/waitForDebugger挂起并附加调试器定位。所有命令均要求测试二进制的架构x86/x64与所用te.exe架构一致这是使用 TAEF 运行测试时唯一需要时刻牢记的约束。【免费下载链接】terminalThe new Windows Terminal and the original Windows console host, all in the same place!项目地址: https://gitcode.com/GitHub_Trending/term/terminal创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表