`
xo_tobacoo
  • 浏览: 391885 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

Junit入门和基本运行结构分析

    博客分类:
  • j2ee
阅读更多

The test code must be written to do a few things:

一、测试流程:

1 Setup all conditions needed for testing (create any re-quired objects, allocate any needed resources, etc.)

初始化资源

2 Call the method to be tested

调用方法开始测试

3 Verify that the method to be tested functioned as ex-Pected

验证被测试方法是否按期望方式运行

4 Clean up after itself

完成测试后自行清理资源

 

下面让以上述为依据看看testCase的源代码:

public abstract class TestCase extends Assert implements Test {

       /**

        * the name of the test case测试用例名称

        */

       private String fName;

 

       /**

        * No-arg constructor to enable serialization. This method 构造函数

        * is not intended to be used by mere mortals without calling setName().

        */

       public TestCase() {

              fName= null;

       }

       /**

        * Constructs a test case with the given name.构造函数

        */

       public TestCase(String name) {

              fName= name;

       }

       /**

        * Counts the number of test cases executed by run(TestResult result).记录测试用例数目

        */

       public int countTestCases() {

              return 1;

       }

       /**

        * Creates a default TestResult object//创建默认TestResult对象,里面存储测试结果

        *

        * @see TestResult

        */

       protected TestResult createResult() {

           return new TestResult();

       }

       /**

        * A convenience method to run this test, collecting the results with a

        * default TestResult object.执行测试很简易的方法,使用默认的TestResult

        *

        * @see TestResult

        */

       public TestResult run() {

              TestResult result= createResult();

              run(result);

              return result;

       }

       /**

        * Runs the test case and collects the results in TestResult.执行测试并把手机测试结果信息存入指定TestResult

        */

       public void run(TestResult result) {

              result.run(this);

       }

       /**

        * Runs the bare test sequence. 执行测试方法,包括初始化和销毁方法

        * @throws Throwable if any exception is thrown

        */

       public void runBare() throws Throwable {

              Throwable exception= null;

              setUp();

              try {

                     runTest();

              } catch (Throwable running) {

                     exception= running;

              }

              finally {

                     try {

                            tearDown();

                     } catch (Throwable tearingDown) {

                            if (exception == null) exception= tearingDown;

                     }

              }

              if (exception != null) throw exception;

       }

       /**

        * Override to run the test and assert its state. 执行测试方法

        * @throws Throwable if any exception is thrown

        */

       protected void runTest() throws Throwable {

              assertNotNull("TestCase.fName cannot be null", fName); // Some VMs crash when calling getMethod(null,null);

              Method runMethod= null;

              try {

                     // use getMethod to get all public inherited

                     // methods. getDeclaredMethods returns all

                     // methods of this class but excludes the

                     // inherited ones.

                     runMethod= getClass().getMethod(fName, (Class[])null);

              } catch (NoSuchMethodException e) {

                     fail("Method \""+fName+"\" not found");

              }

              if (!Modifier.isPublic(runMethod.getModifiers())) {

                     fail("Method \""+fName+"\" should be public");

              }

 

              try {

                     runMethod.invoke(this);

              }

              catch (InvocationTargetException e) {

                     e.fillInStackTrace();

                     throw e.getTargetException();

              }

              catch (IllegalAccessException e) {

                     e.fillInStackTrace();

                     throw e;

              }

       }

       /**

        * Sets up the fixture, for example, open a network connection.

        * This method is called before a test is executed. 测试前的初始化方法

        */

       protected void setUp() throws Exception {

       }

       /**

        * Tears down the fixture, for example, close a network connection.

        * This method is called after a test is executed. 测试后的销毁方法

        */

       protected void tearDown() throws Exception {

       }

       /**

        * Returns a string representation of the test case

        */

       @Override

       public String toString() {

           return getName() + "(" + getClass().getName() + ")";

       }

       /**

        * Gets the name of a TestCase返回测试案例的名称

        * @return the name of the TestCase

        */

       public String getName() {

              return fName;

       }

       /**

        * Sets the name of a TestCase设定测试案例的名称

        * @param name the name to set

        */

       public void setName(String name) {

              fName= name;

       }

}

 

二、运行方式:

您定义自己的TestCase,并使用TestRunner来运行测试,事实上TestRunner并不直接运行 TestCase上的单元方法,而是透过TestSuiteTestSuite可以将数个TestCase在一起,而让每个TestCase保持简单。

 

public class SimpleTest extends TestCase {

       protected int fValue1;

       protected int fValue2;

 

        SimpleTest(String name){

        super(name);

        }

       @Override

       protected void setUp() {

              fValue1= 2;

              fValue2= 3;

       }

      

       public void testAdd() {

              double result= fValue1 + fValue2;

              // forced failure result == 5

              assertTrue(result == 6);

       }

       public void testDivideByZero() {

              int zero= 0;

              int result= 8/zero;

              result++; // avoid warning for not using result

       }

       public void testEquals() {

              assertEquals(12, 12);

              assertEquals(12L, 12L);

              assertEquals(new Long(12), new Long(12));

 

              assertEquals("Size", 12, 13);

              assertEquals("Capacity", 12.0, 11.99, 0.0);

       }

       public static void main (String[] args) {

              junit.textui.TestRunner.run(suite());

       }

}

在这个例子中,您并没有看到任何的TestSuite,事实上,如果您没有提供任何的TestSuiteTestRunner会自己建立一个,然后这个 TestSuite会使用反射(reflection)自动找出testXXX()方法。
如果您要自行生成TestSuite,则在继承TestCase之后,提供静态的(static)的suite()方法,例如:
 public static Test suite() {

 

              /*

               * the type safe way

               **/

              TestSuite suite= new TestSuite();

              suite.addTest(

                     new SimpleTest("add") {

            @Override

                             protected void runTest() { testAdd(); }

                     }

              );

 

              suite.addTest(

                     new SimpleTest("testDivideByZero") {

            @Override

                             protected void runTest() { testDivideByZero(); }

                     }

              );

              return suite;

             

 

              /*

               * the dynamic way

               */

              //return new TestSuite(SimpleTest.class);

       }
JUnit
并没有规定您一定要使用testXXX()这样的方式来命名您的测试方法,如果您要提供自己的方法(当然JUnit 鼓励您使用testXXX()这样的方法名称),则可以如上撰写,为了要能够使用建构函式提供测试方法名称,您的TestCase必须提供如下的建构函式:
public SimpleTest (String testMethod) {
  super(testMethod);
}

如果要加入更多的测试方法,使用addTest()就可以了,suite()方法传回一个TestSuite物件,它与 TestCase都实作了Test介面,TestRunner会调用TestSuite上的run()方法,然后TestSuite会将之委託给 TestCase上的run()方法,并执行每一个testXXX()方法。
除了组合TestCase之外,您还可以将数个TestSuite组合在一起,例如:
public static Test suite() {
  TestSuite suite= new TestSuite();
  suite.addTestSuite(TestCase1.class);
  suite.addTestSuite(TestCase2.class);
  return suite;
}

如此之来,您可以一次运行所有的测试,而不必个别的运行每一个测试案例,您可以写一个运行全部测试的主测试,而在使用TestRunner时呼叫 suite()方法,例如:
junit.textui.TestRunner.run(TestAll.suite());

TestCase
TestSuite都实作了Test介面,其运行方式为 Command 模式 的一个实例,而TestSuite可以组合数个TestSuiteTestCase,这是 Composite 模式的一个实例。

 

 

三、失败和错误的区别

通常情况下是不希望自己编写的Java代码抛出错误的,而只应该抛出异常。通常来说,应该让Java虚拟机本身来抛出错误。因为一个错误意味着低级别的、不可恢复的问题,例如:无法装载一个类,这种问题我们也不期望被恢复。出于这个原因,也许我们对JUnit通过抛出错误来表示一个断言的失败而感到有些奇怪。

JUnit抛出的是错误而不是异常,这是因为在Java中,错误是不需要检查的;因此,不是每个方法都必须声明它会抛出哪些错误。你可能会认为RuntimeException可以完成相同的功能,但是如果JUnit抛出这种在产品代码中可能抛出的异常的类型,JUnit测试就会和你的产品相互影响。这种影响会降低JUnit的价值。

当你的测试包含了一个失败的断言,JUnit会将它算做一个失败的测试;但是如果你的测试抛出了一个异常(并且没有捕获它),JUnit将它看成是一个错误。这个区别是很细微的,却是非常有用的:一个失败的断言通常表示产品代码中有问题,而一个错误却表示测试本身或周围的环境存在着问题。也许你的测试期望了一个不该期望的错误的异常对象,或者错误地在一个null的应用上调用了一个函数。也有可能磁盘已经满了,或者网络连接不可用,或者是一个文件找不到了。JUnit并不把这个算做产品代码的缺陷,因此它只是在表达,有些不对劲了。我不能分辨这个测试是否通过。请解决这个问题并再重新测试一次。这就是失败和错误的区别。

JUnit的测试运行器会报告一个测试运行的结果,格式如下:“78 run, 2 failures,1 error从这个结果可以判断有75个测试已经通过,有两个失败,还有一个没有结论。我们的建议是先去调查那个错误,解决了此问题以后再重新运行这个测试。也许在解决了这个错误以后,所有的测试都通过了!

 

分享到:
评论

相关推荐

    junit和TestNG框架入门

    - **JUnit**: JUnit是最早也是最广泛使用的Java单元测试框架之一,主要用于编写和运行测试用例。它支持注解驱动的测试方法,但其版本迭代相对缓慢,部分高级特性支持不如新框架。 - **TestNG**: TestNG是一个基于...

    junit与ant教程.rar

    2. **Ant入门**:介绍Ant的基本结构,如项目、目标、任务和属性,以及如何编写构建文件。 3. **JUnit与Ant的集成**:如何在Ant构建文件中配置JUnit任务,如何处理测试失败,以及生成测试报告。 4. **高级特性**:如...

    junit eclipse testcast Testsuite

    通过分析JUnit和Eclipse Testcast Testsuite的源码,我们可以更深入地理解它们的工作原理。例如,JUnit的@Test注解是如何触发测试方法的执行,以及Testcast Testsuite如何读取和执行测试计划。源码学习可以帮助我们...

    Ant 入门资料(完整版)

    手册可能涵盖了如何配置Ant任务来运行JUnit测试,以及如何解读和分析测试结果等内容。学习这部分将帮助开发者确保代码质量,并在项目早期发现潜在问题。 "Ant 入门讲解视频(22分03秒)":这个视频教程可能是对Ant...

    Android从入门到精通源代码 孙更新.rar

    9. **测试与调试**:学会使用JUnit、Espresso进行单元测试和UI测试,使用Android Studio的调试工具分析代码运行状态,能帮助你发现和修复问题。 10. **发布与打包**:掌握APK的签名、版本控制、打包发布流程,了解...

    全面的软件测试入门ppt

    这份名为“全面的软件测试入门PPT”的资源旨在为初学者提供一个基础且全面的指南,帮助他们理解软件测试的基本概念、方法和技术。下面我们将深入探讨软件测试的核心知识点。 1. **软件测试定义与重要性** 软件测试...

    Intellij IDEA 2017入门教程 带书签目录 完整pdf

    9. **单元测试**:集成JUnit或其他测试框架,编写和运行测试用例,理解测试驱动开发(TDD)的概念。 10. **集成开发环境的高效使用**:提供时间节省技巧,如使用键盘快捷键、自定义操作和设置,以提升开发效率。 ...

    最经典的软件测试入门教程下

    首先,软件测试的基本概念包括功能测试、性能测试、兼容性测试、安全测试和回归测试等。功能测试关注的是软件是否按照需求文档正确执行,验证每个功能是否符合预期。性能测试则评估软件在不同负载和压力下的响应速度...

    第4章高级Java开发技术《Eclipse从入门到精通》教学课件.ppt

    Eclipse内置了JUnit插件,提供了一个图形用户界面来运行和管理测试,通过JUnit视图展示测试结果。 **4.2.3 准备测试的类** 在使用JUnit进行测试时,需要为待测试的类编写测试用例。通常,这意味着要编写继承自JUnit...

    Eclipse从入门到精通

    视图如Package Explorer、Problem View、Console等,提供了对项目结构、错误警告和运行输出的查看。编辑器则是编写代码的地方,Eclipse的Java编辑器具备智能代码补全、语法高亮和错误检查等功能。 接着,我们深入...

    最好的java入门基础书

    这本书可能包含了Java语言的基本概念、语法、数据类型、控制结构、类与对象等核心主题。 1. **Java语言简介**:Java是一种跨平台的、面向对象的编程语言,由Sun Microsystems(现属Oracle公司)于1995年发布。它的...

    软件测试入门电子书(适合初学者)

    白盒测试,又称为结构测试,侧重于代码结构和逻辑,通过分析代码来发现潜在问题。 4. **自动化测试**:随着软件规模的增大,手动测试效率降低,自动化测试工具如Selenium、Junit等应运而生,可以编写脚本进行重复性...

    Parasoft_JTest 入门教程-通俗易懂

    - **使用方法:** JTest可以通过分析源代码结构自动生成测试用例。 - **3.7 桩函数** - **定义:** 一种模拟其他系统部分的测试工具。 - **作用:** 在测试某个模块时,隔离外部依赖。 - **使用方法:** JTest...

    面向 Java 开发人员的 Ajax: Google Web Toolkit 入门(GWT入门)

    **Java开发人员的Ajax:Google Web Toolkit (GWT) 入门** Google Web Toolkit (GWT) 是一个强大的工具,它允许Java开发人员使用熟悉的Java语言来构建高性能、跨浏览器的Ajax应用程序。GWT通过将Java代码编译为优化...

    软件测试入门(PPT介绍入门级别)

    **软件测试入门(PPT...通过这个入门级的PPT,初学者可以对软件测试有基本认识,并逐步深入学习更多高级主题,如敏捷测试、自动化测试框架和持续集成实践。不断学习和实践,将有助于你在软件测试领域建立坚实的基础。

    Android配置入门样例

    通过实践这些基本步骤和分析"Sudoku"样例,你不仅能掌握Android应用的创建过程,还能为后续的Android开发打下坚实的基础。随着技能的提升,你可以尝试更复杂的项目,如网络通信、数据库操作、多媒体处理等,进一步...

    软件测试工程师入门教程

    2. 白盒测试:又称为结构测试,分析程序的内部逻辑,确保每条路径都得到测试。 自动化测试是现代软件测试的重要组成部分,学习使用自动化工具和框架至关重要。例如,Selenium用于Web应用测试,Appium针对移动应用,...

    Java Web从入门到精通光盘17-1

    此外,学会使用日志框架(如Log4j)来记录和分析应用运行情况也很重要。 综上所述,"Java Web从入门到精通光盘17-1"涵盖了Java Web开发的基础和进阶知识,读者在学习过程中需注意自行配置环境,特别是jar文件的获取...

    IntelliJ IDEA中文教程从入门到进阶

    它的核心特点在于智能代码补全、代码分析和重构工具,以及对框架和库的广泛支持,使得开发过程更加高效。 二、安装与启动 在下载IntelliJ IDEA安装包后,按照向导进行安装。启动IDE后,会看到欢迎界面,你可以选择...

Global site tag (gtag.js) - Google Analytics