TestNG annotation

一个suite(套件) 由一个或多个测试组成。 一个test(测试) 由一个或多个类组成 一个class(类) 由一个或多个方法组成。
@BeforeSuite/@AfterSuite 在某个测试套件开始以前/在某个套件全部测试方法执行以后
@BeforeTest/@AfterTest 在某个测试开始以前/在某个测试全部测试方法执行以后
@BeforeClass/@AfterClass 在某个测试类开始以前/在某个类的全部测试方法执行以后
@BeforeMethod/@AfterMethod 在某个测试方法以前/在某个测试方法执行以后
@BeforeGroup/@AfterGroup 在某个组的全部测试方法以前/在某个组的全部测试方法执行以后
测试的一个目标就是确保代码按照预期的方式工做。这种测试要么在用户层面上进行,要么在编程层面上进行。这两种类型的测试分别是经过功能测试和单元测试来实现的。
 
针对失败而测试
Java提供了两种不一样类型的异常:从java.lang.RuntimeException派生的运行时刻异常和从java.lang.Exception派生的被检查的异常。
抛出被检查的异常的经验法则:调用者能够为这个异常作什么吗?若是答案是确定的,那么可能应该是用被检查的异常,不然,最好是选择运行时刻异常。
属性expectedExceptions是一组类,包含了这个测试方法中预期会抛出的异常列表。若是没有抛出异常,或抛出的异常再也不该属性的类表中,那么TestNG就会认为这个测试方法失败了。
单一职责:
testng-failed.xml
当您执行包涵失败的测试套件时,TestNG会在输出目录(默认是test-output/)下自动生成一个名为testng-failded.xml的问他件。这个XML文件包含了原来的testng.xml中失败的方法所构成的子集。
TestNG让您能够选择本身将测试类实例化。这是经过@Factory annotation来实现的,他必须放在返回一个对象数组方法的顶部。全部这些对象都必须是包含TestNG annotation的类的实例。若是有@Factory annotation,那么这个循环会继续下去,知道TestNG拿到的都是没有@Factory annotation实例,或者@Factory方法都已被调用过的实例。
能够安全的在同一个类包含@Factory和@Test annotation,由于TestNG确保@Factory方法只被调用一次。
org.testng.ITest接口
当TestNG遇到实现了这个接口的测试类时,他会在生成各类报告中包含getTestName()方法返回的信息。
数据驱动测试
测试须要针对许多具备相似结构的数据来执行。 实际的测试逻辑是同样的,仅仅发生改变的是数据。 数据能够被一组不一样的人修改。
参数测试方法 测试逻辑能够很是简单或不易改变,而提供給他的数据确定会随着时间增加。
TestNG能够经过两种方式向测试方法传递参数:
一、利用testng.xml传递参数
在测试方法中指定参数
若是犯下如下错误之一,TestNG将抛出一个异常:
2.利用@DataProvider传递参数
若是须要向测试方法传递的参数不是基本的Java类型,或者若是须要的值智能在运行时刻建立,那么咱们应该考虑使用@DataProvider annotation。
数据提供者是用@Dataprovider标注的方法。这个annotation只有一个字符串属性:他的名称,若是没有提供名称,数据提供者的名称就默认采用方法的名称。
数据提供者同时实现两个目的:
向测试方法传递任意数目的参数 根据须要,容许利用不一样的参数集合对他的测试方法进行屡次调用。
因为数据提供者是测试类中的一个方法,他能够属于一个超类,而后被一些测试方法复用。咱们也能够有几个数据提供者,只要他们定义在测试类或者他的一个子类上。当咱们像在合适的地方记录数据源,并在几个测试方法中复用他时,这种方法是很方边的。
针对数据提供者的参数 数据提供者自己能够接受两个类型的参数:Method和ITestContext
Method参数 若是数据提供者的第一个参数是java.lang.reflect.Method,TestNG传递这个将调用的测试方法。若是您但愿数据提供者根据不一样的测试方法返回不一样的数据,那么这种作法就很是有用。
使用同一个数据提供者的地方:
数据提供者代码至关复杂,应该保存在一个地方,这样维护起来更方便。 咱们要传入数据的那些测试方法具备许多参数,其中只有少数参数是不同的。 咱们引入了某个方法的特殊状况。
ITestContext参数 若是一个数据提供者在方法签名中声名了一个ITestContext类型的参数,TestNG就会将当前的测试上下文设置给它,这使得数据提供者可以知道当前测试执行的运行时刻参数。
ITestContext对象中的数据是运行时刻的信息,不是静态的信息:这个测试方法即属于unit-test组,也属于functional-test组,但在运行时刻,咱们决定只执行functional-test组,这个值由ITestContext#getIncludeGroups方法返回。
延迟数据提供者
为了实现这种方法,TestNG容许咱们从数据提供者返回一个Iterator,而不是一个二维对象数组。
这种方法与数组不一样之处在于,当TestNG须要从数据提供者取得下一组参数时,他会调用Iterator的next方法,这样就有机会在最后一刻实例化相应的对象,即恰好在须要这些参数的测试方法被调用以前。
若是传递的参数是简单类型的常数,利用testng.xml的方法是很好的。档咱们须要更多灵活性,并知道参数的数目和值将随时间增长时,咱们可能应该选择@DataProvider。
提供数据 数据的位置多是:硬编码在Java源码中、再文本文件中、在属性文件中、在Excel表格中、在数据库中、在网络中…。
数据提供者仍是工厂 数据提供者向测试方法传递参数,而工厂像构造方法传递参数。
不如不能肯定使用哪一种方法,那么就看看测试方法所使用的参数。是否有几个测试方法须要接收一样的参数?若是是这样,您可能最好是将这些参数保存在一个字段中,而后在几个方法中复用这个字段,这就意味着最好是选择工厂。反之,若是全部的测试方法都须要传入不一样的参数,那么数据提供者多是最好的选择。
异步测试 异步代码一般出如今下列领域:
测试异步代码比测试同步代码的问题更多:
当调用异步时有三种可能的结果:
测试异步代码也一样遵循下面的模式:
发出异步调用,他会当即返回。若是可能,制定一个回调对象。
若是有回调方法:
等待结果,在接到结果是设置布尔变量,反应结果是不是您的预期。
在测试方法中,监视那个布尔变量,等到他被设置或过了一段时间。
若是没有回调方法:
在测试方法中,按期检查预期的值。若是过了一段时间尚未检查到预期值,就失败并退出。
不指定回调方法
在这个测试中,消息是做为测试初始化的一部分,利用@BeforeClass发出的,这保证了这段代码在测试方法调用以前执行而且只执行一次。在初始化后TestNG将调用waitForAswer测试方法,他将进行不彻底忙等。
有回调方法:
如今sendMessage()是一个@Test方法,他将包含在最终的报告中,若是发送消息失败,TestNG将跳过waitForAnswer测试方法,并把他表示为SKIP。
TestNG调用该方法100次,若是98%的调用成功,就认为整体测试经过。
测试多线程代码 并发测试
@invocationCount至关简单,在不考虑并发时也可使用:他决定了TestNG调用一个测试方法的次数。
@threadPoolSize要求TestNG分配必定数量的线程,并使用这些线程来调用这个测试方法,当一个测试完成以后,执行他的线程将归还给线程池,而后能够用于下一次调用。
并发执行
thread-count属性指定了线程数目,TestNG将使用这些线程来执行这个测试套件中的全部测试方法,parallel属性告诉TestNG您在执行这些测试时但愿采用的并行模式。
arallel=”methods” 在这种模式下,每一个测试方法将在他本身的一个线程中执行。
arallel=”test” 在这种模式下,在某个标签内的全部测试方法将在他们本身的一个线程中执行。
在tests模式中,TestNG保证每一个将在他本身的线程中执行。若是但愿测试不安全的代码,这一点是很是重要的。在method模式中,全部限制都被取消,没法预测哪些方法将在同一个线程中执行,哪些方法将在不一样的测试中执行。
为可模拟性设计 为了可以成功地使用模拟模拟对象或桩,重要得失要确保代码的设计能让使用模拟对象或桩变得简单而直接。 这种设计最重要的方面就是正确的肯定组件之间的交互,从而肯定组件的交互接口。
若是咱们有2个组件A和B,A须要用到B,那么应该经过B的接口来完成,而不是经过B的具体实现。
Singleton查找
对于某个对象智能由一个实例,这在项目生命周期的后期产生阻碍效果。
JNDI定位服务
不可以向A提供一个受控制的B的实例。只有一个全局实例,A只能取得这个实例。
依赖注入
从外部通知A应该使用哪一个B的实例。这让咱们可以根据实际状况灵活地决定向A提供B的哪一个实例。
EasyMock
1建立模拟对象 这是经过createMock方法完成的,传入但愿模拟的类做为参数。
2纪录预期行为 只要在模拟对象上调用咱们预期会被调用的方法,就能纪录预期的行为。当用到某些具体的参数时,只要将这些参数传入就能够了。
3调用主要被测对象 在主要的被测对象上调用一个方法或一组方法,预期此次调用将倒置被测对象调用模拟对象的那些预期的方法。
4验证预期行为 最后调用verify,检查全部的模拟对象。
JMock jMock是一个模拟库,她让咱们经过编成的方式来之行约束条件。
选择正确的策略
缺乏接口 有时候,咱们面对的是庞大臃肿的遗留系统,没有向指望的那样有很好的设计。 大多数模拟库如今都容许替换类,而不只是接口。这些库会在运行时刻生成一个新类,经过字节码操做来实现指定的契约。
复杂的类 若是咱们获得了一些类,他们拥有20多个方法,与许多其余组件交互,并且随着是间的推移变得愈来愈复杂。 这种状况下,使用动态的模拟对象库效果会比较好,由于他们可以定义单个方法的行为,而不是考虑全部的方法。
契约纪录 使用模拟对象让咱们记录更多的契约信息,而不止是方法签名。咱们能够随时验证器乐的。
测试目标 根据经验法则,若是但愿测试组件之间交互,模拟对象可能优于桩对象。模拟库可以以一种准确的方式来指定交互。而桩该做为被测试组件使用的那些次要的组件。在这种状况下,测试的目标是测试被测试组件自己,而不是他与其余组件之间的交互。
模拟易犯的错误 依赖模拟对象会导至许多问题,因此重要的是要知道使用模拟对象不利的一面:
依赖的测试 层叠失败:一个测试的失败致使一组测试的失败。
依赖的代码只要测时方法依赖于其余测试方法,就很难以隔离的方式执行这些测试方法。 彼此依赖的测试方法一般会出现这样的状况,由于他们共享了一些状态,而在测试之间共享状态是很差的。
利用TestNG进行依赖的测试 TestNG经过@Test annotation的两个属性(dependsOnGroups和dependsOnMethods)赖支持依赖的测试。
dependsOnMethods的问题: 经过字符串来执行方法名称,若是未来对他进行重构,代码就有可能失效。方法名称违反了”不要重复本身”的原则,方法名称即在Java方法中用到,也在字符串中使用,另外,等咱们不断添加新的测试方法时,这个测试用例伸缩性也很差。
利用组来指定依赖关系能够解决咱们遇到的全部问题:
依赖的测试和线程 当打算并行执行测试时,要记住,线程池中的一个或多个线程将用于依次执行每一个方法。因此,若是打算在不一样的线程中执行一些测试,过渡的使用依赖的测试将影像执行性能。
配置方法的失败 依赖测试方法和配置方法之间惟一的不一样就是,测试方法隐式的依赖于配置方法。
虽然dependsOnMethods能够处理简单的测试或之由一个测试方法依赖于另外一个测试方法的状况,可是在大多数状况下,您都应该使用dependsOnGroups,这种方式的伸缩性好,面对未来的重构也更为健壮。
既然咱们提供了准去的依赖信息,那么TestNG就可以按照于骑的顺序来执行测试。
测试隔离并无所以而受到影响。
若是出现层叠式的错误,依赖测试能够加快测试执行速读。
继承和annotation范围
他违反了”不要重复本身”的原则 他为未来添加测试方法的开发者带来了负担。
annotation继承
全部扩展自BaseWebTest的类都会看到,他们全部的工有方法都自动成为web.credit-card组的成员。 WebTest变成了一个普通的传统Java对象(POJO),不带任何annotation。
集成易犯的错误 因为TestNG的测试方法必须是公有的,在基类中声明的方法会自动在子类中可见,因此他们永远也不须要做为测试类显式的列出(不要将测试基类列在testng.xml文件中)
测试分组分组解决了上面提到的局限性,实际上,他们进一步提高了TesgNG的一个设计目标:在静态模型(测试代码)和动态模型(执行哪些测试)之间实现清晰的分离。
语法@Test annotation和配置annotation(@BeforeClass, @AfterClass, @BeforeMethod…)均可以属于分组
test1属于group2组,test2同时属于group2组和group3组
分组与运行时刻
这个testng.xml告诉TestNG执行com.example.A类中全部属于group1组的测试方法。
若是某个方法即属于包含的组,又属于排除的组,那么排除的组优先。 若是既没有include,也没有exclude,那么TestNG将忽略组,执行全部的测试方法。
另外一个功能就是能够在testng.xml中利用正则表达式来指定组。
在设计组的层次关系时,可以在testng.xml中定义新组带来灵活性: 能够在代码中使用粒度很是小的分组,而后在运行时刻将这些小分组合并成大分组。
执行分组 利用命令行执行
利用ant
利用Mave
利用Java API
排除失败的测试 建立一个特书的组如broke
而后在运行时刻排除这个组。
组分类
测试类型:单元测试、继承测试 测试规模:小规模、大规模 功能描述:数据库、界面 测试速度:慢测试、快测试 过程描述:冒烟测试、发布测试
让开发者可以指定方法的分组,主要的好处在于开发者所以可以很容易找出他们须要执行哪些测试。(如刚刚修改了数据库代码,可能只须要执行fast和database组测试)
组命名
TestNG可以利用正则表达式来之定要执行的组,若是与这项功能配合使用,这种命名方式就颇有用了。
代码覆盖率 类的覆盖率:类覆盖描熟了项目中多少类已被测试套件访问。  方法覆盖率:方法覆盖率是被访问的方法的百分比。 语句覆盖率:语句覆盖率追踪单条源代码语句的调用。 语句块覆盖率:语句快覆盖率将语句块做为基本的覆盖律单元。 分支覆盖率:分支覆盖率也被称为判断覆盖率。指标计算哪些代码分支被执行。
覆盖律工具 Clover、EMMA和Cobertura
成功使用覆盖率的建议 覆盖率报告的信息何音的解读不一样 覆盖率很难 百分比没有意义 为覆盖率而设计是错误得 有一点好过没有 覆盖律工具不会测试不存在的代码 覆盖率的历史讲述了本身的故事
企业级测试 单元测试:单元测试对系统中的一个单元进行独立的测试。
功能测试:功能测试关注一项功能。一般涉及不一样组件之间的交互。
继承测试:继承测试是一种端到端的测试,他会执行整个应用栈,包括全部的外部依赖关系或系统。
一个具体的例子 系统中有一个至关典型的组件,他接收一条JMS消息,其中包含一段有效的XML文本。这段XML文本至关长,描述了一笔财务交易。这个组件的工做是读出这条消息,解析XML,根据消息的内容条填充一些数据库的表,而后调用一个存储过程来处理这些表。
测试内容
咱们将建立一个成功测试。但愿确保,若是收到一条有效的XML消息,咱们会正确地处理他,并更新正确的数据表,而后存储过程的调用也成功。 咱们将摹拟不一样的场景。但愿可以为测试替工不一样的XML文本,这样就可以很容易地不断添加测试粒子数据。 咱们提供明确的失败测试。失败的行为将被记录和测试,这样当组件内部出现失败时,他的状态就能够与测,而且很容易记录下来。
非测试内容
咱们不测试JMS provider的功能。假定他是一个彻底兼容的实现,已经正确的进行了配置,将成功地提交咱们指望的消息。咱们不执行捕捉全部错误得测试。失败测试应该针对明确的、可重现的失败场景。咱们不测试API。例如,JDBC去冬的行为不是测试的主题。确保全部的测试都贯注业务功能,要避免对Java语言的语义进行测试。
测试成功场景 对于JMS API的接口 利用模拟对象(或桩)对象,建立TextMessage实现,用一个简单的POJO来表现,带有消息内容和其余属性的设置方法。重构该组件,解除业务功能与JMS API的耦合。
构件测试数据
咱们的测试如今接受一个参数,再也不须要本身考虑测试数据的来源,也不须要考虑如何加载测试数据。他要作的只是指定数据提供者。加载XML的实际工做如今代理给了一段独立的加载程序。
固然,能够从数据提供者返回一个Object[]的数组,可是,这种方法意味着咱们必需将全部的文件的数据都一次性加载到内存中,由于数组必须事先填充。
测试准备问题
幂等的测试是指,这个测试执行一次和执行屡次的结果是同样的。若是某个东西是幂等的,那么说明他在屡次调用时状态不会改变。
不只须要测试是幂等的,并且测试的次序应该可有可无。因此除了须要是是幂等的以外,测试不该该在状态或数据方面影像其余测试。
对于一些写操做,成功执行以后很容易会对再次执行产生影响,下面方法有助于咱们对付这个问题:
嵌入式数据
在测试准备时初始化数据
事务回滚
选择正确的策略
错误处理
这种方法在于,他们没能让咱们区分失败是不是预期的。相反,咱们应该可以区分预期的成功和预期的失败。这个测时目前在两种状况下会经过:要么遇到好的数据时会经过,要么遇到坏数据时会经过。在每种状况下,咱们都不能肯定会发生些什么。
一个测试不该该在两种或两种以上的状况下都经过。若是测试验证了不一样的失败状况,这没问题,但若是测试在好数据和坏数据的状况下都经过,那就会致使一些微妙的错误,这类错误难以被发现。(所以咱们定义了另外一个目录和数据提供者来处理失败的状况)
逐渐出现的单元测试 单元测试不必定是在其它测试以前编写的,他们能够是功能测试驱动的。特别是对于大型项目或原有的代码来讲,一开始就编写有用的单元测试可能很困难,由于在不了解全局的状况下,单元测试可能太琐碎或不过重要。相反,单元测试能够从有意义的继承测试中推导出来,由于调试开发功能测试和集成测试的过程揭示他们所需的单元测试。
对于例子来讲咱们须要将XML验证与数据库处理放到各自独立的方法中。这样就能对他们进行测试
这测重构的结果是咱们获得了一个简单的单元测试。
不论测试编写的次序如何,功能测试和单元测试都是互不的。功能测试是更为水平化的测试,涉及许多不一样的组件,执行代码的不少部分。相反,单元测试是更为垂直化的测试,他关注范围狭窄的主题,比功能测试要完全得多。
竞争消费者模式 消费者的执行是并发的,因此咱们必须在测试中进行某种程度的模拟,生产环境中的真实状况。在咱们这样做了以后,也但愿验证结果。不论哪一个消费者先开始,也不论哪一个消费者先结束,都没有关系。咱们但愿肯定对于给定数量的消费者,咱们将得道一组已知的结果,能够进行验证。
咱们的测试被分红两个,一个负责执行消费者,另外一个负责验证结果。缘由是runConcurrentProcessors会被调用屡次,而咱们只须要在全部方法调用完成以后,对结果验证一次。为了表示这种次序,咱们利用了dependsOnMethods这个annotation属性。
当TestNG发现一个数据提供者时,他将针对数据提供者返回的每一条数据调用一次测试。相似的,当咱们指定调用次数时,TestNG会按照指定的次数调用测试。所以,若是咱们返回数据提供者中准备好的3条数据,那么每一个线程都会执行3次测试。
所以解决方案是使用一个栈结构,每次调用数据提供者时,返回一条数据,并将这条数据从列表中清除。数据提供者将被调用3次,每次都将为数据返回不同的数据。
原则:将数据的考虑和功能的考虑分开来是很关键的。 在这个例子中,消费者须要的数据应该和实际的测试没有依赖关系。这种方法意味着,随着咱们对数据的需求不断变化,变得更为复杂,测试自己却不须要被修改。
一个具体的例子 咱们但愿测试一个登陆servlet。这个servlet接受一个请求,检查用户名和口令,若是他们有效,就在会话中加入一个标记。代表用户已登陆。
这个例子展现了重构在测试方面起到的重要辅助做用,说明了即便对于看上去很麻烦、须要一很复杂地方是进行交互的API,页能够经过抽象去掉依赖关系。这种抽象意味着 在测试过程当中,咱们能够利用更简单的对象,这些对象更容易构造,所以也更容易测试。
增长可测试性的一个反作用就是改进了设计。为提升可测试性而进行重构,能够帮助咱们以一种实际的、代码中的方式来肯定职责和考虑,而这种效果经过画设计图是很难达到的。
Java EE测试 容器内测试与容器外测试的对比
容器内测试 优势:
缺点:
容器外测试 优势:
缺点:
容器内测试 测试步骤:
建立一个测试环境的实例。 肯定测试。 在测试框架中注册测试。 注册一个监听者来接收搜测试结果。
建立测试环境
肯定测试 假定全部的测试类都在WEB-INF/classes目录下,咱们能够递归地读入这个目录,找到其中全部的类文件。
context是一个ServletContext实例,他是经过调用servlet或JSP页面获得的。
注册测试 注册测试类的动做告诉了TestNG他要查看的一组类,TestNG将在这组类中查找须要执行哪些测试。他将检查每一个指定的类,肯定他是否包涵测试方法或配置方法。当全部类都检查事后,TestNG内部会生成一个依赖关系图,以决定照到的这些测试的执行次序。
注册结果监听者
TestNG自代了3个默认的报告类:
SuiteHTMLRepoter 默认报告类,他在一个目录下输出交叉引用HTML文件,让您能看到某个具体测试的结果。
FailedReporter: 这个报高生成一个TestNG执行配置,该配置包含了全部前一次运行时失败的测试。他也是默认运行的。
EmailableReporter: 这个报告类生成一个报告文件,能够很容易地经过电子邮件发送,显示测试的结果。
默认状况下,EmailableReporter在磁盘上生成一个文件。
调用TestNG的JSP页面
Java命名和目录接(JNDI) JNDI是一个在全局目录中查找资源的API。能够把他当作是一个很大的树型结构,咱们在其中按照名称查找某个节点。
上面建立一个InitialContext对象,若是在执行容器内执行,会利用供应商提供的API实现,来查找容器内部命名目录结构。建立了上下文以后,咱们在其中查找对象,列出他的内容,或遍历这棵树。全部这些都是经过JNDI API来完成的。InitialContext的构造方法由一个重载的版本,接受一个Hashtable对象做为参数,其中包含不一样的环境变量值,决定了上下文应该如何建立。
避免JNDI 组件依赖关系要么经过服务定位(一般是JNDI)来实现,要么经过注入来实现。若是您能够选择,就采用注入的方式,由于这样测试的开销最小,而且这种方式带来了更大的灵活性。
Java消息服务(JMS)
在测试中使用ActiveMQ
处理状态 在JMS的例子中,当咱们拥有多个测试时,会引起一个有趣的问题。由于测试是由一对方法组成的,因此让咱们假定同一个类中还有另外一对发送/接收测试。
一种方法是将发送和接受者放在一个测试中,并在每一个测试方法以前初始化消息代理。请注意两点都要作到,由于让消息代里在一对测试方法以前初始化是比较麻烦的。
另外一种方法是使用消息分捡器。JMS消息分捡器让咱们可以过滤接收到的消息,这样能够只接收与分捡器匹配的消息。
Spring Spring的测试包功能
TestNG经过本身的一组针对Spring的类来解决这些问题,这些类做为扩展提供。org.testng.spring.test包中包含了全部Spring在其测试包中提供的类,这些类已修改过,能够用在基于TestNG的测试中。
AbstractSpringContextTests 这是全部Spring测试的基类。他的主要职责是提供上下文的管理。这个类包含一个静态map,其中包含全部注册的Spring上下文。
AbstractSingleSpringContextTests 这个类扩展了AbstractSpringContextTests,提供了装入一个ApplicationContext对象的钩子。他的子类应该实现getConfigLocation(String[] paths)方法。这个方法返回一个字符串数组,指出了Spring配置文件的位置,一般是从classpath加载的。
Spring的配置方法被声明在名为Spring-init的TestNG分组中。咱们没必要依赖于单个的onSetUp或ontearDown方法,能够根据须要声明任意多个@BeforeMethod/@AfterMethod配置方法,只要指定他们依赖于spring-init,就能够确保他们在Spring执行完准备工做以后获得调用。
AbstractDependencyInjectionSpringContextTests 这个类提供的最有趣的功能就是向测试注入依赖。测试依赖关系能够表现为设值方法或成员字断。测试也能够指定Spring应该对他们的树性执行哪一种类型的自动编织。
这个类有一个事务管理器属性。由于他派生自支持注入的类,配置文件中必需指定一个PlatforTransactionManager,以便注入。
咱们没有在测试中指定任何事务行为,超类自动处理了事务方面的问题,让每一个测试在他本身的事务中执行,这个十五将在该测试完成以后回滚。
增长的调用setComplete通知超类在测试执行以后应该提交这个事务,而不是回滚。调用这个方法由一个有趣的反作用:这个类中全部后续测试都会提交事务,而不是依赖于默认行为。
答案在于JUnit和TestNG之间的一个微妙区别。Spring测试假定采用了JUnit的语义。每一个测试类对每一个测试方法都会从新实例化。所以,全部的测试都假定每一个测试开始时,测试时里的状态都会复原,但TestNG不是这样的。
AbstractTransactionalDataSouceSpringContextTests 这个类添加了一些JDBC相关的便利方法。
AbstractAnnotationAwareTransactionalTests 这个类支持超类提供的全部功能以外,这个类容许咱们在测试方法上指定Spring特有的事务annotation,而不是经过编程的方式来指定事务行为。
Guice 第2章中的例子,对于每一个接口,咱们都有两个实现。一个是实际的产品实现,他会与一些外部的依赖关系进行交互,如UserDAO对象会与数据库交互,Mailer对象会与SMTP邮件服务器交互。咱们还有桩对象实现。
Guice注入测试
Spring注入测试
对象工厂
杂谈 关注和提供异常 一层遇到了一个没有预料到的错误,不知道如何处理。因此这一层就快乐地向上一层抛出一个异常,但愿这个可怜的异常最终会遇到知道怎么做的人。
吞掉抛出异常
这种方法问题在于,实际上咱们丢试了真实错误的有意义的信息。当咱们最后有机会处理这个异常的时候,咱们获得的信息仅仅是某一层中出了问题,但咱们不知道是在这一曾自己出了问题,仍是更低的层出了问题。
记日志并抛出
问题在于调用栈常常发生的状况:信息隐藏。假定一个应用程序有三层或四层,每一层都在日志中记录他处里的异常,查遍8页的调用栈信息并非最有效地方式。
嵌套抛出
当这个调用栈显示的时候,没有丝毫暗示代表背后的缘由是什么。您必须编写一个帮助方法,从外面的包装中取出背后实际的异常。
咱们建议两种解决方案
避免需检察异常。运行时异常很合适这样的状况。 包装异常。假如您很是确定在调用栈打印时,背后的缘由会显示出来,那么包装的异常也很好。
有状态测试 有两种大相径庭的状态分类:不可修改的状态和可修改的状态
不可修改的状态 访问共享的不可修改的状态的测试方法,相互之间是独立的。 由于这些方法都不能修改他们读到的状态,因此调用顺序能够是任意的,所以他们没有违反测试访法应该彼此肚里的原则。
可修改的状态
JUnit会让这个测试经过,但TestNG不会。 只有当您知道测试方法被调用的顺序时,共享可修改的状态才有意义。
安全的共享数 安全 不可修改的状态
安全   可修改的状态与彻底指定的依赖关系
不安全  可修改的状态与不肯定的依赖关系
测试驱动开发的缺点 他注重微观设计超过宏观测试
他在实践中难以应用
TDD注重微观设计超过宏观设计
测试驱动开发能够获得更健壮的软件,但他也可能致使没必要要的反复和过分重构的趋势,这可能对饮的软件、设计和最后期限产生负面影响。
TDD难以应用
这种方式获得的代码自己并不会优先于传统方法测试的代码。
如何建立测试并不重要,重要的是确实要建立测试
测试私有方法 若是他有可能出问题,您就应该测试他。
测试私有方法的比较好的方法是提高方法的可见性,例如,让他变成保护可见,或者包可见。后者更好一些,由于您能够把测试和被测类放在同一个包中,而后您就能够访问他的全部字段。若是这些方法都不可取,咱们测试私有方法的方式就是利用反射。
咱们利用字符串来描述Java元素。若是您对这些元素进行重命名,这种危险的实践确定会失效。
咱们利用了该类危险的私有信息。咱们不只假定存在一些私有方法和属性,并且也假定这个方法将以某种方式修改一个字段。
测试与封装 若是让代码更可测试,不要担忧破坏封装。可测试星应该赛过封装。
让一个私有方法(或字段)成为包可见的、保护可见的或公有的。
去掉方法的final限定符。这让测试勒可以扩展这些类,或重写这些方法,模拟或稍微改变他们的实现,从而让系统的其它部分更可测试。
记日志的最佳实践 在出错时,输出错误或警告是合理的。可是对於警告的状况,重要的是肯定这是否是该作的事情。咱们添加的每一条无用的日志信息都会干扰有用的信息,所已精心选择是有意义的。
对于调试需求,记日志是有用的。可是,只要有一个开关能打开或关闭,绝大多数的记日志需求都可以知足了,不须要复杂的解决方案。
相关文章
相关标签/搜索