有很多應用程式,都是在多人的環境之下使用,例如網站應用程式,您可以使用LoadTest來模擬多使用者的情況下,應用程式的行為,例如您撰寫了一個Resource類別:
package onlyfun.caterpillar;
public class Resource { public Resource() { // 建立這個資源很耗時 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } public void doSomething() { try { // I'm doing something... Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }
假設您有個ResourceClient會使用這個Resource:
package onlyfun.caterpillar;
public class ResourceClient { public ResourceClient() { } public synchronized boolean doSomething() { Resource resource = new Resource(); resource.doSomething(); return true; } }
這只是一個簡單的程式,傳回true表示doSomething()正確執行無誤,您也許會為它撰寫一個TestCase:
- ResourceClientTestCase.java
package onlyfun.caterpillar.test;
import onlyfun.caterpillar.ResourceClient; import junit.framework.TestCase;
public class ResourceClientTestCase extends TestCase { private ResourceClient client = new ResourceClient();; public ResourceClientTestCase(String name) { super(name); } public void testResourceClient() { assertTrue(client.doSomething()); } }
在單元測試正確無誤之後,接下來您打算測試多人環境下會有什麼結果,您可以使用LoadTest,例如:
int users = 10;
Test testCase = new ResourceClientTestCase("testResourceClient");
Test loadTest = new LoadTest(testCase, users);
這個程式片段模擬10個使用者同時對ResourceClientTest進行測試,也許您會搭配TimedTest來測試一下是否可以在預期時間下完成任務,例如:
- ResourceClientLoadTest.java
package onlyfun.caterpillar.test;
import com.clarkware.junitperf.LoadTest; import com.clarkware.junitperf.TimedTest;
import junit.framework.Test;
public class ResourceClientLoadTest { public static Test suite() { int users = 10; int maxElapsedTime = 10000; Test testCase = new ResourceClientTestCase("testResourceClient"); Test loadTest = new LoadTest(testCase, users); Test timedTest = new TimedTest(loadTest, maxElapsedTime); return timedTest; } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } }
執行測試的結果是失敗的:
..........TimedTest
(WAITING): LoadTest (NON-ATOMIC): ThreadedTest:
testResourceClient(onlyfun.caterpillar.test.ResourceClientTestCase):
25000 ms
F
Time: 25
There was 1 failure:
1) LoadTest (NON-ATOMIC): ThreadedTest:
testResourceClient(onlyfun.caterpillar.test.ResourceClientTestCase)junit.framework.AssertionFailedError:
Maximum elapsed time exceeded! Expected 10000ms, but was 25000ms.
at com.clarkware.junitperf.TimedTest.runUntilTestCompletion(TimedTest.java:161)
at com.clarkware.junitperf.TimedTest.run(TimedTest.java:138)
at onlyfun.caterpillar.test.ResourceClientLoadTest.main(ResourceClientLoadTest.java:19)
FAILURES!!!
Tests run: 10, Failures: 1, Errors: 0
|
建立Resource是個耗時的工作,觀察Resource的行為,它其實是可以重用的物件,所以您考慮製作一個簡單的Pool:
package onlyfun.caterpillar;
import java.util.*;
public class ResourcePool { private int max; private List resources;
public ResourcePool(int max) { this.max = max; resources = new LinkedList(); } public synchronized Resource getResource() { if(resources.size() == 0) { return new Resource(); } else { int lastIndex = resources.size() - 1; return (Resource) resources.remove(lastIndex); } } public synchronized void putResource(Resource resource) { if(resources.size() != max) { resources.add(resource); } } }
接著修改一下ResourceClient:
package onlyfun.caterpillar;
public class ResourceClient { private ResourcePool pool; public ResourceClient() { pool = new ResourcePool(10); } public synchronized boolean doSomething() { Resource resource = pool.getResource(); resource.doSomething(); pool.putResource(resource); return true; } }
再次運行測試,由於這次可以重用Resource物件,不必每次都耗時建立物件,所以測試通過:
..........TimedTest
(WAITING): LoadTest (NON-ATOMIC): ThreadedTest:
testResourceClient(onlyfun.caterpillar.test.ResourceClientTestCase):
7031 ms
Time: 7.031
OK (10 tests)
|
您還可以搭配Timer實例來模擬使用者的造訪頻率,ConstantTimer可以設定使用者造訪的時間固定間隔,例如:
int users = 10;
Timer timer = new ConstantTimer(1000); // 每個使用者每隔1000毫秒依次造訪
Test testCase = new ResourceClientTestCase("testResourceClient");
Test loadTest = new LoadTest(testCase, users, timer);
RandomTimer則可以模擬使用者隨機間隔時間造訪的情況。
更多有關 JUnitPerf 的資料,可以參考其官方網站之 文件。
|