关于为啥要写单元测试,可以参考《重构》《代码大全》《测试驱动开发》,具体原因不赘述。
第一步,到AssetsStore下载 UnityTestTools,导入资源。
(倒入之后可能会出错,你项目中的类名的如果与倒入的包中的某个类名重复的话,就会报错。要么改你的类名,要么改包中的类名。)
第二步,在Assets下新建一个目录UnitTest ,添加子目录 Editor(因为要在非运行状态下跑脚本,所以测试文件要放在Editor目录下)。
第三步,编写测试代码。
就用上次的代码测吧。
需要测试的类EditCache(这个类是被测试类,你放哪都行。)代码如下:
using UnityEngine;
using System.Collections.Generic;
using System;
public class EditCache {
private Stack<IStep> _history = new Stack<IStep> ();
private Stack<IStep> _forward = new Stack<IStep> ();
public
void
AddStep
(
IStep
step
){
_history.Push (step);
_forward.Clear ();
}
// ctrl + z
public void StepRollback(){
StepActivity<IStep>(_history,_forward,s=>s.Rollback());
}
// ctrl + y
public void StepForward(){
StepActivity<IStep>(_forward,_history,s=>s.Forward());
}
private void StepActivity<T>(Stack<T> source,Stack<T> destination,Action<T> action){
if (source.Count == 0)
return;
T step = source.Pop ();
action (step);
destination.Push (step);
}
public int ForwardCount()
{
return _forward.Count;
}
public int HistoryCount()
{
return _history.Count;
}
}
对外开放的方法好几个,全写太多,这里只写测第一个方法的代码。
PS:
IStep是个接口:
public interface IStep {
void Rollback();
void Forward();
}
接口相关的测试可以使用
NSubstitute,详细用法自行google,我这里只给简陋的用法。
测试类:
EditCacheTest
.cs(这个类是需要跑的测试类,必须放在Editor目录或它的子目录下):
using UnityEngine;
using System.Collections;
using NUnit.Framework;
using NSubstitute;
[TestFixture]
public class EditCacheTest {
private EditCache _editCache;
[SetUp]
public void SetUp(){
_editCache = new EditCache();
}
[TearDown]
public void TearDown(){
_editCache = null;
}
[Test]
public void test_add_step_forward_should_clear()
{
var step = Substitute.For<IStep>();
_editCache.AddStep(step);
Assert.AreEqual(_editCache.ForwardCount(),0);
}
[Test]
public void test_add_step_history_count_plus_1()
{
var step = Substitute.For<IStep>();
var before = _editCache.HistoryCount();
_editCache.AddStep(step);
var after = _editCache.HistoryCount();
Assert.AreEqual(after - before, 1);
}
}
第四步:打开Unit Test Runnner:
运行所有,
绿钩表示测试通过。
一般类都能用这种方式测试,但是UNITY有其特殊性,很多类继承自
MonoBehaviour 。
要想测试,必须做一番手脚。因为这类脚本要依附于一个GameObject上。
private GameObject _go;
[SetUp]
public void SetUp(){
_go = new GameObject ();
//TODO add
MonoBehaviour scrpit on _go
}
[TearDown]
public void TearDown(){
MonoBehaviour.DestroyImmediate (_go);//这个方法很关键,非运行状态要用这个方法来销毁GameObject
//TODO Destroy you script
}
至于一些标签如[Setup][TearDown]是怎么回事,具体怎么用,可以参考《 .
NET单元测试艺术》。