码迷,mamicode.com
首页 > 其他好文 > 详细

单元测试概括

时间:2015-05-04 01:01:12      阅读:335      评论:0      收藏:0      [点我收藏+]

标签:

一、单元测试的目的

验证代码与设计相符合(Code Inspection与Unit Test相结合)

跟踪需求和设计的实现

发现设计和需求中存在的错误

发现编码过程中引入的错误

对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

二、单元测试的环境

构造最小运行调度系统,即驱动模块(Driver),用以模拟被测模块的上一级模块 模拟实现单元接口桩(Stub),即被测单元需调用的其他单元函数的接口 模拟生成数据或状态,为单元测试准备动态环境

三、单元测试的方法

孤立测试策略 单元内的全局输入/输出变量测试(Driver) 单元内调用的函数(Stub)的接口测试 覆盖测试(语句覆盖/分支覆盖/复合谓词覆盖/路径覆盖)。 Note:应该依据规格说明书、流程图并结合源程序规划测试方法和测试用例。

四、单元测试的测试用例设计

为系统运行与正向测试设计测试用例:等价类划分、决策表 为逆向测试设计测试用例:边界值法 为代码覆盖设计测试用例:代码覆盖:语句覆盖、分支覆盖、复合谓词覆盖、路径覆盖、数据定义使用测试

五、单元测试应坚持的原则

单元测试前应该执行静态检查、代码走读 对全新的代码或修改过的代码进行单元测试 被测试的对象为实现一组相关功能的代码(一个或一组函数) 单元测试根据单元测试的计划和方案进行,排除测试的随意性 项目管理者保证测试用例经过审核(集思广益) 当测试用例的测试结果与预期结果不一致时,单元测试的执行人员需如实记录实际测试结果 当测试达到计划的结束标准时,单元测试结束 对被侧单元需达到一定的代码覆盖率要求 当程序修改后,测试人员要执行回归测试,以保证修改后没有引入新的错误。

我们编写代码时,一定会反复调试保证它能够编译通过。如果是编译没有通过的代码,没有任何人会愿意交付给自己的老板。但代码通过编译,只是说明了它的语法正确;我们却无法保证它的语义也一定正确,没有任何人可以轻易承诺这段代码的行为一定是正确的。

幸运的是,单元测试会为我们的承诺做保证。编写单元测试就是用来验证这段代码的行为是否与我们期望的一致。有了单元测试,我们可以自信的交付自己的代码,而没有任何的后顾之忧。

什么时候测试?单元测试越早越好,早到什么程度?XP开发理论讲究TDD,即测试驱动开发,先编写测试代码,再进行开发。在实际的工作中,可以不必过分强调先什么后什么,重要的是高效和感觉舒适。从老纳的经验来看,先编写产品函数的框架,然后编写测试函数,针对产品函数的功能编写测试用例,然后编写产品函数的代码,每写一个功能点都运行测试,随时补充测试用例。所谓先编写产品函数的框架,是指先编写函数空的实现,有返回值的随便返回一个值,编译通过后再编写测试代码,这时,函数名、参数表、返回类型都应该确定下来了,所编写的测试代码以后需修改的可能性比较小。

由谁测试?单元测试与其他测试不同,单元测试可看作是编码工作的一部分,应该由程序员完成,也就是说,经过了单元测试的代码才是已完成的代码,提交产品代码时也要同时提交测试代码。测试部门可以作一定程度的审核。

关于桩代码,老纳认为,单元测试应避免编写桩代码。桩代码就是用来代替某些代码的代码,例如,产品函数或测试函数调用了一个未编写的函数,可以编写桩函数来代替该被调用的函数,桩代码也用于实现测试隔离。采用由底向上的方式进行开发,底层的代码先开发并先测试,可以避免编写桩代码,这样做的好处有:减少了工作量;测试上层函数时,也是对下层函数的间接测试;当下层函数修改时,通过回归测试可以确认修改是否导致上层函数产生错误。

在一种传统的结构化编程语言中,比如C,要进行测试的单元一般是函数或子过程。在象C++这样的面向对象的语言中, 要进行测试的基本单元是类。对Ada语言来说,开发人员可以选择是在独立的过程和函数,还是在Ada包的级别上进行单元测试。单元测试的原则同样被扩展到第四代语言(4GL)的开发中,在这里基本单元被典型地划分为一个菜单或显示界面。

六、单元测试工具

代码静态分析工具:Logiscope、McCabe QA、CodeTest 代码检查工具:PC-LINT、CodeChk、Logiscope 测试脚本工具:TCL、Python、Perl 覆盖率检测工具: Visual studio ,Logiscope、Purecoverage 内存检测工具:Purify、CodeTest 单元测试工具:Visual studio 2005-2013,xUnit

七、实验内容

创建解决方案和单元测试项目

在“文件”菜单上选择“新建”,然后选择“新建项目”。 

在“新建项目”对话框中,展开“已安装”、“Visual C#,选择“Windows Store。  然后从项目模板列表中选择“空白应用程序”。

将项目命名为 Maths,并确保选中“创建解决方案的目录”。 

在解决方案资源管理器中,选择解决方案名称,从快捷菜单中选择“添加”,然后选择“新建项目”。 

在“新建项目”对话框中,展开“已安装”、“Visual C#,然后选择“Windows 应用商店”。  然后从项目模板列表中选择“单元测试库(Windows Store 应用程序)

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;

 

namespace UnitTestLibrary1

{

    [TestClass]

    public class UnitTest1

    {

        [TestMethod]

        public void TestMethod1()

        {

            Assert.AreEqual(0, 0);

 

}

 

        }

    }

以下是测试源码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

 

namespace App1

{

    public class Class1

    {

        public Class1()

    {

    }

        public double SquareRoot(double x)

        {

            double estimate = x;

            double diff = x;

            if (x < 0.0)

            {

                throw new ArgumentOutOfRangeException();

            }

 

            while (diff > estimate / 1000)

            {

                double previousEstimate = estimate;

                estimate = estimate - (estimate * estimate - x) / (2 * estimate);

                diff = Math.Abs(previousEstimate - estimate);

            }

            return estimate;

 

        }

 

 

    }

}

 

 

 

 

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;

using App1;

 

namespace UnitTestLibrary1

{

    [TestClass]

    public class UnitTest1

    {

        [TestMethod]

        public void TestMethod1()

        {

            Assert.AreEqual(0, 0);

 

        }

         [TestMethod]

        public void BasicTest()

        {

            App1.Class1 rooter = new Class1();

            double expected = 0.0;

            double actual = rooter.SquareRoot(expected * expected);

            double tolerance = .001;

            Assert.AreEqual(expected, actual, tolerance);

        }

        [TestMethod]

        public void RangeTest()

        {

            Class1 rooter = new Class1();

            for (double v = 1e-6; v < 1e6; v = v * 3.2)

            {

                double expected = v;

                double actual = rooter.SquareRoot(v * v);

                double tolerance = expected;

                Assert.AreEqual(expected, actual, tolerance);

            }

        }

        [TestMethod]

        public void NegativeRangeTest()

        {

            string message;

            Class1 rooter = new Class1();

            for (double v = -0.1; v > -3.0; v = v - 0.5)

            {

                try

                {

                    // Should raise an exception:

                    double actual = rooter.SquareRoot(v);

 

                    message = String.Format("No exception for input {0}", v);

                    Assert.Fail(message);

                }

                catch (ArgumentOutOfRangeException ex)

                {

                    continue; // Correct exception.

                }

                catch (Exception e)

                {

                    message = String.Format("Incorrect exception for {0}", v);

                    Assert.Fail(message);

                }

            }

        }

 

 

 

 

        }

    }

 

 

 

以下是app源码

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Runtime.InteropServices.WindowsRuntime;

using Windows.ApplicationModel;

using Windows.ApplicationModel.Activation;

using Windows.Foundation;

using Windows.Foundation.Collections;

using Windows.UI.Xaml;

using Windows.UI.Xaml.Controls;

using Windows.UI.Xaml.Controls.Primitives;

using Windows.UI.Xaml.Data;

using Windows.UI.Xaml.Input;

using Windows.UI.Xaml.Media;

using Windows.UI.Xaml.Navigation;

 

// “空白应用程序”模板在 http://go.microsoft.com/fwlink/?LinkId=234227 上有介绍

 

namespace App1

{

    /// <summary>

    /// 提供特定于应用程序的行为,以补充默认的应用程序类。

    /// </summary>

    sealed partial class App : Application

    {

        /// <summary>

        /// 初始化单一实例应用程序对象。    这是执行的创作代码的第一行,

        /// 逻辑上等同于 main() 或 WinMain()。

        /// </summary>

        public App()

        {

            this.InitializeComponent();

            this.Suspending += OnSuspending;

        }

 

        /// <summary>

        /// 在应用程序由最终用户正常启动时进行调用。

        /// 以打开特定文件等情况下使用其他入口点。

        /// </summary>

        /// <param name="e">有关启动请求和过程的详细信息。</param>

        protected override void OnLaunched(LaunchActivatedEventArgs e)

        {

 

#if DEBUG

            if (System.Diagnostics.Debugger.IsAttached)

            {

                this.DebugSettings.EnableFrameRateCounter = true;

            }

#endif

 

            Frame rootFrame = Window.Current.Content as Frame;

 

            // 不要在窗口已包含内容时重复应用程序初始化,

            // 只需确保窗口处于活动状态

            if (rootFrame == null)

            {

                // 创建要充当导航上下文的框架,并导航到第一页

                rootFrame = new Frame();

                //设置默认语言

                rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

 

                rootFrame.NavigationFailed += OnNavigationFailed;

 

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)

                {

                    //TODO:  从之前挂起的应用程序加载状态

                }

 

                // 将框架放在当前窗口中

                Window.Current.Content = rootFrame;

            }

 

            if (rootFrame.Content == null)

            {

                // 当未还原导航堆栈时,导航到第一页,

                // 并通过将所需信息作为导航参数传入来配置

                // 参数

                rootFrame.Navigate(typeof(MainPage), e.Arguments);

            }

            // 确保当前窗口处于活动状态

            Window.Current.Activate();

        }

 

        /// <summary>

        ///导航到特定页失败时调用

        /// </summary>

        ///<param name="sender">导航失败的框架</param>

        ///<param name="e">有关导航失败的详细信息</param>

        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)

        {

            throw new Exception("Failed to load Page " + e.SourcePageType.FullName);

        }

 

        /// <summary>

        /// 在将要挂起应用程序执行时调用。    在不知道应用程序

        /// 将被终止还是恢复的情况下保存应用程序状态,

        /// 并让内存内容保持不变。

        /// </summary>

        /// <param name="sender">挂起的请求的源。</param>

        /// <param name="e">有关挂起的请求的详细信息。</param>

        private void OnSuspending(object sender, SuspendingEventArgs e)

        {

            var deferral = e.SuspendingOperation.GetDeferral();

            //TODO:  保存应用程序状态并停止任何后台活动

            deferral.Complete();

        }

    }

}

 

 

 

 

单元测试概括

标签:

原文地址:http://www.cnblogs.com/2522150225qq/p/4475034.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!