001: /*
002: * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
003: * Copyright (C) 2007 - Javolution (http://javolution.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009: package javolution.testing;
010:
011: import j2me.lang.CharSequence;
012:
013: /**
014: * <p> This class represents a test case which can be used for validation,
015: * performance and regression tests.</p>
016: *
017: * <p> The structure of a test case is as follow:[code]
018: * class MyTestCase extends TestCase {
019: *
020: * // Prepares data/state in which to run the test.
021: * public void prepare() { ... } // Optional
022: *
023: * // Executes the test (it may exercise the test case several times).
024: * public void execute() { ... } // Mandatory.
025: *
026: * // Returns the number of times the test case has been exercised (default 1).
027: * public int count() { ... } // Optional
028: *
029: * // Validates the results.
030: * public void validate() { ... } // Optional.
031: *
032: * // Cleanups after execution (e.g. release resources).
033: * public void cleanup() { ... } // Optional
034:
035: * }[/code]
036: * It should be noted that some testing contexts (e.g. {@link TimeContext})
037: * may run the sequence (prepare, execute, validate, cleanup) multiple
038: * times to calculate for example the average execution time (
039: * {@link #validate validation} in that case is performed only once
040: * after the last run). Here is an example of test case
041: * implementation for the <code>HashMap.put(key, value)</code> method:[code]
042: * class HashMap_put extends TestCase {
043: * private HashMap _map;
044: * private int _size;
045: *
046: * public HashMap_put(int n) {
047: * _size = 0;
048: * Index.setMinimumRange(0, n); // Preallocates.
049: * }
050: *
051: * public void prepare() {
052: * _map = new HashMap();
053: * }
054: *
055: * public void execute() {
056: * for (int i=0; i < _size;) {
057: * _map.put(Index.valueOf(i), Index.valueOf(i++));
058: * }
059: * }
060: *
061: * public int count() { // Number of put operations performed.
062: * return _size;
063: * }
064: *
065: * public void validate() {
066: * TestContext.assertTrue("Wrong size", _size == _map.size());
067: * for (int i=0; i < _size;) {
068: * if (!TestContext.assertEquals(_map.get(Index.valueOf(i)), Index.valueOf(i++)))
069: * break; // Error, no need to continue.
070: * }
071: *
072: * // Asserts performance.
073: * long avgTime = TimeContext.getAverageTime("ns");
074: * TestContext.assertTrue(avgTime + "ns too slow!", avgTime < 100);
075: * }
076: *
077: * public CharSequence getDescription() {
078: * return "java.util.HashMap.put(key, value) - " + n + " entries added";
079: * }
080: * };[/code]
081: * Test cases are typically grouped into a {@link TestSuite}:[code]
082: * public HashMapTests extends TestSuite {
083: * public void run() {
084: * TestContext.info("Test put(key, value) for various size");
085: * TestContext.test(new HashMap_put(10));
086: * TestContext.test(new HashMap_put(100));
087: * TestContext.test(new HashMap_put(1000));
088: * ...
089: * }
090: * }
091: * TimeContext.enter(); // To measure execution time.
092: * try {
093: * new HashMapTests().run();
094: * } finally {
095: * TimeContext.exit();
096: * }[/code] </p>
097: *
098: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
099: * @version 5.2, August 5, 2007
100: * @see TestContext
101: */
102: public abstract class TestCase {
103:
104: /**
105: * Default constructor.
106: */
107: protected TestCase() {
108: }
109:
110: /**
111: * Prepares the test case execution (the default implementation does
112: * nothing).
113: */
114: public void prepare() {
115: // Does nothing.
116: }
117:
118: /**
119: * Executes this test case (possibly multiple times in which case
120: * the {@link #count()} method should be overriden).
121: */
122: public abstract void execute();
123:
124: /**
125: * The number of times the test case is exercised (default <code>1</code>).
126: *
127: * @return the number of test case occurences in {@link #execute}.
128: */
129: public int count() {
130: return 1;
131: }
132:
133: /**
134: * Validates the test results (the default implementation does
135: * nothing).
136: */
137: public void validate() {
138: // Does nothing.
139: }
140:
141: /**
142: * Cleanup once test is complete (the default implementation does
143: * nothing).
144: */
145: public void cleanup() {
146: // Does nothing.
147: }
148:
149: /**
150: * Returns the description of this test case or <code>null</code> if none.
151: *
152: * @return the description or <code>null</code>
153: */
154: public CharSequence getDescription() {
155: return null;
156: }
157:
158: /**
159: * Returns the <code>String</code> representation of this test case
160: * (the description or the class name by default).
161: *
162: * @return the string representation of this test case.
163: */
164: public String toString() {
165: CharSequence description = getDescription();
166: return description == null ? this.getClass().getName()
167: : description.toString();
168: }
169: }
|