Add link to posts because IFTTT really hates feeds without links.
[SquirrelJME.git] / test-writing.mkd
blobb90a23eaa2525ac196cf3b94a9d987b4d40482b0
1 # Test Writing
3 As _SquirrelJME_ is its own virtual machine implementation it uses its own
4 testing system that is different from _JUnit_ or _TestNG_ however it is simple
5 and suits the needs of the project. The main intention of the test framework
6 is to allow for the testing on various virtual machines, since _JUnit_ while
7 it supports _Java SE_ it does not support _Java ME_. So as such there will be
8 some differences as to how tests are written along with their expectations.
10 # Placement of Tests
12 Like standard Java tests, the tests are placed within the standard directory
13 tree as like other _Gradle_ projects:
15  * `module/src/test/java` -- Source code for tests.
16    * `./TestCuteness.java` -- Test source.
17  * `module/src/test/resources` -- Expectations for _SquirrelJME_.
18    * `./TestCuteness.in` -- Test expectations for `TestCuteness`.
20 # Base Test Classes
22 All tests within _SquirrelJME_ extend from one of the base classes that
23 exist depending on what is needed for a test, all of these `abstract` classes
24 are declared in `net.multiphasicapps.tac`:
26  * `TestBiConsumer` -- Takes two arguments, provides no result.
27  * `TestBiFunction` -- Takes two arguments, provides a result.
28  * `TestBoolean` -- Takes no arguments, provides a `boolean`.
29  * `TestConsumer` -- Takes one argument, provides no result.
30  * `TestFunction` -- Takes one argument, provides a result.
31  * `TestInteger` -- Takes an `int` argument.
32  * `TestLong` -- Takes a `long` argument.
33  * `TestRunnable` -- Takes no arguments, provides no result.
34  * `TestSupplier` -- Takes no arguments, provides a result.
36 # Results And Expectations
38 One of the major differences is that _SquirrelJME_'s test expectations are
39 written in an expectations file rather than as something that exists in
40 source code. The manifest itself is in the following format, the keys and
41 values are specified later on in the document. Since there are virtual machine
42 tests and the test framework uses the project's own implementation of the API
43 there can be potential cases where a test may falsely pass because of some
44 event or condition within the project that is erroneous. As such, since the
45 results are elsewhere and static they are for the most part compared via
46 string representation apart from some special conditions.
48 The manifest file is named the same as the test itself and is placed within
49 the same package from within `resources`. The resources are accessed in the
50 same manner as `Class.getResourceAsStream(classBaseName)` and as such
51 is in the specific format:
53 ```manifest
54 result: NoResult
55 thrown: NoExceptionThrown
56 secondary-int--value: int:1234
57 ```
59 The `result` is formed as part of the return value of a method, if there is
60 one. `thrown` is any exception that is thrown from the test method. Any
61 secondary value is set by using `this.secondary(key, value)` from a test, the
62 result is stored for later checking. Secondary keys may be any value however
63 they are dash encoded for special characters.
65 ## Printing Resultant Manifest
67 In the event a manifest needs to quickly be created there is a property
68 which will print that manifest, this is generally used for getting the
69 baseline results via Java SE. This should _never_ be used outside of
70 that, as running a test and placing in its own values normally is a very
71 bad idea.
73 The following system property can be set:
75  * `net.multiphasicapps.tac.resultManifest=true`
77 ## Expectation Specifiers
79 The following expectation specifiers are used for various values. Arrays are
80 specified by `[length]` and the values within are split by `,`. Primitive
81 type arrays may have the type followed by `*`, such as `byte*[length]`, if
82 they indicate that the array is of a boxed type, such as `Byte[length]` rather
83 than `byte[length]` in Java.
85 Special specifiers for `result` and `thrown` are these:
87 * `NoResult`
88     * Used only for `result`, specifies the return type is `void`.
89 * `ExceptionThrown`
90     * Used in `result` when an exception is thrown.
91 * `NoExceptionThrown`
92     * No exceptions are thrown from the method.
94 The general value specifiers are:
96  * `true`
97    * True boolean value, which is `Boolean.TRUE`.
98  * `false`
99    * False boolean value, which is `Boolean.FALSE`.
100  * `boolean[<length>]:<arrayValues,>`
101    * Boolean array values, each is encoded as `T` for `true` and `f` for
102      false, and as such `[true, true, false]` encodes as `TTf`.
103  * `string:<encodedString>`
104    * Represents a single string.
105  * `string[<length>]:<asString:,>`
106    * An array of strings, which are encoded accordingly.
107  * `char:<printableNonDigitGlyph|integer>`
108    * A single character.
109    * For printable non-digit ASCII characters this will be the glyph.
110    * Otherwise, it will be an integer of the character code.
111  * `char[<length>]:<asChar:,>`
112    * An array of characters values.
113  * `byte:<integer>`
114    * An integral `byte` value, follows the rules of `Byte.valueOf(String)`.
115  * `byte[<length>]:<asByte:,>`
116    * An array of `byte` values.
117  * `short:<integer>`
118    * An integral `short` value, follows the rules of `Short.valueOf(String)`.
119  * `short[<length>]:<asShort:,>`
120    * An array of `short` values.
121  * `int:<integer>`
122    * An integral `int` value, follows the rules of `Integer.valueOf(String)`.
123  * `int[<length>]:<asInt:,>`
124    * An array of `int` values.
125  * `long:<integer>`
126    * An integral `long` value, follows the rules of `Long.valueOf(String)`.
127  * `long[<length>]:<asLong:,>`
128    * An array of `long` values.
129  * `long-fudge:<asLong>:<absoluteDifference>`
130    * Similar to `long:` except that the value may be within
131      `<absoluteDifference>` using the formula:
132      `expected - diff <= actual <= expected + diff`
133  * `long-ignore-sign:<asLong>`
134    * Similar to `long:` except that the sign bit is ignored.
135  * `throwable:<throwableType>`
136    * An exception that is thrown.
137    * Exceptions in `java.lang` are just the base class name such as
138      `throwable:IllegalArgumentException`.
139    * Otherwise, they are the fully qualified class name such as
140      `throwable:fully.Qualified`.
141  * `other:<encodedString>`
142    * Unknown value type, uses `Object.toString()`.
144 ## String Encoding
146 For any `<encodedString>`, the characters are encoded as the following:
148  * `null` is encoded as `\NULL`.
149  * Double quote (`"`) is encoded as `\"`.
150  * Single quote (`'`) is encoded as `\'`.
151  * Space (` `) is encoded as `\_`.
152  * Newline (`\n`) is encoded as `\n`.
153  * Carriage return (`\r`) is encoded as `\r`.
154  * Tab (`\t`) is encoded as `\t`.
155  * Opening curly brace (`{`) is encoded as `\(`.
156  * Closing curly brace (`}`) is encoded as `\)`.
157  * Delete or `0x7F` is encoded as `\d`.
158  * `0x00` through `0x1F` are encoded as `\0` to `\9` then `A` through `\V`.
159  * Characters at or above 0x7F are encoded as `\@xxxx` with the character
160    hex digit representation.
161  * Otherwise, the ASCII glyph of the character.
163 ## Secondary Key Encoding
165 The following characters map to the specified secondary key encoding:
167  * `-` = `--`
168  * `!` = `-x`
169  * `"` = `-q`
170  * `#` = `-h`
171  * `$` = `-m`
172  * `%` = `-c`
173  * `&` = `-e`
174  * `*` = `-s`
175  * `+` = `-p`
176  * `.` = `-d`
177  * `/` = `-l`
178  * `:` = `-o`
179  * `?` = `-u`
180  * `@` = `-a`
181  * `^` = `-r`
182  * `|` = `-i`
183  * `~` = `-t`
185 # Example
187 An example test with the test expectations:
189 ```java
190 // -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
191 // ---------------------------------------------------------------------------
192 // SquirrelJME
193 //     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
194 // ---------------------------------------------------------------------------
195 // SquirrelJME is under the Mozilla Public License Version 2.0.
196 // See license.mkd for licensing and copyright information.
197 // ---------------------------------------------------------------------------
199 package lang;
201 import net.multiphasicapps.tac.TestRunnable;
204  * Tests string trim.
206  * @since 2018/12/05
207  */
208 public class TestStringTrim
209         extends TestRunnable
211         /**
212          * {@inheritDoc}
213          * @since 2018/12/05
214          */
215         @Override
216         public void test()
217         {
218                 String cute = "squirrels are cute";
219                 
220                 this.secondary("a", cute.trim());
221                 this.secondary("b", "  \t      squirrels are cute".trim());
222                 this.secondary("c", "squirrels are cute    \t".trim());
223                 this.secondary("d", "       \tsquirrels are cute \t    ".trim());
224                 this.secondary("e", "           ".trim());
225                 this.secondary("f", "           ".trim());
226                 this.secondary("g", cute.trim());
227         }
231 ```manifest
232 result: NoResult
233 thrown: NoExceptionThrown
234 secondary-a: string:squirrels\_are\_cute
235 secondary-b: string:squirrels\_are\_cute
236 secondary-c: string:squirrels\_are\_cute
237 secondary-d: string:squirrels\_are\_cute
238 secondary-e: string:
239 secondary-f: string:
240 secondary-g: string:squirrels\_are\_cute