junit 经典示例_JUnit 4,JWebUnit,Arquillian和JSF单元示例教程

junit 经典示例

Along side of development lifecycle, most of us looking for a way to be sure that the unit of work that has been written is working properly and committed to its contract. This is actually may be much easier when you come to work with one class and one object as well. But what if you have a massive amount of components that contain a huge set of methods that should be examined.

在开发生命周期中,我们大多数人都在寻找一种方法来确保已编写的工作单元能够正常工作并遵守合同。 当您同时使用一个类和一个对象时,这实际上可能会容易得多。 但是,如果您有大量包含大量应检查方法的组件,该怎么办?

This isn’t the whole picture, while most of software have developed gradually, no one can assure you that he/she has the whole business components before getting started the development process. This will be carrying with some complexity as the implementation of one class may be evolved several times and every time it needs to be re-examined that it’s working properly and that evolution doesn’t break its core functionality.

这还不是全部,尽管大多数软件都是逐步开发的,但是没有人可以在开始开发过程之前就向您保证他/她拥有整个业务组件。 这将带来一些复杂性,因为一个类的实现可能会演化多次,并且每次需要重新检查其运行正常且演化不会破坏其核心功能时,都会对其进行扩展。

Upon that, how much complexity you may face there to re-examine certain class several time to make sure it’s not broken due to certain enhancements you did intentionally or unintentionally – as a normal result for gradual evolving. This is actually the job of JUnit framework and all of its relevant ones that are built on;

在那之后,您可能会面临多少复杂性,以便多次重新检查某个类,以确保它不会由于您有意或无意地进行的某些增强而被破坏-这是逐渐发展的正常结果。 这实际上是JUnit框架及其所有相关基础的工作。

JUnit is an open source software that help you generate Test Cases that can be executed easily, consistently and effectively to verify that your component works as expected and to catch the bugs earlier.

JUnit是一个开源软件,可以帮助您生成可以轻松,一致且有效地执行的测试用例,以验证您的组件是否按预期工作并尽早发现错误。

A lot of frameworks are developed upon JUnit; frameworks like HttpUnit, ServeltUnit, JSFUnit, JWebUnit .. and others, are samples for those software that you may use to verify your components regardless whether your components are so simple or it needs specific container to function.

JUnit上开发了许多框架; 诸如HttpUnitServeltUnitJSFUnitJWebUnit ..等框架都是这些软件的示例,您可以使用它们来验证组件,而无论组件是否如此简单或需要特定的容器来运行。

Here, you will find all what you need to understand the basic terminology of JUnit and use its features effectively. Beside that, you will see how to verify a simple Java Class, Web Page, Portlet and JSF components using JUnit, JWebUnit and JSFUnit (Arquillian) respectively.

在这里,您将找到理解JUnit的基本术语并有效使用其功能所需的全部内容。 除此之外,您还将看到如何分别使用JUnit,JWebUnit和JSFUnit(Arquillian)来验证简单的Java类,Web Page,Portlet和JSF组件。

Following below main bullets that will be discussed at this Tutorial as you may navigate into that one you need directly:

跟随以下主要要点,这些要点将在本教程中讨论,您可以直接导航到需要的那个要点:

To make sure you will be fully aware of all concepts that this tutorial is going to discuss, be sure that you have read these below also:

为确保您完全了解本教程将要讨论的所有概念,请确保还阅读以下内容:

  • JSF Beginner Tutorial which will help you understanding the basic concepts about JSF framework and clarify you the most easy sample.

    《 JSF入门教程》将帮助您了解有关JSF框架的基本概念并阐明最简单的示例。
  • Apache Pluto Tutorial while will help you understanding the basic concepts about Portlet, Portlet Container and clarify you HelloWorld Portlet.

    Apache Pluto教程将帮助您理解有关Portlet,Portlet容器的基本概念,并向您阐明HelloWorld Portlet。

设置JUnit (Setting Up JUnit)

Setting up of JUnit isn’t much more than adding two JARs into your compilation path and execution path. Following below steps all what you need:

设置JUnit只不过是在编译路径和执行路径中添加了两个JAR。 执行以下所有步骤即可:

  • Download JUnit JAR from Maven Central Repository.

    从Maven中央存储库下载JUnit JAR。
  • Download hamcrest library from Maven Central Repository. JUnit actually depends on this library for more attractive, easy and clear assertions.

    从Maven中央存储库下载hamcrest库。 实际上,JUnit依赖于此库来获得更有吸引力,更容易且更明确的断言。
  • Adding JUnit and hamcrest libraries into your classpath. The most easiest way that you may use is by setting these libraries beneath your JDK extension directory.
    • Specify to which JDK your environment has been referring. JAVA_HOME variable should help.
    • Specify the location of JDK extension, always you should be able to find this path beneath your JDK directory. %JAVA_HOME%\jre\lib\ext.

    将JUnit和hamcrest库添加到您的类路径中。 您可以使用的最简单的方法是,将这些库设置在JDK扩展目录下。
    • 指定您的环境所引用的JDK。 JAVA_HOME变量应该有所帮助。
    • 指定JDK扩展的位置,始终可以在JDK目录下找到此路径。 %JAVA_HOME%\ jre \ lib \ ext
    • Be sure that you have JUnit library inside your classpath by invoking java -verbose against console which will print out all loaded classes instantly.

      通过对控制台调用java -verbose ,确保在类路径中具有JUnit库,该控制台将立即打印出所有已加载的类。

Execution of java -verbose

Execution of java -verbose

[Loaded org.junit.runner.JUnitCore from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.notification.RunListener from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.internal.TextListener from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.Describable from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.Runner from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.manipulation.Filterable from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.manipulation.Sortable from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.internal.runners.JUnit38ClassRunner from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.internal.JUnitSystem from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.Computer from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runners.model.RunnerBuilder from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.Computer$1 from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runners.ParentRunner from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runners.Suite from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.notification.RunNotifier from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.notification.SynchronizedRunListener from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
[Loaded org.junit.runner.notification.StoppedByUserException from file:/C:/Program%20Files/Java/jdk1.6.0_26/jre/lib/ext/junit-4.12.jar]
  • Create the most simple Test Case like below

    创建最简单的测试用例,如下所示

HelloWorldTestCase.java

HelloWorldTestCase.java

import org.junit.Test;
import static org.junit.Assert.*;

public class HelloWorldTestCase {

	@Test
	public void testHelloWorld(){
		// Print a message before assertion
		System.out.println("Before Getting Test Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test Execution ::");
	}

	public static void main(String [] args){
		// JUnitCore is provided by JUnit to run your Tests through consols
		org.junit.runner.JUnitCore.runClasses(HelloWorldTestCase.class);
	}
}
  • Open your console and compile the class and then execute it. We have used assertEquals which should compare values of last two arguments (Invoking equals()). More later.

    打开控制台并编译该类,然后执行它。 我们使用了assertEquals,它应该比较最后两个参数的值( Invoking equals() )。 以后再说。
  • JUnitCore is a class provided by JUnit to allow you run and display your result via console directly.

    JUnitCore是JUnit提供的类,可让您直接通过控制台运行和显示结果。
  • Invoke Java compilation and interpretation respectively against your HelloWorldTestCase.

    针对您的HelloWorldTestCase分别调用Java编译和解释。
  • If you have got arguments changed (for example hello and Hello) you would of course see the below result:

    如果您更改了参数(例如hello和Hello),那么您当然会看到以下结果:
  • Second message wasn’t showed due to assertion failure.

    由于断言失败,未显示第二条消息。
  • Don’t consume your time understanding what you had seen on the HelloWorldTestCase, as most of these components/annotations would be subject of next sections.

    不要浪费您的时间来了解您在HelloWorldTestCase上看到的内容,因为大多数这些组件/注释将在下一节中讨论。

Setting your library inside your JDK extension should be much helper than providing them while program execution. This concept is so relevant of the ClassLoader and the way in which it loads the libraries and at which level the extension directory comes.

将库设置在JDK扩展中应该比在程序执行时提供它们大有帮助。 这个概念与ClassLoader及其加载库的方式以及扩展目录所在的级别非常相关。

通过Eclipse利用JUnit (Leverage JUnit Through Eclipse)

Even though you may find JUnit so beautiful while using it through your command console, but when you leverage it inside your Eclipse you will be wondering from these facilities Eclipse can provide which surely will lead you to leave the console without revert.

即使您在通过命令控制台使用JUnit时可能会发现它如此漂亮,但是当您在Eclipse中使用JUnit时,您会想知道Eclipse可以提供的这些功能肯定会导致您退出控制台而无需还原。

Eclipse IDE doesn’t only provide a way to execute your JUnit’s Test Cases properly, but it also provides you a brilliant graphical user interface that would give you indicators whether Test Cases you had ran are finished successfully.

Eclipse IDE不仅提供正确执行JUnit测试用例的方法,而且还为您提供了一个出色的图形用户界面,该界面可以为您指示已运行的测试用例是否成功完成。

Following below, required steps that would lead you for proper usage of JUnit from within Eclipse IDE.

遵循以下步骤,这些步骤将引导您从Eclipse IDE中正确使用JUnit。

  • Remove JUnit and hamcrest JARs from JDK extension so that you will refer those provided by Eclipse itself. Be sure they are removed by invoking java -verbose and looking for JUnit.

    从JDK扩展中删除JUnit和hamcrest JAR,以便您将引用Eclipse本身提供的那些。 确保通过调用java -verbose并查找JUnit将其删除。
  • Install Eclipse IDE, for this tutorial i’ll use Eclipse Kepler.

    安装Eclipse IDE ,在本教程中,我将使用Eclipse Kepler。
  • Create most simple Maven project, by using Eclipse embedded Maven quickstart archetype.

    通过使用Eclipse嵌入式Maven快速入门原型创建最简单的Maven项目。

It supposed to be familiar with Maven, but for those aren’t. Maven is a build tool that can help you generating executable binaries, managing project’s dependencies and much more. Maven also provides you a way to create a standard project with a ready-made internal structure.

它本来应该熟悉Maven,但是对于那些并不是。 Maven是一个构建工具,可以帮助您生成可执行二进制文件,管理项目的依存关系等等。 Maven还为您提供了一种使用现成的内部结构创建标准项目的方法。

  • Fill in all required information, groupId, artifactId and package and then finish.

    填写所有必需的信息,groupId,artifactId和包,然后完成。
  • Make sure your project created recently doesn’t show any issue or errors. In case yes, it shows, just remove parent section as most of these archetypes are too old.

    确保您最近创建的项目没有显示任何问题或错误。 如果显示的是,请删除父节,因为大多数原型都太旧了。
  • Your created project will be having a reference for a JUnit library which is absolutely too old and it needs some refinement. Open your pom file and change version of JUnit library to be 4.12 and add hamcrest maven dependency. Your pom file should be looks like below:

    您创建的项目将具有JUnit库的引用,该库绝对太旧了,需要进行一些改进。 打开您的pom文件,并将JUnit库的版本更改为4.12,并添加hamcrest maven依赖项。 您的pom文件应如下所示:

pom.xml

pom.xml

<?xml version="1.0"?>
<project
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>HelloWorldTestCase</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>HelloWorldTestCase</name>
	<url>https://maven.apache.org</url>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<dependency>
			<groupId>org.hamcrest</groupId>
			<artifactId>hamcrest-core</artifactId>
			<version>1.3</version>
		</dependency>
	</dependencies>
</project>
  • Do a normal clean for your project so that these referenced JARs have been installed.

    对项目进行常规清理,以便已安装这些引用的JAR。
  • Notice that you have inside your project two packages; one represents your classes while other represents Test Cases. I recommend highly delete them for now, so that you may start cleanly.

    请注意,您的项目中有两个软件包。 一个代表您的课程,另一个代表测试用例。 我建议暂时将其高度删除,以便您可以重新启动。

Don’t give com.journaldev package that’s located beneath src/test/java any care as we will have a separate section that shows you how can integrate your JUnit TestCases with Maven build tool.

不要轻易放在src / test / java下面的com.journaldev软件包,因为我们将有单独的部分向您展示如何将JUnit TestCases与Maven构建工具集成。

  • Create HelloWorldTestCase class that you had created before inside your project and beneath your package.

    创建在项目内部之前和包下方创建的HelloWorldTestCase类。

HelloWorldTestCase.java

HelloWorldTestCase.java

package com.journaldev;

import org.junit.Test;
import static org.junit.Assert.*;

public class HelloWorldTestCase {

	@Test
	public void testHelloWorld(){
		// Print a message before assertion
		System.out.println("Before Getting Test Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test Execution ::");
	}

	public static void main(String [] args){
		// JUnitCore is provided by JUnit to run your Tests through console
		org.junit.runner.JUnitCore.runClasses(HelloWorldTestCase.class);
	}
}
  • Compile your project and make sure that you don’t have any errors.

    编译您的项目,并确保没有任何错误。
  • To execute your project, you have two options:
    • Execute it normally just like you did above with any normal Java class that have main method.
    • Execute it using Eclipse IDE’s JUnit facility.

    要执行您的项目,您有两个选择:
    • 就像您对具有main方法的任何普通Java类所做的一样,通常执行它。
    • 使用Eclipse IDE的JUnit工具执行它。
  • Executing the project using the first way would lead you for below result (CTRL + SHIFT + x & j):

    使用第一种方法执行项目将导致您得到以下结果(CTRL + SHIFT + x&j):
  • Executing the project using the second way would lead you for below nice result (CTRL + SHIFT + x & t:

    使用第二种方式执行项目会导致您获得以下不错的结果(CTRL + SHIFT + x&t:
  • As you notice above, there’s now an indicators tell you the result of TestCase beside the above messages on the console.

    如上所述,控制台上的上述消息旁边现在有一个指示器可以告诉您TestCase的结果。

JUnit注释; @ Test,@ Before,@ After,@ AfterClass,@ BeforeClass (JUnit Annotations; @Test, @Before, @After, @AfterClass, @BeforeClass)

From now on, no need to use JUnit through using basic command console, rather consume your time preparing your TestCases and provide a way to run it, use Eclipse directly and enjoy seeing these indicators.

从现在开始,无需通过基本的命令控制台来使用JUnit,而是花时间准备TestCases并提供一种运行它的方法,直接使用Eclipse并欣赏这些指示器。

This usage doesn’t consider defining a main method, thereby, you should use CTRL + SHIFT + x & t at each time you want to execute your Tests.

这种用法不考虑定义main方法,因此,每次执行测试时都应使用CTRL + SHIFT + x&t。

After all of these clarifications that were introduced in previous sections, it’s now the time to focus deeply at JUnit concepts and its various features.

在前面各节中介绍了所有这些澄清之后,现在是时候深入关注JUnit概念及其各种功能了。

To define a TestCase within your class, you shall use @Test annotation in conjunction with your defined method. That class and this method should have the following rules:

要在类中定义TestCase,应将@Test批注与定义的方法结合使用。 该类和此方法应具有以下规则:

  • Your class must be defined as public and have a default constructor (zero argument).

    您的类必须定义为public并具有默认构造函数(零参数)。
  • Your Test method should be defined as a public, take no arguments and return void.

    您的Test方法应该定义为公共方法,不带任何参数并返回void。

Once JUnit framework has met an @Test annotation, it will create an instance of that class that is containing that method and invoking the @Test annotated method. This is the philosophy of JUnit and how it works.

JUnit框架遇到@Test注释后,它将创建该类的实例,该实例包含该方法并调用@Test带注释的方法。 这是JUnit的原理及其工作原理。

If your Test class has two methods annotated with @Test, this means JUnit will create two instances to invoke both of them and so on. Due to this fact, you can’t reuse instance variables values across test methods.

如果您的Test类有两个用@Test注释的方法,则意味着JUnit将创建两个实例来调用这两个实例,依此类推。 因此,您不能在测试方法之间重用实例变量值。

JUnit framework judge certain @Test method by calling assertion(s) it contains, so that be sure that every @Test method has called specific assertions to eliminate any confusion. This confusion happens when you get a result that specific @Test method returns success while no assertions was used there.

JUnit框架通过调用其包含的断言来判断某些@Test方法, 以确保每个@Test方法都调用了特定的断言以消除任何混淆。 当您得到特定的@Test方法返回成功而没有在其中使用任何断言的结果时,就会发生这种混乱。

It’s not recommended providing one more assertion within @Test method, so that you will know exactly which TestCase has failed and due to what it’s got. But actually no constraints has been applied from the JUnit framework itself.

不建议在@Test方法中再提供一个断言,这样您就可以准确知道哪个TestCase失败以及由于什么原因。 但是实际上,JUnit框架本身并未施加任何约束。

You have seen how can one @Test method be used, but let’s now see how can we collaborate one more @Test method simultaneously.

您已经了解了如何使用一种@Test方法,但是现在让我们看看如何同时协作一种@Test方法。

HelloWorldTestCase.java

HelloWorldTestCase.java

package com.journaldev;

import org.junit.Test;
import static org.junit.Assert.*;

public class HelloWorldTestCase {

	@Test
	public void testHelloWorldOne(){
		// Print a message before assertion
		System.out.println("Before Getting Test #1 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #1 Execution ::");
	}

	@Test
	public void testHelloWorldTwo(){
		// Print a message before assertion
		System.out.println("Before Getting Test #2 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #2 Execution ::");
	}	

}

Execution of sample above would result in the below:

执行上面的示例将导致以下结果:

Execution Result

Execution Result

Before Getting Test #1 Started ::
After Test #1 Execution ::
Before Getting Test #2 Started ::
After Test #2 Execution ::
  • As you may notice, two TestCases are executed and the result is drawn through JUnit’s Eclipse indicators.

    您可能会注意到,将执行两个TestCases,并通过JUnit的Eclipse指示器绘制结果。

But what i you want some prior/posterior executions for your Tests, something executed right before or/and after of any @Test method and without any respect being @Test has finished successfully or not. Then, you should use @Before and @After, respectively. Let’s now see how it works after adding these methods that are annotated with @Before and @After.

但是我想为您的测试执行一些之前/之后的执行,在任何@Test方法之前或之后执行的事情,而@Test没有任何方面成功完成与否。 然后,您应该分别使用@Before和@After。 现在让我们看一下在添加使用@Before和@After注释的这些方法之后的工作方式。

HelloWorldTestCase.java

HelloWorldTestCase.java

package com.journaldev;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

public class HelloWorldTestCase {

	@Before
	public void beforeExecutingTestCase(){
		System.out.println("Before Executing Test Case :: ");
	}

	@After
	public void afterExecutingTestCase(){
		System.out.println("After Executing Test Case :: ");
	}

	@Test
	public void testHelloWorldOne(){
		// Print a message before assertion
		System.out.println("Before Getting Test #1 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #1 Execution ::");
	}

	@Test
	public void testHelloWorldTwo(){
		// Print a message before assertion
		System.out.println("Before Getting Test #2 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #2 Execution ::");
	}	

}

Execution of above should lead you for below:

执行以上操作将引导您进行以下操作:

Execution Result

Execution Result

Before Executing Test Case ::
Before Getting Test #1 Started ::
After Test #1 Execution ::
After Executing Test Case ::
Before Executing Test Case ::
Before Getting Test #2 Started ::
After Test #2 Execution ::
After Executing Test Case ::

You may notice above execution of @Before method and @After, before and after every @Test method.

您可能会注意到@Before方法和@After在每个@Test方法之前和之后的执行情况。

One important note here and it’s beware from getting multiple @Before and @After methods defined as no one can tell you what’s the order of their execution.

这里有一个重要的注意事项,它要当心:获取多个定义为@Before和@After的方法,因为没有人可以告诉您它们的执行顺序是什么。

At the other hand, what if you want methods called right before all your @Test methods and after all your @Test methods. This is exactly what you get when you have used @BeforeClass and @AfterClass.

另一方面,如果要在所有@Test方法之前和所有@Test方法之后调用方法,该怎么办? 这就是使用@BeforeClass和@AfterClass时得到的。

HelloWorldTestCase.java

HelloWorldTestCase.java

package com.journaldev;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.*;

public class HelloWorldTestCase {

	@BeforeClass
	public static void beforeExecutingHelloWorldTestCases(){
		System.out.println("Before Executing HelloWorldTestCases :: ");
	}

	@AfterClass
	public static void afterExecutingHelloWorldTestCases(){
		System.out.println("After Executing HelloWorldTestCases :: ");
	}

	@Before
	public void beforeExecutingTestCase(){
		System.out.println("Before Executing Test Case :: ");
	}

	@After
	public void afterExecutingTestCase(){
		System.out.println("After Executing Test Case :: ");
	}

	@Test
	public void testHelloWorldOne(){
		// Print a message before assertion
		System.out.println("Before Getting Test #1 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #1 Execution ::");
	}

	@Test
	public void testHelloWorldTwo(){
		// Print a message before assertion
		System.out.println("Before Getting Test #2 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #2 Execution ::");
	}	

}

Execution result for the above will be:

以上执行结果为:

Execution Result

Execution Result

Before Executing HelloWorldTestCases ::
Before Executing Test Case ::
Before Getting Test #1 Started ::
After Test #1 Execution ::
After Executing Test Case ::
Before Executing Test Case ::
Before Getting Test #2 Started ::
After Test #2 Execution ::
After Executing Test Case ::
After Executing HelloWorldTestCases ::

As you may notice that @BeforeClass and @AfterClass methods have been called once before and after of all your @Test methods.

您可能会注意到,@BeforeClass和@AfterClass方法在所有@Test方法之前和之后都被调用过一次。

超时与预期 (Timeout & Expected)

You have seen how annotations like @Test, @Before, @After, @BeforeClass and @AfterClass be used withing JUnit framework. This section will focus on discussing how a Test case can be await for specific time before got failed and how it can be handle certain exceptions.

您已经了解了如何将@ Test,@ Before,@ After,@ BeforeClass和@AfterClass等注释与JUnit框架一起使用。 本节将重点讨论如何在失败之前的特定时间内等待测试用例,以及如何处理某些异常。

Though no specific annotations could be used but @Test would have now additional attributes that you may use for resolving these features.

尽管不能使用特定的注释,但@Test现在将具有可用于解析这些功能的其他属性。

Timeout argument is passed for @Test annotation to specify to which millisecond(s) this method will be waiting before get failed. This is actually so helpful when you’re going to examine and verify performance of given code.

为@Test注释传递了超时参数,以指定此方法在获取失败之前将等待的毫秒数。 当您要检查和验证给定代码的性能时,这实际上非常有用。

Following sample shows you clearly how this could be used:

以下示例清楚地说明了如何使用它:

HelloWorldTestCase.java

HelloWorldTestCase.java

package com.journaldev;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.*;

public class HelloWorldTestCase {

	@BeforeClass
	public static void beforeExecutingHelloWorldTestCases(){
		System.out.println("Before Executing HelloWorldTestCases :: ");
	}

	@AfterClass
	public static void afterExecutingHelloWorldTestCases(){
		System.out.println("After Executing HelloWorldTestCases :: ");
	}

	@Before
	public void beforeExecutingTestCase(){
		System.out.println("Before Executing Test Case :: ");
	}

	@After
	public void afterExecutingTestCase(){
		System.out.println("After Executing Test Case :: ");
	}

	@Test
	public void testHelloWorldOne(){
		// Print a message before assertion
		System.out.println("Before Getting Test #1 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #1 Execution ::");
	}

	@Test
	public void testHelloWorldTwo(){
		// Print a message before assertion
		System.out.println("Before Getting Test #2 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #2 Execution ::");
	}	

	@Test(timeout=1)
	public void testWaitForATime(){
		// Print statement
		System.out.println("@Test Will Be Waiting For 100 Milliseconds :: Supposed Task Should Be Done Before Timeout");

		// Some adhoc processing
		for(int i = 0 ; i < 1000 ; i++){
			Math.random();
		}
		// Print statement
		System.out.println("Task Done Before Timeout :: This Test Has Finished Sucessfully ::");
	}

}

Here’s detailed information for the code listed above:

以下是上面列出的代码的详细信息:

  • By providing timeout argument, now it could be executing Test method that wouldn’t be exceed specific amount of time (by milliseconds).

    通过提供超时参数,现在可以执行不会超过特定时间量(以毫秒为单位)的Test方法。
  • If execution of this method exceeds the specific amount of milliseconds it would fail even if there’s no failure resulted by certain assertion within that method.

    如果此方法的执行超过了特定的毫秒数,即使该方法中的某些断言没有导致失败,它也将失败。
  • If execution of this method doesn’t exceed the specific amount of milliseconds it would pass successfully if there’s no failure resulted by certain assertion.

    如果此方法的执行未超过特定的毫秒数,则在没有因某些断言而导致失败的情况下,它将成功通过。
  • Setting timeout to 1000 would cause this Test to be finished successfully, while setting it to 10000 wouldn’t.

    将超时设置为1000将导致此测试成功完成,而将其设置为10000则不会成功。

Execution Result - Timeout 10000 Milliseconds
This is all about timeout and how to specify it in conjunction with @Test annotation. But what if you want certain Test method to be failed if certain exception isn’t thrown or vice versa; at certain exception should be considered success.
This is actually what you’re about when you used  expected argument. Following sample shows you a Test method that generates a number and find the result of % 2 to specify if that number is even or not. In case it’s even, a String variable will be initialized, otherwise it’s not.

这全部与超时有关,以及如何与@Test批注一起指定超时。 但是,如果您希望某些Test方法在未引发某些异常的情况下失败,或者反之亦然,该怎么办? 在某些例外情况下应视为成功。
这实际上是使用期望参数时要注意的。 下面的示例向您显示一个Test方法,该方法生成一个数字并查找%2的结果以指定该数字是否为偶数。 如果是偶数,将初始化一个String变量,否则不初始化。

HelloWorldTestCase.java

HelloWorldTestCase.java

package com.journaldev;

import java.io.File;
import java.io.UnsupportedEncodingException;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.*;

public class HelloWorldTestCase {

	@BeforeClass
	public static void beforeExecutingHelloWorldTestCases(){
		System.out.println("Before Executing HelloWorldTestCases :: ");
	}

	@AfterClass
	public static void afterExecutingHelloWorldTestCases(){
		System.out.println("After Executing HelloWorldTestCases :: ");
	}

	@Before
	public void beforeExecutingTestCase(){
		System.out.println("Before Executing Test Case :: ");
	}

	@After
	public void afterExecutingTestCase(){
		System.out.println("After Executing Test Case :: ");
	}

	@Test
	public void testHelloWorldOne(){
		// Print a message before assertion
		System.out.println("Before Getting Test #1 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #1 Execution ::");
	}

	@Test
	public void testHelloWorldTwo(){
		// Print a message before assertion
		System.out.println("Before Getting Test #2 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #2 Execution ::");
	}	

	@Test(timeout=1)
	public void testWaitForATime(){
		// Print statement
		System.out.println("@Test Will Be Waiting For 100 Milliseconds :: Supposed Task Should Be Done Before Timeout");

		// Some adhoc processing
		for(int i = 0 ; i < 100 ; i++){
			Math.random();
		}
		// Print statement
		System.out.println("Task Done Before Timeout :: This Test Has Finished Sucessfully ::");
	}

	@Test(expected=NullPointerException.class)
	public void testNullPointerExceptionShouldBeRaised() throws UnsupportedEncodingException{
		// Define variable
		String variable = null;
		// Get random number
		double value = Math.random() * 100;

		// Print out value
		System.out.println("Value :: "+(int)value);

		if((int)value % 2 == 0){
			// Specify variable value
			variable = "Even Number";
		}
		// Print out variable content with UTF-8 encoding
		System.out.println("This number is :: "+new String(variable.getBytes(),"UTF-8"));
	}

}

Here’d detailed explanation about code listed above:

这是上面列出的代码的详细说明:

  • To specify whether Test method should generate certain exception or not, you should provide expected argument with the @Test annotation.

    若要指定Test方法是否应生成某些异常,应在预期参数中提供@Test批注。
  • If NullPointerException has been thrown, this Test will be passed successfully. Otherwise, it will fail even if its assertion(s) passed.

    如果抛出NullPointerException,则此测试将成功通过。 否则,即使其断言通过,它也将失败。

跑步者和跑步者类型 (Runners & Types of Runners)

You did see in the introduction and in the first example how HelloWorldTestCase works using console command and how it also works from Eclipse by using default normal execution and by using JUnit’s Eclipse built-in features.

您确实在引言和第一个示例中看到了HelloWorldTestCase如何使用控制台命令工作,以及如何通过使用默认常规执行以及JUnit的Eclipse内置功能在Eclipse中工作。

Regardless of the way you had chosen to run your TestCases; either by using JUnit command console or by using Eclipse IDE, your TestCases should be ran by using an implementation of Runner.

无论您选择哪种方式运行TestCases; 通过使用JUnit命令控制台或通过Eclipse IDE,应该使用Runner的实现来运行您的TestCases。

While we have used org.junit.runner.JUnitCore to execute our TestCases from command line or by using Eclipse default class execution (i.e. class with main method), Eclipse uses default built-in native graphical runner to execute them.

当我们使用org.junit.runner.JUnitCore从命令行或使用Eclipse默认类执行(即具有main方法的类)执行TestCases时,Eclipse使用默认的内置本机图形运行程序来执行它们。

Following below table summarizes most runners used by JUnit and their respective purposes:

下表总结了JUnit使用的大多数运行程序及其各自的目的:

RunnerPurpose
org.junit.runner.JUnitCoreIs a facade for running tests, it supports running JUnit 4 test cases, JUnit 3.8 test cases and mixtures.
SuiteIs a standard runner that allows you to manually build a suite containing tests from many classes.
ParametrizedIs a standard runner that allows you to execute test cases with ability to passing parameters.
CategoriesIs a standard runner enabling test cases tagged with certain category to be included/excluded while execution
亚军 目的
org.junit.runner.JUnitCore 是运行测试的外观,它支持运行JUnit 4测试用例,JUnit 3.8测试用例和混合。
套房 是一个标准运行程序,允许您手动构建包含来自许多类的测试的套件。
参数化 是一个标准运行程序,允许您执行具有传递参数功能的测试用例。
分类目录 是标准运行程序,允许在执行时包括/排除带有特定类别标记的测试用例

Let’s now see how each type of these Runners might be used and leveraged. You had seen how JUnitCore could be used so that it won’t be discussed once again.

现在,让我们看看如何使用和利用这些运行器的每种类型。 您已经了解了如何使用JUnitCore,以便不再进行讨论。

Before getting started explaining different types of Runners, it’s important to discuss firstly the concept of @RunWith which is used intensively when it comes to use non-default JUnit Runners.

在开始解释不同类型的Runners之前,重要的是首先讨论@RunWith的概念,在使用非默认JUnit Runners时会大量使用@RunWith

When a class is annotated with @RunWith or extend a class annotated with @RunWith, it will execute its own TestCases using that class mentioned by @RunWith annotation.

当使用@RunWith注释类或扩展使用@RunWith注释的类时,它将使用@RunWith注释所提及的类执行自己的TestCases。

That is, if you want to use Parametrized Runner, you should define @RunWith annotation on your class declaration followed with the Parametrized.class value. Look sample below:

也就是说,如果要使用Parametrized Runner,则应在类声明上定义@RunWith批注,后跟Parametrized.class值。 看下面的例子:

ParametrizedHelloWorldTestCase.java

ParametrizedHelloWorldTestCase.java

package com.journaldev;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class ParametrizedHelloWorldTestCase{

	// Define parametrized's properties
	private String expected;
	private String actualValue;

	public ParametrizedHelloWorldTestCase(String expected, String actualValue) throws Throwable {
		// Set values
		this.expected = expected;
		this.actualValue = actualValue;
	}

	@Parameters
	public static Collection<Object []> dataParameters(){
		return Arrays.asList(new Object[][] {
				{"Hello World","Hello World"} ,
				{"Hi World","HI World"}
				});
	}

	@Test
	public void testConcatenation(){
		// Print out instance reference and values passed
		System.out.println("Instance Reference :: "+this+" :: Expected :: "+this.expected +" :: ActualValue :: "+this.actualValue);
		assertEquals(this.expected, this.actualValue);
	}

}

Here’s detailed explanation for code listed above before seeing the result of execution:

在查看执行结果之前,以下是上面列出的代码的详细说明:

  • @RunWith is used whenever you want to execute your TestCases using non-default Runner. Parametrized is a specialized Runner and therefore, you should define @RunWith followed with the Paramerized.class to tell JUnit framework that you’re going to use Parametrized Runner for executing this Test class.

    每当您要使用非默认Runner执行TestCases时,都使用@RunWith。 Parametrized是专门的Runner,因此,您应在@RunWith和Paramerized.class之后定义,以告诉JUnit框架您将使用Parametrized Runner执行此Test类。
  • To use Parametrized Runner, you should define the following:
    • Define attributes that will be used for passing the parameters. This was done by providing expected and actualValue instance variables.
    • Define the method that would be used to populate Test Data; this method should be annotated with @Parameters, it should also be static and return a Collection<Object[]> type.
    • Define a parametrized constructor that would be used to assign passed Test Data.

    要使用Parametrized Runner,您应该定义以下内容:
    • 定义将用于传递参数的属性。 这是通过提供预期actualValue实例变量来完成。
    • 定义用于填充测试数据的方法 ; 此方法应使用@Parameters进行注释,并且还应该是静态的,并返回Collection <Object []>类型。
    • 定义一个参数化的构造函数,该函数将用于分配传递的测试数据

Now, let’s see the output that resulted in from executing such a program above:

现在,让我们看看上面执行这样的程序所产生的输出:

It’s so important to note the following points upon the result:

在结果上注意以下几点非常重要:

  • As you have two pairs of Test Data {"Hello World","Hello World"} and {"Hi World","HI World"}, and according for being @Test is invoked in conjunction with instance creation, thereby you should notice that we have two different instances with two pairs of parameters. Notice object references.

    由于您有两对测试数据{"Hello World","Hello World"}{"Hi World","HI World"} ,并且由于@Test与实例创建结合被调用,因此您应该注意到我们有两个带有两对参数的不同实例。 注意对象引用。
  • As the first assertEquals is expected to be finished properly while second not, it’s so expected to have the following below indicators.

    由于第一个assertEquals有望正确完成,而第二个assertEquals不能正确完成,因此,它具有以下指标。
  • Two pairs of parameters would initialize two different instances and therefore two different TestCases. If one is failed the whole TestCase would fail as well.

    两对参数将初始化两个不同的实例,因此将初始化两个不同的TestCases。 如果一个失败,整个TestCase也将失败。
  • Creating of these classes and passing respective parameters is the JUnit framework responsibility.

    创建这些类并传递相应的参数是JUnit框架的职责。
  • Number of instances created is equal to number of items defined in the @Parametrized method.

    创建的实例数等于@Parametrized方法中定义的项目数。

Now, let’s look at the second special Runner; it is the suite. If you want to aggregate Test classes, for sure you must use Suite Runner. Following blow sample that shows you how can leverage Suite Runner:

现在,让我们来看第二个特殊的亚军; 这是套房。 如果要聚合测试类,请确保必须使用Suite Runner。 以下打击样本向您展示了如何利用Suite Runner:

SuiteHelloWorldTestCase.java

SuiteHelloWorldTestCase.java

package com.journaldev;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({HelloWorldTestCase.class,ParametrizedHelloWorldTestCase.class})
public class SuiteHelloWorldTestCase {

}

Here’s detailed explanation for the code listed above:

这是上面列出的代码的详细说明:

  • Even that you don’t mention any @Test method, but using CTRL + SHIFT + x & t would lead you to execute all TestCases inside both of HelloWorldTestCase and ParametrizedHelloWorldTestCase respectively.

    即使您没有提到任何@Test方法,但使用CTRL + SHIFT + x&t也会导致您分别在HelloWorldTestCaseParametrizedHelloWorldTestCase执行所有TestCases。
  • Use @Suite and @SuiteClasses for declaring given class as a holder for Test classes and which Test classes should be executed and to which precedence they shall be gone.

    使用@Suite和@SuiteClasses可以将给定的类声明为Test类的持有者,以及应该执行哪些Test类以及将其放到哪个优先级。
  • If you were changed precedence of mentioning Test classes, within @SuiteClasses, the precedence of execution would also be changed as well.

    如果您在@SuiteClasses中更改了提到Test类的优先级,则执行的优先级也将随之更改。
  • Suite class would remain empty as it’s just a holder for the class’s declaration annotation. That is, if you define an @Test method within Suite class, it wouldn’t be executed anymore.

    套件类将保持为空,因为它只是该类的声明注释的持有者。 也就是说,如果您在Suite类中定义@Test方法,它将不再执行。
  • Executing of above code would lead you for the below result. This result below shows you all @Test methods executed from one Test class called now suite.

    执行以上代码将导致您获得以下结果。 下面的结果显示了从一个称为now套件的Test类执行的所有@Test方法。

If you understand Suite Runner properly, you should use Category one smoothly and without any issues. All what you have to do is to categorize your Test classes, and specify which Test classes you would to include/exclude in the execution.

如果您正确理解Suite Runner,则应该顺利使用Category 1。 您要做的只是对Test类进行分类,并指定要在执行中包括/排除的Test类。

It’s so important to know that Category Runner is a special type of Suite, where you should define your Test classes just like you did with Suite special Runner and do the inclusion and exclusion.

知道Category Runner是Suite的一种特殊类型非常重要,您应该像在Suite Special Runner中一样定义Test类,并进行包含和排除。

Following below full sample with the required steps to use Category Runner:

下面是完整的示例,下面是使用类别运行器的必要步骤:

  • Create your categories; which are set of interfaces.

    创建您的类别; 这是一组接口。

Mandatory.java

Mandatory.java

package com.journaldev.categories;

public interface Mandatory {

}

Optional.java

Optional.java

package com.journaldev.categories;

public interface Optional {

}
  • Annotate your Test classes with the wanted category. For example, created ParametrizedHelloWorldTestCase would be annotated as Mandatory while HelloWorldTestCase is Optional.

    用想要的类别注释您的Test类。 例如,创建的ParametrizedHelloWorldTestCase将被标注为强制性,而HelloWorldTestCase是可选的。

ParametrizedHelloWorldTestCase.java

ParametrizedHelloWorldTestCase.java

package com.journaldev;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import com.journaldev.categories.Mandatory;

@RunWith(Parameterized.class)
@Category(Mandatory.class)
public class ParametrizedHelloWorldTestCase{

	// Define parametrized's properties
	private String expected;
	private String actualValue;

	public ParametrizedHelloWorldTestCase(String expected, String actualValue) throws Throwable {
		// Set values
		this.expected = expected;
		this.actualValue = actualValue;
	}

	@Parameters
	public static Collection<Object []> dataParameters(){
		return Arrays.asList(new Object[][] {
				{"Hello World","Hello World"} ,
				{"Hi World","Hi World"}
				});
	}

	@Test
	public void testConcatenation(){
		// Print out instance reference and values passed
		System.out.println("Instance Reference :: "+this+" :: Expected :: "+this.expected +" :: ActualValue :: "+this.actualValue);
		assertEquals(this.expected, this.actualValue);
	}

}

HelloWorldTestCase.java

HelloWorldTestCase.java

package com.journaldev;

import static org.junit.Assert.assertEquals;

import java.io.UnsupportedEncodingException;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.journaldev.categories.Optional;

@Category(Optional.class)
public class HelloWorldTestCase {

	@BeforeClass
	public static void beforeExecutingHelloWorldTestCases(){
		System.out.println("Before Executing HelloWorldTestCases :: ");
	}

	@AfterClass
	public static void afterExecutingHelloWorldTestCases(){
		System.out.println("After Executing HelloWorldTestCases :: ");
	}

	@Before
	public void beforeExecutingTestCase(){
		System.out.println("Before Executing Test Case :: ");
	}

	@After
	public void afterExecutingTestCase(){
		System.out.println("After Executing Test Case :: ");
	}

	@Test
	public void testHelloWorldOne(){
		// Print a message before assertion
		System.out.println("Before Getting Test #1 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #1 Execution ::");
	}

	@Test
	public void testHelloWorldTwo(){
		// Print a message before assertion
		System.out.println("Before Getting Test #2 Started ::");

		// If assertion goes wrong, the execution of Test would fail
		assertEquals("Would Say Hello","Hello","Hello");

		// Print a message after execution of Test; if assertion goes well, this message would be shown
		System.out.println("After Test #2 Execution ::");
	}	

	@Test(timeout=1)
	public void testWaitForATime(){
		// Print statement
		System.out.println("@Test Will Be Waiting For 100 Milliseconds :: Supposed Task Should Be Done Before Timeout");

		// Some adhoc processing
		for(int i = 0 ; i < 100 ; i++){
			Math.random();
		}
		// Print statement
		System.out.println("Task Done Before Timeout :: This Test Has Finished Sucessfully ::");
	}

	@Test(expected=NullPointerException.class)
	public void testNullPointerExceptionShouldBeRaised() throws UnsupportedEncodingException{
		// Define variable
		String variable = null;
		// Get random number
		double value = Math.random() * 100;

		assertEquals("Would Say Hello","Hello","Hello");

		// Print out value
		System.out.println("Value :: "+(int)value);

		if((int)value % 2 == 0){
			// Specify variable value
			variable = "Even Number";
		}
		// Print out variable content with UTF-8 encoding
		System.out.println("This number is :: "+new String(variable.getBytes(),"UTF-8"));
	}

}
  • Providing categories for your created Test classes wouldn’t change anything for them, but they would make them Target for Category Runner. Your Test classes as though would be remain working once CTRL + SHIFT + x & t have been invoked upon them.

    为您创建的Test类提供类别不会对其进行任何更改,但是它们会使它们成为Category Runner的目标。 一旦对它们进行了CTRL + SHIFT + x&t的调用,您的Test类就可以继续工作。

CategorizedHelloWorldTestCase.java

CategorizedHelloWorldTestCase.java

package com.journaldev;

import org.junit.experimental.categories.Categories;
import org.junit.experimental.categories.Categories.ExcludeCategory;
import org.junit.experimental.categories.Categories.IncludeCategory;
import org.junit.runner.RunWith;
import org.junit.runners.Suite.SuiteClasses;

import com.journaldev.categories.Mandatory;
import com.journaldev.categories.Optional;

@RunWith(Categories.class)
@IncludeCategory(Mandatory.class)
@ExcludeCategory(Optional.class)
@SuiteClasses({ParametrizedHelloWorldTestCase.class,HelloWorldTestCase.class})
public class CategorizeHelloWorldTestCase {

}

Here’s detailed explanation for code listed above:

这是上面列出的代码的详细说明:

  • As Category Runner is a special type of suite, so you should use @RunWith but this time with Category.class value.

    由于Category Runner是套件的一种特殊类型,因此您应该使用@RunWith,但是这次使用Category.class值。
  • @SuiteClasses would hold all Targeted Test classes.

    @SuiteClasses将包含所有目标测试类。
  • @IncludeCategory & @ExcludeCategory shall be used to include and exclude Test classes, respectively.

    @IncludeCategory和@ExcludeCategory分别用于包含和排除Test类。
  • Executing of Category Runner implemented above would lead you for below result:

    执行上面实施的Category Runner会导致您获得以下结果:
  • Being @IncludeCategory has mentioned ParametrizedHelloWorldTestCase within its parentheses, then it will be executing.

    @IncludeCategory在其括号内提到了ParametrizedHelloWorldTestCase ,然后它将执行。
  • Being @ExecludeCategory has mentioned HelloWorldTestCase within its parentheses, then it won’t be executing.

    @ExecludeCategory在其括号内提到了HelloWorldTestCase ,因此它将不会执行。

断言和断言类型 (Assertions & Types of Assertions)

You did see before using of assert(*) inside our @Test method, and according of best practices, every @Test method should include one of assert(*) static methods so that the JUnit framework can validate this Test case and makes sure it’s passed or failed.

您确实在@Test方法中使用assert(*)之前就已经看到过,并且根据最佳实践,每个@Test方法都应包括一个assert(*)静态方法,以便JUnit框架可以验证此Test用例并确保它是通过或失败。

All of our example was used assertEquals which is known as a type of assertions that you may use. This section is provided here to help you seeing all types of assertions so that leverage what you want inside your @Test methods.

我们所有的示例都使用assertEquals ,它被称为可以使用的一种断言。 这里提供本节的内容是为了帮助您查看所有类型的断言,以便在@Test方法中利用所需的内容。

Following Table shows you the most list of assertions could be used:

下表显示了可以使用的最多断言列表:

Assert MethodWhat’s It Used For
assertArrayEquals(“message”,A,B)Asserts the equality of the A and B arrays
assertEquals(“message”,A,B)Asserts the equality of objects A and B.
This assert will actually invokes the equals() method on the first object against second.
assertSame(“message”,A,B)Asserts that the A and B objects have the same value.
assertTrue(“message”,A)Asserts that A condition is evaluated to true
assertNotNull(“message”,A)Asserts that A isn’t null
断言方法 它是做什么用的
assertArrayEquals(“ message”,A,B) 断言A和B数组的相等性
assertEquals(“ message”,A,B) 声明对象A和B的相等性。
该断言实际上将针对第二个对象在第一个对象上调用equals()方法。
assertSame(“ message”,A,B) 断言A和B对象具有相同的值。
assertTrue(“ message”,A) 断言条件评估为真
assertNotNull(“ message”,A) 断言A不为空

Before have discussion for these assertions and how they could be used while using JUnit framework and provide their respective samples. It’s important to know what’s pattern they are followed.

在讨论这些断言以及在使用JUnit框架时如何使用它们并提供它们各自的示例之前,请先进行讨论。 了解它们遵循的模式很重要。

All assertions method have followed the rule: message, expected, result when you’re providing its arguments. That is, passing assertion method’s argument shall be according for that rule.

所有的断言方法都遵循以下规则:提供其参数时,消息,预期结果。 也就是说,传递断言方法的参数应符合该规则。

You should pass the message that assertions would throw once it’s failed followed with the expected value that the assert would act upon and the result (Result of your equation or actual value) that will expected value be compared with.

您应该传递一条消息,即断言失败后将抛出断言,然后是断言将要作用于其上的期望值以及与期望值进行比较的结果(方程式或实际值的结果)。

There’s also a Delta argument that you have used sometimes with some of types of assertions like assertEquals when it takes double arguments. This Delta value is used to determine if your actual value (Result of your equation) is within expected – delta and expected + delta.

还有一个Delta参数,当它使用双参数时,有时会与某些断言类型(如assertEquals)一起使用。 此Delta值用于确定您的实际值(方程式的结果)是否在期望值–增量和期望值+增量之内。

Now, following sample shows you all of these mentioned assertions in one full demonstration:

现在,以下示例在一个完整的演示中向您展示了所有上述提及的断言:

AssertionTypesTestCase.java

AssertionTypesTestCase.java

package com.journaldev;

import org.junit.Test;

public class AssertionTypesTestCases {
	@Test
	public void assertEqualArrays(){

		// Declare first array
		int [] arr1 = {1,2,3,4};

		// Declare second array
		int [] arr2 = {1,2,3,4};

		// Assert
		org.junit.Assert.assertArrayEquals("Arrays Aren't Equal ::", arr1, arr2);
	}

	@Test
	public void assertNoEqualArrays(){
		// Declare first array
		int [] arr1 = {1,2,3,4};

		// Declare second array
		int [] arr2 = {1,2,3,5};

		// Assert
		org.junit.Assert.assertArrayEquals("Arrays Aren't Equal ::", arr1, arr2);
	}	

	@Test
	public void assertEquals(){
		// Declare first object
		String message1 = "Hi World";

		// Declare second object
		String message2 = "Hi World";

		// Assert
		org.junit.Assert.assertEquals("Objects Aren't Equal ::", message1, message2);
	}

	@Test
	public void assertNotEquals(){
		// Declare first object
		String message1 = "Hi World";

		// Declare second object
		String message2 = "HI World";

		// Assert
		org.junit.Assert.assertEquals("Objects Aren't Equal ::", message1, message2);
	}	

	@Test
	public void assertSame(){
		// Declare first object
		String message1 = "Hi World";

		// Declare second object
		String message2 = message1;

		// Assert
		org.junit.Assert.assertSame("Objects Aren't Same ::", message1, message2);
	}

	@Test
	public void assertNotSame(){
		// Declare first object
		String message1 = "Hi World";

		// Declare second object
		String message2 = "HI World"; // if you make it Hi World, this assertion would pass

		// Assert
		org.junit.Assert.assertSame("Objects Aren't Same ::", message1, message2);
	}

	@Test
	public void assertTrue(){
		// Declare first object
		String message1 = "Hi World";

		// Declare second object
		String message2 = message1;

		// Assert
		org.junit.Assert.assertTrue("Result Isn't True ::", message1.equals(message2));
	}

	@Test
	public void assertNotTrue(){
		// Declare first object
		String message1 = "Hi World";

		// Declare second object
		String message2 = "Hi World";

		// Assert
		org.junit.Assert.assertSame("Result Isn't True ::", message1.equals(message2));
	}	

	@Test
	public void assertNull(){
		// Declare first object
		String message1 = null;

		// Assert
		org.junit.Assert.assertNull("Result Is Null ::", message1);
	}

	@Test
	public void assertNotNull(){
		// Declare first object
		String message1 = "Hi World";

		// Assert
		org.junit.Assert.assertNull("Result Isn't True ::", message1);
	}		

}

Here’s below the result of execution as half of them failed cause the their respective assertions had failed also which will lead finally for whole Test class to be failed.

这是执行结果的下方,因为其中一半失败,因为它们各自的断言也失败了,这最终将导致整个Test类失败。

Notice that all failed assertions would have a resulted in error message that’s shown. This message is provided through assert(*) itself.

请注意,所有失败的断言都会导致显示错误消息。 该消息是通过assert(*)本身提供的。

关于Hamcrest图书馆的一点点 (Little Bit About Hamcrest Library)

You did see above how much Assert(*) method help you judge given equations and assert upon them to make up finally your Test Cases. These assertions aren’t just those provided by JUnit itself. Hamcrest library also makes an extension for JUnit and provide you another set of them (Let’s called them matchers)

您确实在上面看到了多少Assert(*)方法可以帮助您判断给定的方程式并对其进行断言,最终构成您的测试用例。 这些断言不仅仅是JUnit本身提供的断言。 Hamcrest库还对JUnit进行了扩展,并为您提供了另一套(称为“匹配器”)

This section would focus the light into most used of them and provide you the way in which they can be leveraged. Following below Table lists most of them:

本节将重点介绍最常用的方法,并为您提供可以利用它们的方法。 下表下方列出了其中大多数:

MatcherDescription
containsStringTests whether a given string contains certain string
startWithTests whether a given string starts with a certain string
endsWithTests whether a given string ends with certain string
equalToIgnoringCaseTests whether a given string equals another one, ignoring case
equalToIgniringWhiteSpaceTests whether a given string equals another one, ignoring white spaces
closeToTests whether a given number is close to another number
greaterThanTests whether a given number is greater than another number
greaterThanOrEqualTests whether a given number is greater than or equal to another number
lessThan, lessThanOrEqualTests whether a given number is less than another number or if it is less than or equal another number; respectively
hasItem, hasItemsTests whether a given object(s) is presence in a collection
hasEntry, hasKey, hasValueTests whether a given entry <Key,Value>, key or value is presence in a Map
hasPropertyTests whether a given instance has a given property
notNullValue, nullValueTests whether a given reference is referring to null or not
sameInstanceTests whether a given two instances are referring the same object
instanceOf, isCompatibleTypeTests whether a given objects are of compatible type (are instances of another one)
notTests negation of a given matcher
anyOfCompose set of matchers with OR condition
allOfCompose set of matchers with AND condition
匹配器 描述
containsString 测试给定的字符串是否包含某些字符串
从...开始 测试给定的字符串是否以某个字符串开头
以。。结束 测试给定的字符串是否以某些字符串结尾
equalToIgnoringCase 测试给定的字符串是否等于另一个,忽略大小写
equalToIgniringWhiteSpace 测试给定的字符串是否等于另一个,忽略空格
相近 测试给定数字是否接近另一个数字
比...更棒 测试给定数字是否大于另一个数字
大于等于 测试给定数字是否大于或等于另一个数字
小于,小于或等于 测试给定数字是否小于另一个数字,或者小于或等于另一个数字; 分别
hasItem,hasItems 测试给定对象是否存在于集合中
hasEntry,hasKey,hasValue 测试给定条目<Key,Value>,键或值是否存在于Map中
hasProperty 测试给定实例是否具有给定属性
notNullValue,nullValue 测试给定引用是否引用了null
sameInstance 测试给定的两个实例是否引用相同的对象
instanceOf,isCompatibleType 测试给定对象是否为兼容类型(是另一个对象的实例)
测试给定匹配器的否定
任何 用OR条件组成一组匹配器
所有的 用AND条件组成一组匹配器

And here’s below a provided sample that would use all of these matchers:

下面是提供的示例,该示例将使用所有这些匹配器:

HamcrestTestCases.java

HamcrestTestCases.java

package com.journaldev;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.hamcrest.object.IsCompatibleType;
import org.junit.Test;

public class HamcrestTestCases {

	@Test
	public void testStartWith(){

		// Create Employee instance
		Employee employee = new Employee();

		// Using assertThat to evaluate specific matcher
		assertThat(employee.getName(), startsWith("Empty"));
	}

	@Test
	public void testEndsWith(){

		// Create Employee instance
		Employee employee = new Employee();

		// Using assertThat to evaluate specific matcher
		assertThat(employee.getName(), endsWith("Name"));
	}	

	@Test
	public void testContainsWith(){

		// Create Employee instance
		Employee employee = new Employee();

		// Using assertThat to evaluate specific matcher
		assertThat(employee.getName(), containsString("y N"));
	}	

	@Test
	public void testEqualToIgnoringCase(){
		// Create Employee instance
		Employee employee = new Employee();

		// Using assertThat to evaluate specific matcher
		assertThat(employee.getName(), equalToIgnoringCase("eMpTy NaMe"));
	}

	@Test
	public void testEqualToIgnoringWhiteSpace(){
		// Create Employee instance
		Employee employee = new Employee();

		// Using assertThat to evaluate specific matcher
		assertThat(employee.getName(), equalToIgnoringWhiteSpace("    Empty       Name       "));
	}	

	@Test
	public void testhasItem(){
		// Create Employee instance
		Employee employee = new Employee();

		// Create employees list
		List<Employee> employees = new ArrayList<Employee>();

		// Add employee
		employees.add(employee);

		// Using assertThat to evaluate specific matcher
		assertThat(employees,hasItem(employee));
	}	

	@Test
	public void testhasItems(){
		// Create Employee instance
		Employee employee1 = new Employee();

		// Create Employee instance
		Employee employee2 = new Employee();		

		// Create employees list
		List<Employee> employees = new ArrayList<Employee>();

		// Add employee
		employees.add(employee1);

		// Add employee
		employees.add(employee2);

		// Using assertThat to evaluate specific matcher
		assertThat(employees,hasItems(employee1,employee2));
	}	

	@Test
	public void testhasEntry(){
		// Create Employee instance
		Employee employee1 = new Employee();

		employee1.setName("Mohammad");

		// Create a Map
		HashMap<String,Employee> employees = new HashMap<String,Employee>();

		// Add employee 1
		employees.put(employee1.getName(), employee1);

		// Assert
		assertThat(employees, hasEntry(employee1.getName(), employee1));
	}	

	@Test
	public void testhasProperty(){
		// Create Employee instance
		Employee employee = new Employee();

		// Assert
		assertThat(employee, hasProperty("name"));
	}	

	@Test
	public void testNotNull(){
		// Create Employee instance
		Employee employee = new Employee();

		// Assert
		assertThat(employee, notNullValue());
	}	

	@Test
	public void testSameInstance(){
		// Create employee
		Employee employee = new Employee();

		// Declare another employee variable
		Employee employee2 = employee;

		// Assert
		assertThat(employee, sameInstance(employee2));
	}

	@Test
	public void testInstanceOf(){
		// Create employee
		Employee employee = new Employee();

		// Assert
		assertThat(employee, instanceOf(Person.class));
	}	

	@Test
	public void testNotInstanceOf(){
		// Create employee
		Person person = new Person();

		// Assert
		assertThat(person, not(instanceOf(Employee.class)));
	}

	@Test
	public void testIsCompatibleType(){

		// Create isCompatible Matcher
		IsCompatibleType<Person> isPersonCompatible = new IsCompatibleType<Person>(Person.class);

		// Create isCompatible Matcher
		IsCompatibleType<Employee> isEmployeeCompatible = new IsCompatibleType<Employee>(Employee.class);

		// Assert; Employee class definition is compatible (instance) with/of Person
		assertThat(Employee.class,isPersonCompatible);

		// Assert; Person class definition is compatible (instance) with/of Person
		assertThat(Person.class,isPersonCompatible);

		// Assert; Person class definition is not compatible (instance) with/of Employee
		assertThat(Person.class,not(isEmployeeCompatible));
	}

	@Test
	public void testIsNotCompatibleType(){

		// Create isCompatible Matcher
		IsCompatibleType<String> isNotCompatible = new IsCompatibleType<String>(String.class);

		// Assert; employee class definition isn't compatible/instance with/of String
		assertThat(Employee.class,not(isNotCompatible));
	}

	@Test
	public void testAnyOf(){

		// Create isCompatible Matcher
		IsCompatibleType<Person> isPersonCompatible = new IsCompatibleType<Person>(Person.class);

		// Create isCompatible Matcher
		IsCompatibleType<Employee> isEmployeeCompatible = new IsCompatibleType<Employee>(Employee.class);

		// Assert; employee class is instance of Person OR employee
		assertThat(Employee.class,anyOf(isPersonCompatible,isEmployeeCompatible));
	}

	@Test
	public void testAllOf(){

		// Create isCompatible Matcher
		IsCompatibleType<Person> isPersonCompatible = new IsCompatibleType<Person>(Person.class);

		// Create isCompatible Matcher
		IsCompatibleType<Employee> isEmployeeCompatible = new IsCompatibleType<Employee>(Employee.class);

		// Assert; Person class is an instance of Person AND not of Employee
		assertThat(Person.class,allOf(isPersonCompatible,not(isEmployeeCompatible)));
	}					

}

class Person {

	private String type;

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

}

class Employee extends Person{

	private int id = 0;
	private String name = "Empty Name";

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

}

Basically, JUnit framework doesn’t provide you that level of controlling the Hamcrest library do, so that it’s much better for you to combine both of them JUnit and Hamcrest to make sure that you are having reliable, specific and easy Test Cases.

基本上,JUnit框架没有为您提供控制Hamcrest库的功能,因此最好将JUnit和Hamcrest两者结合使用,以确保您拥有可靠,特定且简单的测试用例。

Now, you can execute it by invoking CTRL + SHIFT + x + t to get the below result:

现在,您可以通过调用CTRL + SHIFT + x + t来执行它,以得到以下结果:

JUnit扩展– JWebUnit (JUnit Extension – JWebUnit)

JWebUnit is a framework built based on JUnit and it provides a way to write test cases for web applications testing purposes. Following sample shows you how it might be used for writing a test cases against the most simple HelloWorldPortletthat was written previously in one of these tutorials provided for Apache Pluto Portal.

JWebUnit是基于JUnit构建的框架,它提供了一种编写测试用例的方法,以用于Web应用程序测试。 以下示例向您展示了如何将其用于针对最简单的HelloWorldPortlet编写测试用例,该最简单的HelloWorldPortlet先前是在为Apache Pluto Portal提供的这些教程之一中编写的。

Using of Apache Pluto Portal would make writing the JWebUnit cases much more interesting as you should pass a login screen and navigate into your Portal pages before getting your HelloWorldPortlet – Actually your web resource – examined.

使用Apache Pluto Portal将使编写JWebUnit案例更加有趣,因为在检查HelloWorldPortlet (实际上是Web资源)之前,您应该通过登录屏幕并导航到Portal页面。

Actually i did some minor modifications at the example that would be shown right here. This modifications get place to make sure JWebUnit is able to recognize some of components that are used.

实际上,我在示例中做了一些小的修改,将在此处显示。 进行此修改可确保JWebUnit能够识别所使用的某些组件。

HelloWorldPortlet.java

HelloWorldPortlet.java

package com.journaldev.portlet;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class HelloWorldPortlet extends GenericPortlet {
	private static int renderCount = 0;
	private static int actionCount = 0;

	public void doView(RenderRequest request, RenderResponse response)
			throws PortletException, IOException {

		synchronized(this){
			renderCount++;
		}
		response.getWriter().print("<form id='main' action="+response.createActionURL()+">"
				+ "<p>Render has executed "+renderCount+"</p>"
				+ "<p>Action has executed "+actionCount+"</p>"
				+ "<button id='submit' value='submit' type='submit'>Submit</button>"
				+ "</form>");
	}

	public void processAction(ActionRequest actionRequest, ActionResponse actionResponse){
		synchronized(this){
			actionCount++;
		}
	}

    public void init( PortletConfig config ) throws PortletException {
        super.init( config );
    }
}

Here’s below hints for the component written above:

以下是上面编写的组件的提示:

  • HelloWorldPortlet is a simple Portlet resource that is responsible to show a simple form with ability to make a submission upon it.

    HelloWorldPortlet是一个简单的Portlet资源,它负责显示具有在其上进行提交的能力的简单表单。
  • Accessing HelloWorldPortlet Portal page would increase the render counter by one.

    访问HelloWorldPortlet门户页面将使渲染计数器增加一。
  • Submitting action button against HelloWorldPortlet would increase the action request by one.

    针对HelloWorldPortlet提交操作按钮将使操作请求增加一。

Following below series of images would clarify you HelloWorldPortlet execution and business scenarios that you have to examine through JWebUnit.

下面的一系列图像将阐明您必须通过JWebUnit检查的HelloWorldPortlet执行和业务场景。

  • Access Apache Pluto Portal base url https://10.10.90.3:8080/pluto.

    访问Apache Pluto Portal基本URL https://10.10.90.3:8080/pluto
  • Make sure you have modified tomcat-users.xmlso that tomcat user is allowed to access and manage.

    确保已修改了tomcat-users.xml以便允许tomcat用户访问和管理。
  • Enter tomcat as a username and password and submit login.

    输入tomcat作为用户名和密码并提交登录。
  • Navigate into Apache Pluto Home page.

    导航到Apache Pluto主页。

Portlet isn’t a standalone web resource, so that to make it accessible you should embed it inside a Portal page. We have created a HelloWorld Portal page and you’re able to do that by following the basic instructions in the referenced Apache Pluto tutorial above.

Portlet不是独立的Web资源,因此要使其可访问,应将其嵌入Portal页面中。 我们已经创建了一个HelloWorld Portal页面,您可以按照上面引用的Apache Pluto教程中的基本说明进行操作。

  • Create a HelloWorld Portal page and add HelloWorldPortlet inside it.

    创建一个HelloWorld Portal页面,并在其中添加HelloWorldPortlet
  • Initially, by each request on the HelloWorld Portal page, the HelloWordlPortlet would be rendered one more. In case you have copy the link https://10.10.90.3:8080/pluto/portal/HelloWorld once again and type it onto another Tab within the same browser, you would see Render has executed 2 and so on.

    最初,根据HelloWorld Portal页面上的每个请求,将再次渲染HelloWordlPortlet 。 如果您再次复制了链接https://10.10.90.3:8080/pluto/portal/HelloWorld ,并在同一浏览器中将其键入到另一个Tab,您将看到Render has executed 2 ,依此类推。
  • Action request is the second type of request that Portlet supports. Portlet has two different request types in its lifecycle.

    操作请求是Portlet支持的第二种请求类型。 Portlet在其生命周期中具有两种不同的请求类型。
  • To make sure you’re getting an action request, you should get Submit button clicked. That would also initiate another render request, so that you have to see Render has executed 2 and Action has executed 1.

    为确保收到动作请求,应单击“提交”按钮。 这还会启动另一个渲染请求,因此您必须看到“渲染已执行2”和“动作已执行1”。

Now, you have seen how HelloWorldPortletworks against your actions that you did upon it. But what if you don’t want to process this directly into browser and want to execute this through using of JWebUnit.

现在,您已经了解到HelloWorldPortlet如何针对您对它执行的操作进行工作。 但是,如果您不想直接将其处理到浏览器中并希望通过使用JWebUnit来执行此操作,该怎么办。

In face and indeed, this automatic execution may lead you for a huge set of Test Cases that get running at every time you want, so that you will make sure your modifications, refinement and refactoring don’t break the basic functionality of your Portlet.

表面上,实际上,这种自动执行可能会导致您产生大量的测试用例,这些用例可在每次您想要的时间运行,从而确保您所做的修改,完善和重构不会破坏Portlet的基本功能。

Following sample shows you a Test Case class that would get this scenario above examined:

下面的示例向您展示了一个测试案例类,可以通过上面的例子来研究这种情况:

HelloWorldPortletTestCase.java

HelloWorldPortletTestCase.java

package com.journaldev;

import net.sourceforge.jwebunit.junit.JWebUnit;

import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.JVM)
public class HelloWorldPortletTestCase {

	@Before
	public void prepareBaseURL(){
		// Set base URL that JWebUnit will start from
		JWebUnit.setBaseUrl("https://10.10.90.3:8080/pluto");
	} 

	@Test
	public void testBaseUrl(){
		// Begin a conversation
		JWebUnit.beginAt("/portal");
	}

	@Test
	public void testShowingAndPopulatingLoginScreen(){

		// Assert if login screen is displayed, so that username and password field would be shown

		JWebUnit.assertTextFieldEquals("j_username", "");
		JWebUnit.assertTextFieldEquals("j_password", "");		

		// Populating login screen with the required values
		JWebUnit.setTextField("j_username", "tomcat");
		JWebUnit.setTextField("j_password", "tomcat");

		// Assert populating is done properly
		JWebUnit.assertTextFieldEquals("j_username", "tomcat");
		JWebUnit.assertTextFieldEquals("j_password", "tomcat");

		// Login Into Portal
		JWebUnit.clickButtonWithText("Login");
	}

	@Test
	public void testNavigateIntoHelloWorldPortalPage(){
		// Check if HelloWorld Portal page is exist or not
		JWebUnit.assertLinkPresentWithText("HelloWorld");
	}

	@Test
	public void testDoActualNavigationIntoHelloWorldPortalPage(){
		// Navigate into HelloWorld Portal page
		JWebUnit.clickLinkWithExactText("HelloWorld");

		// Check of the Render has executed message
		JWebUnit.assertTextPresent("Render has executed 1");
	}	

	@Test
	public void testInitiateActionRequestUponHelloWorldPortlet(){
		// Check if the submit button is exist
		JWebUnit.assertButtonPresent("submit");

		// Click submit against HelloWorld Portlet
		JWebUnit.clickButton("submit");
	}

	@Test
	public void testMessagesAfterActionRequestUponHelloWorldPortlet(){
		// Check of the Render has executed message
		JWebUnit.assertTextPresent("Render has executed 2");

		// Check of the Action has executed message
		JWebUnit.assertTextPresent("Action has executed 1");
	}
}

Here’s detailed information for code listed above:

以下是上面列出的代码的详细信息:

  • I have broke down above passed functional use case into multiple Test Cases.

    我已经将上面通过的功能用例分解成多个测试用例。
  • These Test Cases won’t be executed sequentially if you didn’t use @FixMethodOrder(MethodSorters.JVM). As JUnit suppose that every @Test case is so dependent from another while the fact they’re not at least in our example.

    如果不使用@FixMethodOrder(MethodSorters.JVM)这些测试用例将不会顺序执行。 正如JUnit假设的那样,每个@Test案例都彼此依赖,而事实上至少在我们的示例中它们并非如此。
  • Every functional case has examined while normal browser navigation is written at the above example as a Test case. Locate base URL, starting conversation, Showing and populating login screen, checking existence of HelloWorld Portal page, navigating into it, checking result of navigation, initiating Action request, checking whether the action request initiated is done properly.

    在上面的示例中将正常的浏览器导航作为测试用例时,已经检查了每个功能用例。 找到基本URL,开始对话,显示并填充登录屏幕,检查HelloWorld Portal页面的存在,导航到该页面,检查导航结果,启动Action请求,检查启动的Action请求是否正确完成。
  • @FixMethodOrder has been released since JUnit 4.11 release, so be careful from executing the same application using different release of JUnit rather than this mentioned in the pom file or one later.

    @FixMethodOrder自JUnit 4.11发布以来已发布,因此请谨慎使用不同版本的JUnit执行相同的应用程序,而不要使用pom文件或更高版本中提到的版本。

Below is the result of execution above Test Cases; in case you don’t have this proper result, you can use JWebUnit.getPageSource()that would consume returned HTML.

以下是上述测试用例的执行结果; 如果没有适当的结果,可以使用JWebUnit.getPageSource()来消耗返回HTML。

As you may noticed above, all Test Cases have been passed successfully and that means that we are able to have the same result that you did see while using the normal navigation against the browser.

正如您可能在上面注意到的那样,所有测试用例均已成功通过,这意味着我们可以对浏览器使用常规导航时获得与您看到的相同结果。

Actually using JWebUnit against any Web resource, like Servlet, JSP, HTML and any resource that’s resulted in an HTML response would be much easier than using it against Apache Portal web application. To make sure we have had the most cases that should be covered, the given sample was within Apache Pluto Portal.

实际上,将JWebUnit用于任何Web资源(例如Servlet,JSP,HTML以及导致HTML响应的任何资源),比将其用于Apache Portal Web应用程序要容易得多。 为了确保我们拥有应涵盖的大多数情况,给定的示例位于Apache Pluto Portal中。

JUnit扩展– JSFUnit (JUnit Extension – JSFUnit)

Even that you may find a JSFUnit on the internet for JBoss, but it’s actually not a straight forward framework and you need some awareness for the core of it to make it used willingly.

即使您可能在Internet上也可以找到JBoss的JSFUnit,但是它实际上并不是一个简单的框架,您需要对其核心有一些了解,才能乐意使用它。

Talking about JSF, means that you have a Servlet container that serves your application. And there’s a lot of components to be examined; Managed Beans, View IDs, expressions evaluation and many others. All of these components aren’t just plain Java classes, and thereby they need away to access it and specify their values easily.

谈论JSF,意味着您有一个服务于您的应用程序的Servlet容器。 而且有很多组件需要检查; 托管Bean,视图ID,表达式评估等。 所有这些组件不仅是普通的Java类,因此它们需要访问它并轻松指定其值。

At this section you’re going to use a container to make sure your Test Cases are running effectively, beside all of that, you’re going also to learn the most amazing JBoss’s framework which is used mainly for this purpose and it’s Arquillian.

在本节中,您将使用一个容器来确保您的测试用例有效运行, 除此之外 ,您还将学习最神奇的JBoss框架,该框架主要用于此目的,它是Arquillian

Arquillian is a massive framework that can be used to write real Test Cases that adhere concept Test In Container  for a Java Enterprise Edition.

Arquillian是一个庞大的框架,可用于编写遵循Java Enterprise Edition的概念Test In Container的真实测试用例。

Without any need for getting certain container up and running, you may configuring Arquillian to connect any container you want and then executing your Test Cases effectively.

无需启动和运行某些容器,您可以配置Arquillian以连接所需的任何容器,然后有效地执行测试用例。

For this purpose, I want to introduce you a way to assure that the JSF application referred here is executing properly and getting expected output without need for executing it on a Tomcat container.

为此,我想向您介绍一种方法,以确保此处引用的JSF应用程序能够正确执行并获得预期的输出,而无需在Tomcat容器上执行它。

That sample above is slightly modified, through using of faces-config.xml file rather using of JSF annotations. This is done like that to make sure the concept of Micro Deployment is so clear and for those who are using JSF 1.x.

通过使用faces-config.xml文件而不是使用JSF批注,对上面的示例进行了稍微的修改。 This is done like that to make sure the concept of Micro Deployment is so clear and for those who are using JSF 1.x.

Before getting started explaining a full example of how could Arquillian be used to achieve this mission, let’s look firstly at those assets your Arquillian Test Case should have:

Before getting started explaining a full example of how could Arquillian be used to achieve this mission, let's look firstly at those assets your Arquillian Test Case should have:

  • @RunWith that would refer for Arquillian Test Runner.

    @RunWith that would refer for Arquillian Test Runner.
  • Public static method that’s annotated with @Deployment.

    Public static method that's annotated with @Deployment.
  • At least one method annotated with @Test.

    At least one method annotated with @Test.

Take into consideration as well:

Take into consideration as well:

  • Using latest version of Arquillian JSF Unit Integration.

    Using latest version of Arquillian JSF Unit Integration.
  • Using Tomcat 7.

    Using Tomcat 7.
  • Using of JDK 1.6.

    Using of JDK 1.6.

First and foremost, let’s have a fast look at every component Arquillian framework has used:

First and foremost, let's have a fast look at every component Arquillian framework has used:

  • @Deployment: is a mandatory method for tests that run inside a container to generate the Archive deployment (Micro Deployment); Java Archive (JAR), Web Archive (WAR) and Enterprise Archive (EAR). This archive deployment has been prepared by ShrinkWrap.

    @Deployment : is a mandatory method for tests that run inside a container to generate the Archive deployment (Micro Deployment); Java Archive (JAR), Web Archive (WAR) and Enterprise Archive (EAR). This archive deployment has been prepared by ShrinkWrap.

ShrinkWrap is a Java API for creating archives (jar, war and ear) in Java. By using ShrinkWrap, you’re focusing on your Test Cases, by bringing all required libraries instead of bring all of them. As you may see below within the sample, no need to include all libraries within your Archive.

ShrinkWrap is a Java API for creating archives (jar, war and ear) in Java. By using ShrinkWrap, you're focusing on your Test Cases , by bringing all required libraries instead of bring all of them. As you may see below within the sample, no need to include all libraries within your Archive.

  • @RunWith: is discussed previously, as it’s used to mark different Test Runner to be used. With Arquillian framework, you must annotate your Test Cases using it to make sure you’re getting it executing properly.

    @RunWith : is discussed previously, as it's used to mark different Test Runner to be used. With Arquillian framework, you must annotate your Test Cases using it to make sure you're getting it executing properly.

If you do revert back into sample mentioned, you should see it’s so simple JSF application as it contains:

If you do revert back into sample mentioned, you should see it's so simple JSF application as it contains:

  • Simple helloWorld.xhtml web resource.

    Simple helloWorld.xhtml web resource.
  • Simple faces-config.xml that’s contained one Managed Bean defined.

    Simple faces-config.xml that's contained one Managed Bean defined.
  • Simple web XML file.

    Simple web XML file.
  • Simple Managed Bean that’s contained one attribute called s1.

    Simple Managed Bean that's contained one attribute called s1 .
  • JSF implementation and API libraries.

    JSF implementation and API libraries.
  • JSTL library.

    JSTL library.

The same sample would be used here except as we mentioned using of faces-config.xml rather using its annotations.

The same sample would be used here except as we mentioned using of faces-config.xml rather using its annotations.

Now, look below at the Arquillian Test Class followed with the required libraries inside your pom file:

Now, look below at the Arquillian Test Class followed with the required libraries inside your pom file:

ArquillianHelloWorldTestCase.java

ArquillianHelloWorldTestCase.java

package com.journaldev;

import java.io.File;
import java.io.IOException;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.jsfunit.api.InitialPage;
import org.jboss.jsfunit.jsfsession.JSFClientSession;
import org.jboss.jsfunit.jsfsession.JSFServerSession;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class ArquillianHelloWorldTestCase {

	@Deployment
	public static WebArchive createDeployment() {

		// Create a WAR (Micro deployment) with a given name called
		// helloworld.war
		WebArchive webArchive = ShrinkWrap.create(WebArchive.class,
				"helloworld.war");

		// Set web.xml inside created micro WAR
		webArchive.setWebXML(new File("src/main/webapp/WEB-INF/web.xml"));

		// Add classes
		webArchive.addPackage("com.journaldev.jsf.helloworld");

		// Add web resource
		webArchive.addAsWebResource(new File("src/main/webapp","helloWorld.xhtml"));

		// Add faces-config.xml as a web-inf resource
		webArchive.addAsWebInfResource(new File("src/main/webapp/WEB-INF/faces-config.xml"),"faces-config.xml");

		// Add required libraries
		webArchive.addAsLibrary(new File("C:/Users/mohammad.amr/.m2/repository/com/sun/faces/jsf-impl/2.1.13/jsf-impl-2.1.13.jar"));
		webArchive.addAsLibrary(new File("C:/Users/mohammad.amr/.m2/repository/com/sun/faces/jsf-api/2.1.13/jsf-api-2.1.13.jar"));
		webArchive.addAsLibrary(new File("C:/Users/mohammad.amr/.m2/repository/jstl/jstl/1.2/jstl-1.2.jar"));

		// return the deployment
		return webArchive;
	}

	@Test
	@InitialPage("/faces/helloWorld.xhtml")
	public void testInitialPage(JSFServerSession server, JSFClientSession client)
			throws IOException {

		// Test navigation to initial viewID
		Assert.assertEquals("/helloWorld.xhtml", server.getCurrentViewID());

	}

	@Test
	@InitialPage("/faces/helloWorld.xhtml")
	public void testHelloWorldBeanNotNull(JSFServerSession server, JSFClientSession client){

		// Test if Managed Bean is null
		Assert.assertNotNull(server.getFacesContext().getExternalContext().getSessionMap().get("helloWorld"));
	}

	@Test
	@InitialPage("/faces/helloWorld.xhtml")
	public void testS1Value(JSFServerSession server, JSFClientSession client){

		// Test if Managed Bean is null
		Assert.assertEquals("Hello World!!",server.getManagedBeanValue("#{helloWorld.s1}"));
	}
}

pom.xml

pom.xml

<?xml version="1.0"?>
<project
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
	xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>HelloWorldTestCase</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>HelloWorldTestCase</name>
	<url>https://maven.apache.org</url>
	<plugin>
		<artifactId>maven-surefire-plugin</artifactId>
		<version>2.17</version>
	</plugin>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<dependencies>
		<!-- HTML Unit library -->
		<dependency>
			<groupId>net.sourceforge.htmlunit</groupId>
			<artifactId>htmlunit</artifactId>
			<version>2.8</version>
		</dependency>
		<!-- JUnit Library -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<!-- Hamcrest Library -->
		<dependency>
			<groupId>org.hamcrest</groupId>
			<artifactId>hamcrest-core</artifactId>
			<version>1.3</version>
		</dependency>
		<!-- JWebUnit Library -->
		<dependency>
			<groupId>net.sourceforge.jwebunit</groupId>
			<artifactId>jwebunit-htmlunit-plugin</artifactId>
			<version>3.0</version>
		</dependency>
		<!-- Arquillian JUnit container library -->
		<dependency>
			<groupId>org.jboss.arquillian.junit</groupId>
			<artifactId>arquillian-junit-container</artifactId>
			<version>1.1.8.Final</version>
		</dependency>
		<!-- Arquillian Tomcat Container that's used for Arquillian.xml -->
		<dependency>
			<groupId>org.jboss.arquillian.container</groupId>
			<artifactId>arquillian-tomcat-remote-7</artifactId>
			<version>1.0.0.CR7</version>
		</dependency>
		<!-- JSF Implementation And API -->
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>2.1.13</version>
		</dependency>
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<version>2.1.13</version>
		</dependency>
		<!-- Servlet API -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<!-- JSTL API -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<!-- Arquillian JUnit Library -->
		<dependency>
			<groupId>org.jboss.jsfunit</groupId>
			<artifactId>jsfunit-arquillian</artifactId>
			<version>2.0.0.Beta2</version>
		</dependency>
		<!-- Arquillian JUnit Core library -->
		<dependency>
			<groupId>org.jboss.jsfunit</groupId>
			<artifactId>jboss-jsfunit-core</artifactId>
			<version>2.0.0.Beta2</version>
		</dependency>
		<!-- ShrinkWrap Libraries -->
		<dependency>
			<groupId>org.jboss.shrinkwrap</groupId>
			<artifactId>shrinkwrap-api</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.shrinkwrap.resolver</groupId>
			<artifactId>shrinkwrap-resolver-api</artifactId>
			<version>2.2.0-beta-2</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.shrinkwrap.resolver</groupId>
			<artifactId>shrinkwrap-resolver-impl-maven</artifactId>
			<version>2.2.0-beta-2</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.shrinkwrap.descriptors</groupId>
			<artifactId>shrinkwrap-descriptors-api</artifactId>
			<version>1.0.0-beta-1</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.shrinkwrap.descriptors</groupId>
			<artifactId>shrinkwrap-descriptors-impl</artifactId>
			<version>1.0.0-beta-1</version>
		</dependency>
	</dependencies>
</project>

Here’s detailed explanation for code listed above:

这是上面列出的代码的详细说明:

  • You’ve created one Test Class called ArquillianHelloWorldTestCase.java.

    You've created one Test Class called ArquillianHelloWorldTestCase.java .
  • This class contains one mandatory @Deployment method as its Test Cases have required a container (Servlet container).

    This class contains one mandatory @Deployment method as its Test Cases have required a container (Servlet container).
  • @Deployment method have returned a Web Archive.

    @Deployment method have returned a Web Archive.
  • Web Archive returned has contained one Web XML resource, one package, one web resource, one faces-config.xml and three required libraries; JSF implementation and the JSTL. Those resources have been mentioned explicitly so that the Web Archive would contain them accordingly once @Deployment finishes execution.

    Web Archive returned has contained one Web XML resource, one package, one web resource, one faces-config.xml and three required libraries; JSF implementation and the JSTL. Those resources have been mentioned explicitly so that the Web Archive would contain them accordingly once @Deployment finishes execution.
  • If you didn’t bind a name for your Web Archive, so it would be binded randomly with a given name by the ShrinkWrap implementation. Deployment name is helloworld.war.

    If you didn't bind a name for your Web Archive, so it would be binded randomly with a given name by the ShrinkWrap implementation. Deployment name is helloworld.war .
  • @Deployment will communicate with your (Running Tomcat 7) so that the deployment would be installed there as helloworld.war.

    @Deployment will communicate with your (Running Tomcat 7) so that the deployment would be installed there as helloworld.war .
  • Once the deployment is published successfully, your Test Cases execution would be started.

    Once the deployment is published successfully, your Test Cases execution would be started.
  • All Test Cases methods have mentioned two parameters; JSFServerSession and JSFClientSession which are injected automatically by Arquillian framework.

    All Test Cases methods have mentioned two parameters; JSFServerSession and JSFClientSession which are injected automatically by Arquillian framework.
  • All Test Cases methods have assumed the initial page that would be requested and do the Test Case upon it is /faces/helloWorld.xhtml which uses a facelets implementation to render the UI component.

    All Test Cases methods have assumed the initial page that would be requested and do the Test Case upon it is /faces/helloWorld.xhtml which uses a facelets implementation to render the UI component.
  • Passing assertions inside these methods would mark them passed with a green light. Else, the failure and its message would be there.

    Passing assertions inside these methods would mark them passed with a green light. Else, the failure and its message would be there.
  • TestInitialPage would examine if the rendered JSF view has the /helloWorld.xhtml as a view ID.

    TestInitialPage would examine if the rendered JSF view has the /helloWorld.xhtml as a view ID.
  • TestHelloWorldBeanNotNull would examine if the HelloWorld bean is injected by the JSF framework or not.

    TestHelloWorldBeanNotNull would examine if the HelloWorld bean is injected by the JSF framework or not.
  • TestS1Value would examine if the value of attribute s1 is equal to Hello World!! or not.

    TestS1Value would examine if the value of attribute s1 is equal to Hello World!! 或不。

To make sure you have the ability to run above sample you should check on the below:

To make sure you have the ability to run above sample you should check on the below:

  • Your Tomcat 7 is up and Running.

    Your Tomcat 7 is up and Running.
  • Your source paths or resources (src/main/resources) have mentioned an Arquillian container configuration arquillian.xml which will use the JMX to connect your Tomcat.

    Your source paths or resources (src/main/resources) have mentioned an Arquillian container configuration arquillian.xml which will use the JMX to connect your Tomcat.

arquillian.xml

arquillian.xml

<arquillian xmlns="https://jboss.org/schema/arquillian"
    xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        https://jboss.org/schema/arquillian
        https://jboss.org/schema/arquillian/arquillian_1_0.xsd">
    <container qualifier="tomcat-remote-7" default="true">
        <configuration>
            <property name="user">tomcat</property>
            <property name="pass">tomcat</property>
        </configuration>
    </container>
</arquillian>
  • Make sure your Tomcat configuration has allowed JMX connection with your Tomcat. This might be done by adding the below line into your JAVA_OPTS variable within your catalina.bat

    Make sure your Tomcat configuration has allowed JMX connection with your Tomcat. This might be done by adding the below line into your JAVA_OPTS variable within your catalina.bat

New JAVA_OPTS

New JAVA_OPTS

set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Dcom.sun.management.jmxremote.port=8089 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
  • Allow Tomcat user to has manage-script role as it would be used for executing deployment command.

    Allow Tomcat user to has manage-script role as it would be used for executing deployment command.

tomcat-users.xml

tomcat-users.xml

<tomcat-users>
  <role rolename="tomcat"/>
  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <user username="tomcat" password="tomcat" roles="tomcat,manager-gui,manager-script"/>
</tomcat-users>

If you get this sample executed through invoking CTRL + SHIFT + x + t you would see:

If you get this sample executed through invoking CTRL + SHIFT + x + t you would see:

As you can see from the execution of sample above, all cases have been executed and passed successfully while the process of deployment and Test Cases examinations have been done through Arquillian JSF Unit framework.

As you can see from the execution of sample above, all cases have been executed and passed successfully while the process of deployment and Test Cases examinations have been done through Arquillian JSF Unit framework.

Once your Test Cases get executed and the result of execution being shown, the deployment is removed from Tomcat webapps directory.

Once your Test Cases get executed and the result of execution being shown, the deployment is removed from Tomcat webapps directory.

Sometime this removal wasn’t safe, so the exploded folder of your deployment is still there while the WAR is removed. There, you need to stop your Tomcat and remove it by yourself or your make sure using context.xml with antiJARLocking facility.

Sometime this removal wasn't safe, so the exploded folder of your deployment is still there while the WAR is removed. There, you need to stop your Tomcat and remove it by yourself or your make sure using context.xml with antiJARLocking facility.

Maven & JUnit (Maven & JUnit)

As most of developers know, Maven is a build tool that is used for building, compiling, packaging and managing dependencies of your Application. Even it’s a build and dependency tool but it also helps providing a way to execute your Test Cases through a built-in life cycle.

As most of developers know, Maven is a build tool that is used for building, compiling, packaging and managing dependencies of your Application. Even it's a build and dependency tool but it also helps providing a way to execute your Test Cases through a built-in life cycle.

By using mvn test you’re driving your Maven tool to execute your Test Cases that are located beneath your src/test/java.

By using mvn test you're driving your Maven tool to execute your Test Cases that are located beneath your src/test/java .

For this purpose, i have copied all created Test Cases above and achieved some minor modifications that would lead those Test Cases to be run effectively while Maven running. These slight modifications were:

For this purpose, i have copied all created Test Cases above and achieved some minor modifications that would lead those Test Cases to be run effectively while Maven running. These slight modifications were:

  • Add maven-surefire-report-plugin that would be used for reporting all results for your Test Cases execution.

    Add maven-surefire-report-plugin that would be used for reporting all results for your Test Cases execution.
  • Increase timeout period in HelloWorldTestCase.java.

    Increase timeout period in HelloWorldTestCase.java .
  • Modifying testNullPointerExceptionShouldBeRaised inside the same above class to throw it each time this method has called with.

    Modifying testNullPointerExceptionShouldBeRaised inside the same above class to throw it each time this method has called with.
  • Create a new package under src/test/java and copy all Test Classes into it.

    Create a new package under src/test/java and copy all Test Classes into it.

The structure of the application would look like below:

The structure of the application would look like below:

Due to different Test Cases that we have and being  both of Apache 7 & Apache Pluto servers have been used and they should be up and running to get these Test Cases executed properly; i have modified the Tomcat ports from Eclipse itself for Apache 7.

Due to different Test Cases that we have and being both of Apache 7 & Apache Pluto servers have been used and they should be up and running to get these Test Cases executed properly; i have modified the Tomcat ports from Eclipse itself for Apache 7.

Once you’re executing mvn test you should see your Test Cases had written being executed and the result would be shown on both of console and under your Target folder target/surefire-reports.

Once you're executing mvn test you should see your Test Cases had written being executed and the result would be shown on both of console and under your Target folder target/surefire-reports .

Before executing your Test Cases, make sure you have your Apache Pluto and Apache Tomcat 7 up and running so that Arquillian and Portlet Test Cases get executed properly.

Before executing your Test Cases, make sure you have your Apache Pluto and Apache Tomcat 7 up and running so that Arquillian and Portlet Test Cases get executed properly.

The result of execution that you would get it will be:

The result of execution that you would get it will be:

As you may notice, Maven has executed its Test phase and gets all Test Cases that are defined beneath the src/test/javaexecuted successfully.

As you may notice, Maven has executed its Test phase and gets all Test Cases that are defined beneath the src/test/java executed successfully.

This is not the way in which you may know exactly what happens with your Test Case. Beside console messages you have also ability to access the target/surefire-reports folder which will contain set of files that show you execution output that are resulted in by your Test Cases.

This is not the way in which you may know exactly what happens with your Test Case. Beside console messages you have also ability to access the target/surefire-reports folder which will contain set of files that show you execution output that are resulted in by your Test Cases.

Let’s see the result of execution Arquillian Test Case:

Let's see the result of execution Arquillian Test Case:

摘要 (Summary)

JUnit framework is an open source framework that’s used for executing set of Test Cases. While Testing phase takes different forms; Acceptance Test, Integration Test, Functional Test and Unit Test; the most important one of them is Unit Test that would examine your components individually to make sure they’re working properly.

JUnit framework is an open source framework that's used for executing set of Test Cases. While Testing phase takes different forms; Acceptance Test, Integration Test, Functional Test and Unit Test; the most important one of them is Unit Test that would examine your components individually to make sure they're working properly.

Test coverage of functional Test doesn’t exceed 70% according for most QA philosopher, while Unit Test would cover all cases that might not be examined while normal functional Test.

Test coverage of functional Test doesn't exceed 70% according for most QA philosopher, while Unit Test would cover all cases that might not be examined while normal functional Test.

If you combine your Unit Test with Integration, you’re likely about getting full fledged application that’s mostly clean.

If you combine your Unit Test with Integration, you're likely about getting full fledged application that's mostly clean.

According for different forms of technologies and components were provided these days, it’s so important to use reliable tools and APIs to get these components Tested. Presence of JUnit, JWebUnit, JSF Unit and much more would help you achieve this mission.

According for different forms of technologies and components were provided these days, it's so important to use reliable tools and APIs to get these components Tested. Presence of JUnit, JWebUnit, JSF Unit and much more would help you achieve this mission.

This tutorial is aimed to provide you a massive amount of information about most of these frameworks a along side with deep clarification for JUnit 4. Contribute us by commenting below and find below implemented sample for your download.

This tutorial is aimed to provide you a massive amount of information about most of these frameworks a along side with deep clarification for JUnit 4. Contribute us by commenting below and find below implemented sample for your download.

翻译自: https://www.journaldev.com/7354/junit-4-jwebunit-arquillian-jsf-unit-example-tutorial

junit 经典示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值