Skip to content

Write a Unit Test Library for Dynamo

ikeough edited this page Nov 27, 2014 · 10 revisions

This article provides all the information you need to create unit tests for your Dynamo library. Dynamo uses the NUnit framework for all of its unit testing. Additionally, the Revit Test Framework has been developed to enable unit testing on top of Revit.

There are two types of tests that you will find in the Dynamo project, and which you might want to make for your library, unit tests and system tests. Unit tests test small "units" of code, like methods, while system tests test the entire system similar to the way in which a user would use it. System tests typically create a Dynamo session, open a Dynamo file, evaluate it, and ensure that the returned results are what you'd expect.

There are thousands of tests available in the Dynamo source if you need to see how to write a test. For example, CoreNodesTests contains unit tests for Dynamo's core node library. WorkflowTests contains unit tests for some of Dynamo's samples.

###Test Libraries Several libraries are provided with Dynamo which contain base classes and utility methods to facilitate testing.

  • TestServices - Contains the base class for Dynamo unit tests.
  • SystemTestServices - Contains the base class for Dynamo system tests.

###Base Classes Several base classes are provided to facilitate writing tests for Dynamo. Using these base classes means you don't have to worry about things like initializing Dynamo and its geometry library for units tests, or providing access to the Dynamo workspace in system tests.

  • GeometricTestBase - For unit tests that can use the geometry library.
  • SystemTestBase - For system tests that start Dynamo and can use .dyn files.
  • RevitNodeTestBase - For unit tests, runnable on Revit through RTF.
  • RevitSystemTestBase - For system tests, runnable on Revit through RTF.

###Setting Up A Visual Studio Project for Testing

Because your tests will rely on Dynamo libraries, you'll need to reference Dynamo libraries in your project. There are several methods to create references to Dynamo libraries.

####Method 1: Relative Paths (Default) If you already have a fork of the Dynamo repository, or an install of Dynamo, you can reference assemblies in those locations using relative paths. Visual Studio will default to creating a relative path when you select References -> Add Reference in the interface. This is a fast way to reference a Dynamo assembly, and is convenient if you are the only developer on a project. The down side to this method is that if you move either your library's directory or the Dynamo directory, all of these relative paths will break and your references will be unresolved. Additionally, if you share your source code with anyone else, these references will fail to resolve unless that person has their system setup exactly like yours.

####Method 2: Local Assemblies The easiest way to do this is to copy the necessary dlls from either a Dynamo install or a fork of the Dynamo repository on your disk to a \lib directory in your source. Then you create references in your project to the files in your \lib directory. This allows your library to be portable and does not require your library to know where Dynamo is located. The down side to this method is that you'll need to keep the Dynamo libraries in your \lib directory up to date.

####Method 3: Environment Variables The most flexible method for referencing Dynamo assemblies is to create an environment variable that specifies the Dynamo core directory from where the referenced assemblies will be pulled. Then, as you add references to your project, you can edit the .csproj file, replacing the relative path with your environment variable. Finally, you can create a batch file to start your solution which sets the environment variable to the correct value, thereby pulling the referenced assemblies from the correct locations. This method is portable, allowing for other developers to use your source on their systems specifying a value for the environment variable that works on their system, and it's robust insofar as it keeps the references up to date with the version of Dynamo that you supply as the base path. The one down side to this method is the necessity to start Visual Studio using a script to set the environment variable.

The following code shows part of the cs.props file used for the Solar Analysis for Dynamo package.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
    ...
    <DYNAMO_BASE Condition=" '$(DYNAMO_BASE)' == ''">..\..\Dynamo\bin\AnyCPU\Debug</DYNAMO_BASE>
    ...
    <BaseIntermediateOutputPath>$(OutputPath)\int\</BaseIntermediateOutputPath>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
    ...
    <DYNAMO_BASE Condition=" '$(DYNAMO_BASE)' == ''">..\..\Dynamo\bin\AnyCPU\Debug</DYNAMO_BASE>
    ...
    <BaseIntermediateOutputPath>$(OutputPath)\int\</BaseIntermediateOutputPath>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
</Project>

The DYNAMO_BASE variable is used to define the location of Dynamo from where the assemblies will be pulled. You can set a default value in the .props file, and override that value using our Visual Studio startup script. You can then reference this .props file in your project file by inserting a reference to it as follows:

<ImportGroup Label="PropertySheets">
    <Import Project="$(SolutionDir)/Config/CS.props" />
</ImportGroup>

The startup batch file used to start Visual Studio with the correct value for this variable looks like:

Set DYNAMO_BASE=C:\Users\Ian\Documents\GitHub\Dynamo\bin\AnyCPU\Debug
"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe" "DynamoSolarAnalysis.sln"

Here, the first line sets the DYNAMO_BASE variable to the location of Dynamo on my machine. The second line starts Visual Studio specifying my solution file.