I have been programming mainly in Unity3D over the last fortnight, and thought it time to write some unit tests for my work. I found reference to a few testing frameworks online. The most promising appeared to be SharpUnit, and it is also released under a fairly relaxed license. However, I had to make a few changed to get it running, so this post details that work.
SharpUnit works like a standard unit testing framework for C# code in Unity3D (although all output goes to the console, but that is fine for me). Although my work has largely been in UnityScript (Unity3D’s JavaScript like language) and this didn’t work so well due to issues with compilation order and SharpUnit’s use of .Net custom attributes. After making the changes below, I found SharpUnit works well, and I’ll probably be using it for my unit testing.
Unity3D compiles scripts in a set order (as described
here).
Thus if you have C# code that references a UnityScript class there can
be a problem - although the reverse is not such an issue. When testing
UnityScript with SharpUnit this means that the C# Unity3D_TestRunner
class can be an issue. It references the TestCase
classes, which I
want to write in UnityScript. To do this I put the SharpUnit code in a
folder under the Plugins
top-level folder (the Standard Assets
folder would have also worked). This means the SharpUnit code is
compiled first. Then my tests went in a new folder together with a
UnityScript rewrite of Unity3D_TestRunner
, as shown below. This
UnityScript TestRunner script is then attached to the TestRunner
GameObject (in a special testing scene) rather than the C# version as
described in the SharpUnit instructions.
#pragma strict
import SharpUnit;
function Start () {
var suite: TestSuite = new TestSuite();
suite.AddAll(DummyTest());
var res: TestResult = suite.Run(null);
var reporter: Unity3D_TestReporter = new Unity3D_TestReporter();
reporter.LogResults(res);
}
Other possible solutions to this problem would be to just write my code
in C# or to change SharpUnit to load TestCase
classes dynamically at
runtime. Rewriting the TestRunner seemed easiest.
The other problem encountered is that SharpUnit uses the C# custom
attribute [UnitTest]
to identify its test methods. The equivalent in
UnityScript is a script directive (see the relevant section
here).
Thus @UnitTest
needs to be placed at the top of each test function.
After that change I could run UnityScript tests with SharpUnit. An example test is below:
#pragma strict
import SharpUnit;
class DummyTest extends TestCase {
var dummy: String;
/** Setup test resources, called before each test. */
function SetUp() {
dummy = "lkjkjh";
}
/** Dispose of test resources, called after each test */
function TearDown() {
dummy = null;
}
/** Sample test that passes */
@UnitTest
function TestDummy_Pass() {
Assert.NotNull(dummy);
}
/** Sample test that fails. */
@UnitTest
function TestDummy_Fail() {
Assert.Null(dummy);
}
}