10.单元测试

随着类的不断增多,如何在编写完一个类后测试它的正确性就变得越来越重要,不要等到写了很多类之后再想到除错,那已经为时已晚,你根本就找不到到底是哪个类有问题。比如说编写完UIImage后,想知道它是否工作正常,一个方法就是新建一个项目,从引擎类继承,再添加一个Scene,将UIImage类放在这个Scene中,运行项目看看是否正常,调试一个类时这种方法挺管用,如果以后还有大量的类呢?每个类都要创建一个项目吗?其实发现测试的过程都是类似的,自然想到需要将测试过程封装成一个类。具体的实现原理可参见《ProfessionalXNA》中的§2.3让我们编写Pong§3.3XNA 中的单元测试

先在引擎类StunEngine.cs中添加一个委托:

/// <summary>
/// 用于单元测试的委托。
/// </summary>
public delegate void RenderDelegate();

然后创建一个入口点类:

namespace StunEngine
{
    static class Program
    {
        static void Main(string[] args)
        {
               
        }
    }
}

接着还要新建一个类TestGame从引擎继承:

namespace StunEngine
{
    class TestGame:StunXnaGE 
    {
        成员变量        
        
        /// <summary>
        /// 创建单元测试
        /// </summary>
        /// <param name="setWindowsTitle">设置窗口标题</param>        
        /// <param name="setInitCode">设置初始化代码</param>
        /// <param name="setUpdateCode">设置更新代码</param>
        /// <param name="setDrawCode">设置绘制代码</param>
        protected TestGame(string setWindowsTitle,RenderDelegate setInitCode,RenderDelegate setUpdateCode,RenderDelegate setDrawCode)
        {
            this.Window.Title = setWindowsTitle;

            initCode = setInitCode;
            updateCode = setUpdateCode;
            drawCode = setDrawCode;
        }
        
        /// <summary>
        /// 初始化代码
        /// </summary>
        protected override void Initialize()
        {
            base.Initialize();
            
            //添加默认屏幕
            scene = new defaultScene(this);
            SceneManager.AddScene(scene);  
            
            // 调用自定义的初始化代码
            if (initCode != null)
                initCode();
        }        

        /// <summary>
        /// 更新代码
        /// </summary>
        protected override void Update(GameTime time)
        {
            base.Update(time);

            // 按ESC键或手柄Back退出测试
            if (Input.KeyboardEscapeJustPressed ||
                Input.GamePadBackJustPressed)
                this.Exit();

            // 调用自定义的更新代码
            if (updateCode != null)
                updateCode();
        }
        
        /// <summary>
        /// 绘制代码
        /// </summary>
        protected override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
            
            // 调用自定义的绘制代码
            if (drawCode != null)
                drawCode();
                    
        }        

        开始测试

        单元测试
    }
}

在TestGame类中有一个静态的Scene,我命名为defaultScene,所以还需要在项目中添加一个defaultScene类,这个类中添加了一个相机,一个相机控制器和一个默认单向光源。代码如下:

class defaultScene:Scene
    {
        public FpsCameraController fpsCamCtrl;
        /// <summary>
        /// 构造函数
        /// </summary>
        public defaultScene(StunXnaGE engine)
            : base(engine, "default")
        {
            
        }

        public override void LoadContent()
        {
            base.LoadContent();

            //-----------------------------------
            //  添加一个指向左后方的默认单向光源,颜色为白色            
            //----------------------------------- 
            Light sun = new Light(new Vector3(1.0f, 1.0f, 1.0f),new Vector3(-1f, 0, -1f));
            AddLight(sun);

            //-----------------------------------
            //  创建相机 
            //-----------------------------------
            Vector3 cameraPosition = new Vector3(0, 0, 20);
            CameraSceneNode Camera = new CameraSceneNode(engine, this, cameraPosition, cameraPosition + Vector3.Forward);
            Camera.Initialize();
            Camera.FOV = MathHelper.PiOver4;
            this.Camera = Camera;

            //-----------------------------------
            //  创建fps相机控制器
            //-----------------------------------            
            fpsCamCtrl = new FpsCameraController(engine);
            fpsCamCtrl.Elevation = 90;
            Camera.AttachController(fpsCamCtrl);           
        }
    }
}

编写好上述几个类后,要实现单元测试,首先需要StunEngine项目的属性中将“输出类型”从“类库”改为“Windows应用程序”,并将右击StunEngine项目将它“设为启动项目”。比如我要测试UIImage类是否工作正常,只需在UIImage类的最后添加以下代码:

单元测试

最后别忘了在Program.cs类中调用这个单元测试:

namespace StunEngine
{
    static class Program
    {
        static void Main(string[] args)
        {
            UIImage.TestUIImage();
        }
    }
}

运行代码后,程序截图如下:

单元测试截图

以后我每编写一个类都会实现单元测试,这样可以将错误限定在一个类中,给程序除错带来极大的方便,而且你也可以从单元测试中看到类的使用方法。


发布时间:2010/1/15 下午1:55:51  阅读次数:5762

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号