qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

单元性能测试之使用JUnitPerf测试多线程并发

简介:

  单元测试性能测试在测试领域属于要求相对较高的测试活动,也是测试工程师成长、向上发展的反向。单元测试评测我们的代码实现功能的情况,性能测试则企图分析应用程序的性能表现和负载能力。那么“单元性能测试”能做什么?我们可以这样说,单元性能测试以单元测试的形式对代码进行性能测试。单元性能测试像单元测试一样,需要测试人员编写测试代码,但现在关注的不是代码的功能实现情况了,而是想得到被测试代码的性能数据,包括执行方法耗时、多线程并发是否线程安全、内存是否泄漏、是否存在短期循环对象等。单元性能测试相对于系统性能测试更容易定位问题,对关键的方法进行测试,可以降低系统性能风险,减少系统集成后系统性能测试的工作量。本篇文档演示如何使用JUnitPerf程序包对代码进行多线程并发测试。

  待测代码DateUtil:

  我们待测的程序代码为com.loggingselenium.DateUtil类。这个类中有一个私有静态成员timeFormator和一个静态方法compareDateTime(String dateTime1, String dateTime2)。

package com.loggingselenium;
import java.util.Date;
import java.text.SimpleDateFormat;
public class DateUtil {
 private  static SimpleDateFormat timeFormator =
  new SimpleDateFormat("yyyyMMdd HH:mm:ss");
 public synchronized static int compareDateTime(String dateTime1, String dateTime2) {
  try {
   Date date1 = timeFormator.parse(dateTime1);
   Date date2 = timeFormator.parse(dateTime2);
   if (date1.before(date2))
    return -1;
   if (date1.after(date2))
    return 1;
   else
    return 0;
  } catch (Exception e) {
   throw new RuntimeException("解析日期时间格式出错,期望的字符串格式为[yyyyMMdd HH:mm:ss]");
  }
 }
}

  单元测试代码UnitTestDateUtil:

  我们的测试代码com.loggingselenium.UnitTestDateUtil如下:

package com.loggingselenium;
import junit.framework.TestCase;
public class UnitTestDateUtil extends TestCase {
 protected void setUp() throws Exception {
  super.setUp();
 }
 protected void tearDown() throws Exception {
   super.tearDown();
 }
 public  void testCompareDateTime(){  
  String dateTime1="20120111 01:02:03";
  String dateTime2="20130111 01:02:03";
  String dateTime3="20130111 01:02:03";  
  assertEquals(-1, DateUtil.compareDateTime(dateTime1, dateTime2));
  assertEquals(1,  DateUtil.compareDateTime(dateTime2, dateTime1));
  assertEquals(0,  DateUtil.compareDateTime(dateTime2, dateTime3));
 }
}

  经过运行单元测试代码,可以验证com.loggingselenium.DateUtil类的compareDateTime(String dateTime1, String dateTime2)的功能已经实现了,可以用来比较两个日期时间的大小了。

  对方法进行多线程测试ThreadTestDateUtil

  虽然通过了单元测试,这个方法的功能实现了,但在多线程并发调用该方法的时候会出现抛出异常。手写多线程并发测试代码,com.loggingselenium.ThreadTestDateUtil继承java.lang.Thread线程类,重新实现其run()方法,用于调用com.loggingselenium.DateUtil类的compareDateTime(String dateTime1, String dateTime2)。在main()方法中创建两个线程并启动线程执行调用日期时间比较的方法。

package com.loggingselenium;
public class ThreadTestDateUtil extends Thread {
 public void run() {
  int i1=DateUtil.compareDateTime("20130111 01:02:03","20130111 01:02:03");
  int i2=DateUtil.compareDateTime("20120111 01:02:03","20130111 01:02:03");
  System.out.println("i1="+i1);
  System.out.println("i2="+i2);
 }
 public static void main(String a[]) {  
  Thread t = new ThreadTestDateUtil();
  t.start();
  Thread t2 = new ThreadTestDateUtil();
  t2.start();
 }
}

  编译、运行该方法,控制台报异常:

  java.lang.RuntimeException: 解析日期时间格式出错,期望的字符串格式为[yyyyMMdd HH:mm:ss]

  at DateUtil.compareDateTime(DateUtil.java:43)

  at TestDateUtil2.run(TestDateUtil2.java:3)

  使用JUnitPerf进行多线程测试JUnitPerfTestDateUtil

  我们手写多线程并发测试代码的一个弊端是,如果我们需要测试100个线程,我们就需要创建100个线程实例Thread t,t1,t2,t3……并一一启动这些线程。JunitPerf包可以帮助我们更容易对代码进行多线程并发测试。

  首先,访问http://www.clarkware.com/software/junitperf-1.9.1.zip下载我们需要的junitperf-1.9.1.jar,放到我们单元测试项目的构建路径。

  在测试代码com.loggingselenium. UnitTestDateUtil的基础上进行修改,创建新测试类JUnitPerfTestDateUtil,以使用JunitPerf进行多线程并发测试。新测试类中compareDateTimeLoadTestMethod()实现以5个线程执行testCompareDateTime(),这个单元测试方法调用我们的日期时间比较方法。方法compareDateTimeLoadTestMethod()只会运行1次,会有5个线程运行方法testCompareDateTime(),等于有5个线程调用方法compareDateTime(String dateTime1, String dateTime2)。我们可以指定需要的线程数目,JunitPerf也提供了丰富的接口供我们选用。

package com.loggingselenium;
import com.clarkware.junitperf.LoadTest;
import com.clarkware.junitperf.TestMethodFactory;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class JUnitPerfTestDateUtil extends TestCase {
 public JUnitPerfTestDateUtil(String name) {
  super(name);
 }
 protected void setUp() throws Exception {
  super.setUp();
 }
 protected void tearDown() throws Exception {
  super.tearDown();
 }
 public void CompareDateTime() {
  String dateTime1 = "20120111 01:02:03";
  String dateTime2 = "20130111 01:02:03";
  String dateTime3 = "20130111 01:02:03";
  assertEquals(-1, DateUtil.compareDateTime(dateTime1, dateTime2));
  assertEquals(1, DateUtil.compareDateTime(dateTime2, dateTime1));
  assertEquals(0, DateUtil.compareDateTime(dateTime2, dateTime3));
 }
 protected static Test compareDateTimeLoadTestMethod() {
  int users = 5;
  Test factory = new TestMethodFactory(JUnitPerfTestDateUtil.class,
    "CompareDateTime");
  Test loadTest = new LoadTest(factory, users);
  return loadTest;
 }
 public static Test suite() {
  TestSuite suite = new TestSuite();
  suite.addTest(compareDateTimeLoadTestMethod());
  return suite;
 }
 public static void main(String args[]) {
  junit.textui.TestRunner.run(suite());
 }
}


  编译、运行该测试方法,使用Run as Application,控制台可能输出如下结果,有2个Error:

  …..EE

  Time: 0.053

  There were 2 errors:

  1) CompareDateTime(com.loggingselenium.JUnitPerfTestDateUtil)java.lang.RuntimeException: 解析日期时间格式出错,期望的字符串格式为[yyyyMMdd HH:mm:ss]

  at com.loggingselenium.DateUtil.compareDateTime(DateUtil.java:18)
  at com.loggingselenium.JUnitPerfTestDateUtil.CompareDateTime(JUnitPerfTestDateUtil.java:22)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at com.clarkware.junitperf.TestFactory.run(TestFactory.java:83)
  at com.clarkware.junitperf.ThreadedTest$TestRunner.run(ThreadedTest.java:75)
  at java.lang.Thread.run(Unknown Source)

  2) CompareDateTime(com.loggingselenium.JUnitPerfTestDateUtil)java.lang.RuntimeException: 解析日期时间格式出错,期望的字符串格式为[yyyyMMdd HH:mm:ss]

  at com.loggingselenium.DateUtil.compareDateTime(DateUtil.java:18)
  at com.loggingselenium.JUnitPerfTestDateUtil.CompareDateTime(JUnitPerfTestDateUtil.java:22)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at com.clarkware.junitperf.TestFactory.run(TestFactory.java:83)
  at com.clarkware.junitperf.ThreadedTest$TestRunner.run(ThreadedTest.java:75)
  at java.lang.Thread.run(Unknown Source)

  FAILURES!!!

  Tests run: 5, Failures: 0, Errors: 2

  多线程并发测试失败,我们的比较日期时间大小的方法存在线程不安全的问题,我们需要在DateUtil中方法前加上线程同步关键字synchronized:

public synchronized static int compareDateTime(String dateTime1, String dateTime2) {......}

  再次运行单元测试方法,可以发现多线程并发下存在的问题得到了解决。

版权声明:本文出自 lobster 的51Testing软件测试博客:http://www.51testing.com/?194329

原创作品,转载时请务必以超链接形式标明本文原始出处、作者信息和本声明,否则将追究法律责任。

posted on 2013-01-14 11:55 顺其自然EVO 阅读(428) 评论(0)  编辑  收藏 所属分类: 测试学习专栏


只有注册用户登录后才能发表评论。


网站导航:
 
<2013年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜