xUnitRevitUtils.2020 1.0.7

Requires NuGet 2.14 or higher.

dotnet add package xUnitRevitUtils.2020 --version 1.0.7                
NuGet\Install-Package xUnitRevitUtils.2020 -Version 1.0.7                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="xUnitRevitUtils.2020" Version="1.0.7" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add xUnitRevitUtils.2020 --version 1.0.7                
#r "nuget: xUnitRevitUtils.2020, 1.0.7"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install xUnitRevitUtils.2020 as a Cake Addin
#addin nuget:?package=xUnitRevitUtils.2020&version=1.0.7

// Install xUnitRevitUtils.2020 as a Cake Tool
#tool nuget:?package=xUnitRevitUtils.2020&version=1.0.7                

xUnitRevit

Build

xunit2

Twitter Follow Community forum users website docs

Introduction

An xUnit runner for Autodesk Revit.

Check out our blog post on this 👉 https://speckle.systems/blog/xunitrevit !

xUnitRevit uses speckle.xunit.runner.wpf which is a fork of xunit.runner.wpf, it allows to easily develop and run xUnit tests in Revit.

Many thanks to all the developers of xunit and xunit.runner.wpf!

Structure

This repo is composed of 2 projects:

  • xUnitRevitRunner: the actual Revit addin
  • xUnitRevitUtils: a utility library to help pass Revit data to the test libraries when running the tests

Getting Started

There are very few steps required to create and run your fist unit tests with xUnitRevit:

  1. create a copy of the config sample file and re-name the copy to config.json
  2. follow the instructions here to set up the config file
  3. build/install xUnitRevitRunner
  4. create a test library
  5. start Revit, launch the xUnitRevitRunner addin and select the test library
  6. done! Add a star ⭐ to our repo if it was useful 😉

Building/installing xUnitRevit

After cloning this repo, all you need to do to run xUnitRevitRunner is to build the project corresponding to your revit version in Debug mode

This will build the project and copy its dlls to the Revit addin folder %appdata%\Autodesk\Revit\Addins.

You can also, similarly, build the project in Release mode, and manually copy the built files from xunit-Revit\Release.

Creating a test library

Creating a test library is pretty straightforward, at least we tried to make it as simple as possible!

Just follow the steps below for Revit 2021:

  • create a new .net framework class library project (4.8 for Revit 2021)
  • add the NuGet packages
    • xunit
    • xUnitRevitUtils.2021

That's it, now we can start adding our tests.

Writing a simple test

To do almost anything with the Revit API you need a reference to the active Document, and this is where xUnitRevitUtils comes into play, with its xru static class. The code below shows how we can use it to get a list of Walls and check their properties.

Full code : https://github.com/Speckle-Next/xUnitRevit/blob/master/SampleLibrary/SampleTest.cs

  [Fact]
public void WallsHaveVolume()
{
  var testModel = GetTestModel("walls.rvt");
  var doc = xru.OpenDoc(testModel);

  var walls = new FilteredElementCollector(doc).WhereElementIsNotElementType().OfCategory(BuiltInCategory.OST_Walls).ToElements();

  foreach(var wall in walls)
  {
    var volumeParam = wall.get_Parameter(BuiltInParameter.HOST_VOLUME_COMPUTED);
    Assert.NotNull(volumeParam);
    Assert.True(volumeParam.AsDouble() > 0);
  }
  doc.Close(false);
}
Writing tests with fixtures

To be able to share context between tests, xUnits uses fixtures. We can use fixtures for instance, to open a Revit model only once and use it across multiple tests.

Let's see an example, full code: https://github.com/Speckle-Next/xUnitRevit/blob/master/SampleLibrary/TestWithFixture.cs

public class DocFixture : IDisposable
{
  public Document Doc { get; set; }
  public IList<Element> Walls { get; set; }


  public DocFixture()
  {
    var testModel = Utils.GetTestModel("walls.rvt");
    Doc = xru.OpenDoc(testModel);

    Walls = new FilteredElementCollector(Doc).WhereElementIsNotElementType().OfCategory(BuiltInCategory.OST_Walls).ToElements();
  }

  public void Dispose()
  {
  }
}
public class TestWithFixture : IClassFixture<DocFixture>
{
  DocFixture fixture; 
  public TestWithFixture(DocFixture fixture)
  {
    this.fixture = fixture;
  }

  [Fact]
  public void CountWalls()
  {
    Assert.Equal(4, fixture.Walls.Count);
  }

  [Fact]
  public void WallOffset()
  {
    var wall = fixture.Doc.GetElement(new ElementId(346573));
    var param = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET);
    var baseOffset = UnitUtils.ConvertFromInternalUnits(param.AsDouble(), param.DisplayUnitType);

    Assert.Equal(2000, baseOffset);
  }
}
Writing test that use Revit transactions

Another feature of xUnitRevitUtils is that it offers a helper method to run Transactions, so you don't have to worry about that 🤯! Check the example below: https://github.com/Speckle-Next/xUnitRevit/blob/master/SampleLibrary/TestWithFixture.cs

[Fact]
public void MoveWallsUp()
{
  var walls = fixture.Walls.Where(x => x.Id.IntegerValue != 346573);

  xru.RunInTransaction(() =>
  {
    foreach(var wall in walls)
    {
      var param = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET);
      var baseOffset = UnitUtils.ConvertToInternalUnits(2000, param.DisplayUnitType);
      param.Set(baseOffset);
    }
  }, fixture.Doc)
  .Wait(); // Important! Wait for action to finish

  foreach (var wall in walls)
  {
    var param = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET);
    var baseOffset = UnitUtils.ConvertFromInternalUnits(param.AsDouble(), param.DisplayUnitType);
    Assert.Equal(2000, baseOffset);
  }
}

image

Additional Notes

Configuration

We've added a couple of optional settings for lazy developers like me, to help speed up frequent testing of a test library. You'll see a config_sample.json in the root of the project. Copy the file and rename the copy to config.json and set it to copy local = true. You'll then be able to configure

  • startupAssemblies: if set, automatically loads a set of assemblies when xUnitRevit starts
  • autoStart: if true, automatically opens the xUnitRevit window after Revit loads

Dll locking

Dlls loaded by xUnitRevit are loaded in Revit's AppDomain, and therefore it's not possible to recompile them until Revit is closed (even if you see an auto reload option in the UI). But don't despair, since Revit 2020 it's possible to edit & continue your code while debugging, so you won't have to restart Revit each time.

Next steps

As for next steps, we're planning to add additional features to run xUnitRevit from a CI/CD routine.

Stay tuned!

Contributing

xUnitRevit was developed to help us develop a better Speckle 2.0 connector for Revit, we hope you'll find it useful too.

Want to suggest a feature, report a bug, submit a PR? Please open an issue to discuss first!

Please make sure you read the contribution guidelines and code of conduct for an overview of the practices we try to follow.

Community

The Speckle Community hangs out on the forum, do join and introduce yourself & feel free to ask us questions!

Security

For any security vulnerabilities or concerns, please contact us directly at security[at]speckle.systems.

License

Unless otherwise described, the code in this repository is licensed under the MIT License. Please note that some modules, extensions or code herein might be otherwise licensed. This is indicated either in the root of the containing folder under a different license file, or in the respective file's header. If you have any questions, don't hesitate to get in touch with us via email.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.7 241 6/7/2023
1.0.6 272 3/9/2023
1.0.4 1,984 10/31/2020
1.0.3 339 9/15/2020
1.0.1 341 7/30/2020
1.0.0 496 7/1/2020
0.0.3 204 3/9/2023