Revit Test Framework: 为Dynamo量身定做的测试系统

RevitTestFramework

RevitTestFrameworkAutodesk 提供的针对 Dynamo For Revit 的开源测试框架:https://github.com/DynamoDS/RevitTestFramework
这个框架除了蕴含了D4R测试机制以外,还包含了 Revit 二次开发测试难得解决方案,很有借鉴意义,但需要专业开发人员自己阅读代码才能找到它的核心所在。

运行方式

它有两种运行方式,命令行和GUI。

命令行

如下面这个例子所示:

RevitTestFrameworkConsole.exe --dir C:\MyTestDir -a MyTest.dll -r MyTestResults.xml -revit:"C:\Program Files\Autodesk\Revit 2019\Revit.exe" --continuous

执行 C:MyTestDir 目录下 Mytest.dll 中所有的测试,并且把所有的测试结果放到同目录夹下的 MyTestResults.xml 文件中。
测试代码里面所有使用了的地方 Console.WriteLineConsole.Error.WriteLine 的地方都会显示在命令行里面,同时记录到输出的 XML 文件中,如下面这个例子:

Reading assembly: D:\MyTestDir\MyTest.dll
Loaded test: Name: UnitTest1, Model Path: D:\MyTestDir\MyModel1.rvt (D:\MyTestDir\MyModel1.rvt)
Loaded test: Name: UnitTest2, Model Path: D:\MyTestDir\MyModel2.rvt (D:\MyTestDir\MyModel2.rvt)
Running D:\Projects\UpCodes\upcodes_revit\Tests\2019\bin\Debug\RTF_Batch_Test.txt
Running UnitTest1 in BasicTests
Success: UnitTest1 in BasicTests

Running UnitTest2 in BasicTests
Success: UnitTest2 in BasicTests

Waiting for Revit to terminate
WARNING: One or more journal files could not be deleted.

一个运行单个DynamoRevit自带的测试的例子(需要自己替换掉[]中的内容):

RevitTestFrameworkConsole.exe --dir [DynamoRevit]\test\System -a [DynamoRevit]\bin\AnyCPU\Debug\Revit\RevitSystemTests.dll -r [DynamoRevit]\bin\AnyCPU\Debug\Revit\MyTestResults.xml -revit:"[Revit Install]\Revit.exe" --testName=[Test Name]

GUI

RevitTestFrameworkGUI.exe

在这里插入图片描述
UI界面和命令行本质上是一样的,可以互相对照。

原理和逻辑

在跑测试的时候,你会发现,Revit启动了,而且自动在运行。这是怎么发生的呢?
首先,你要了解 Revit 的journal。
然后,你要了解插件的journal 是如何产生的。
最后,你还必须知道如果用C#来启动Revit来运行这个journal。
下面的内容就比较偏向于软件了,得益于这是一个开源的框架,实际上用户可以自行调试来发现其中的逻辑。

准备工作

Revit 从2020 开始,都只确保一个对应版本的Dynamo For Revit,虽然降低了灵活性,但是也简化了开发过程。各个版本之间理论上,可以想办法来进行兼容性处理,但是对于普通开发者过于困难。
在这里,我用的Revit 2020,打开我的Dynamo For Revit,查看版本信息。

Dynamo Core 2.1.0.7500
Dynamo Revit 2.1.0.7733

Dynamo 版本信息
作为开发者,你需要去 Github 上找到对应的分支:

Dynamo Core 2.1.0.7500 -> https://github.com/DynamoDS/Dynamo/tree/RC2.1.0_master
Dynamo Revit 2.1.0.7733 -> https://github.com/DynamoDS/DynamoRevit/tree/RC2.1.0_Revit2020

只有把对应的分支克隆下来,才能保证你可以正常的进行开发。否则,你需要自己去保证兼容性。在保证你本地有了Dynamo相关的代码,并且顺利编译成功之后,你才能开始进行程序开发和测试的编写。

测试的Journal是如何生成的

选择单独跑一个测试,CurveByPoints,去掉 Continuous 和 Group by model 选项。设置好断点,得到如下callstack:
在这里插入图片描述
这个journal的内容:

'Dim Jrn 
Set Jrn = CrsJournalScript 
Jrn.Command "StartupPage" , "Open this project , ID_FILE_MRU_FIRST" 
Jrn.Data "MRUFileName"  , "E:\GitHub\DynamoRevit\test\System\empty.rfa" 
Jrn.RibbonEvent "Execute external command:487f9ff0-5b34-4e7e-97bf-70fbff69194f:RTF.Applications.RevitTestFramework" 
Jrn.Data "APIStringStringMapJournalData", 6, "testName", "CurveByPoints", "fixtureName", "CurveTests", "testAssembly", "E:\GitHub\DynamoRevit\bin\AnyCPU\Debug\Revit\RevitSystemTests.dll", "resultsPath", "E:\GitHub\DynamoRevit\bin\AnyCPU\Debug\Revit\results.xml", "debug","False","workingDirectory","E:\GitHub\DynamoRevit\test\System" 
Jrn.Command "Internal" , "Flush undo and redo stacks , ID_FLUSH_UNDO" 
Jrn.Command "SystemMenu" , "Quit the application; prompts to save projects , ID_APP_EXIT"

实际上测试界面也会有显示,只是通常跑完之后会删除掉,如下:

17:05:56 Reading assembly: E:\GitHub\DynamoRevit\bin\AnyCPU\Debug\Revit\RevitSystemTests.dll
17:06:12 Running E:\GitHub\DynamoRevit\test\System\CurveByPoints.txt
17:07:06 ......................................................
17:07:06 Test run completed successfully: 1 passed, 0 skipped, 0 failed

Journal 是如何跑起来的

如下所示,自己起一个process,设置好相应的参数即可:
在这里插入图片描述

Journal里面到底做了什么?

下面这个才是 RevitTestFramework 的核心,通过它,可以从journal 里面读取参数,然后让一个测试正常地运行起来。
RevitTestFramework\src\Applications\RTFRevit\RevitTestFramework.cs

    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    [Journaling(JournalingMode.UsingCommandData)]
    public class RevitTestFramework : IExternalCommand, IConsoleTraceListener
    {
        public Result Execute(ExternalCommandData cmdData, ref string message, ElementSet elements)
        {
            using (var consoleInterceptor = new ConsoleOutInterceptor(this))
            {
                Setup(cmdData);

                var exe = new RevitTestExecutive();
                return exe.Execute(cmdData, ref message, elements);
            }
        }

        private void Setup(ExternalCommandData cmdData)
        {
            IDictionary<string, string> dataMap = cmdData.JournalData;

            if (dataMap.ContainsKey("debug") && dataMap["debug"].ToLower() == "true")
            {
                Debugger.Launch();
            }

            NUnitFrameworkResolver.Setup();
        }

        public void OnConsoleOutLine(string text)
        {
            RTFClientStartCmd.SendConsoleMessage(text);
        }

        public void OnErrorOutLine(string text)
        {
            RTFClientStartCmd.SendConsoleMessage(text, Framework.ConsoleMessageType.ErrorOut);
        }
    }
发布了33 篇原创文章 · 获赞 12 · 访问量 9580

猜你喜欢

转载自blog.csdn.net/weixin_44153630/article/details/103659572