risei 1.3.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -368
- package/Read-me reduced.md +294 -0
- package/Read-me redux.md +581 -0
- package/index.js +5 -5
- package/package.json +14 -12
- package/system/ASpoofingFixture.js +7 -8
- package/system/ATestCaller.js +3 -3
- package/system/ATestFinder.js +2 -2
- package/system/ATestReporter.js +2 -1
- package/system/ATestSource.js +5 -1
- package/system/ChosenTestFinder.js +4 -4
- package/system/ClassTestGroup.js +2 -2
- package/system/LocalCaller.js +5 -5
- package/system/{ClassMethodSpoofer.js → MethodSpoofer.js} +54 -48
- package/system/MethodTestGroup.js +2 -2
- package/system/Moment.js +1 -1
- package/system/NameAnalyzer.js +26 -0
- package/system/PropertySpoofer.js +156 -0
- package/system/Risei.js +5 -5
- package/system/SpoofDef.js +260 -0
- package/system/TerminalReporter.js +8 -8
- package/system/{TestDefinition.js → TestDef.js} +153 -107
- package/system/TestFinder.js +3 -3
- package/system/TestFrame.js +15 -52
- package/system/TestGroup.js +1 -1
- package/system/TestResult.js +2 -2
- package/system/TestRunner.js +23 -107
- package/system/TestStages.js +79 -120
- package/system/TestSummary.js +1 -1
- package/system/TotalComparer.js +60 -11
- package/system/TotalDisplayer.js +34 -21
- package/system/TypeAnalyzer.js +41 -79
- package/system/TypeIdentifier.js +18 -8
- package/system/Types.js +3 -1
- package/test-target-objects/ConditionalThrowTarget.js +11 -0
- package/test-target-objects/Counter.js +46 -0
- package/test-target-objects/DomTarget.js +37 -0
- package/test-target-objects/InterSpoofer.js +230 -0
- package/test-target-objects/MixedContents.js +33 -0
- package/test-target-objects/MutationTarget.js +37 -0
- package/test-target-objects/ObjectComposer.js +34 -0
- package/test-target-objects/PolySpoofableInner.js +29 -0
- package/test-target-objects/PolySpoofableOuter.js +52 -0
- package/test-target-objects/PropertiesTarget.js +98 -0
- package/test-target-objects/Returner.js +7 -0
- package/test-target-objects/Searcher.js +25 -0
- package/test-target-objects/Sorter.js +91 -0
- package/test-target-objects/Spoofable.js +36 -0
- package/test-target-objects/StateTarget.js +34 -0
- package/test-target-objects/StaticTarget.js +17 -0
- package/test-target-objects/TestableTarget.js +57 -0
- package/trial-tests/SelfTests.outward-rt.js +511 -0
- package/trial-tests/TopicTests.outward-rt.js +313 -0
- package/usage-examples/Gold-bar-example.png +0 -0
- package/usage-examples/Title-example.png +0 -0
- package/xternal-tests/ASpoofingFixture.tests.js +242 -0
- package/xternal-tests/MethodSpoofer.tests.js +130 -0
- package/xternal-tests/SpoofDef.tests.js +91 -0
- package/xternal-tests/TotalComparer.tests.js +1055 -0
- package/xternal-tests/package.json +7 -0
- package/system/AComparer.js +0 -9
- package/system/ATestFixture.js +0 -44
- package/system/ClassPropertySpoofer.js +0 -182
- package/system/ObjectMethodSpoofer.js +0 -58
- package/system/ObjectPropertySpoofer.js +0 -136
- package/system/SpoofDefinition.js +0 -243
- package/system/TestFrameChooser.js +0 -54
- package/system/TestFrames.js +0 -232
- package/system/TotalCopier.js +0 -106
package/README.md
CHANGED
|
@@ -4,18 +4,16 @@
|
|
|
4
4
|
## What Risei is
|
|
5
5
|
|
|
6
6
|
**Risei is a new way to write unit tests that allows you to:**
|
|
7
|
-
* Whip up full test coverage
|
|
8
|
-
* Refactor or replace existing designs without worrying about
|
|
9
|
-
* Create tests with immediate confidence,
|
|
10
|
-
|
|
11
|
-
Risei may be referred to as **Rs** here for brevity.
|
|
7
|
+
* Whip up full test coverage in no time for object-oriented (or object-hosted) JavaScript and TypeScript.
|
|
8
|
+
* Refactor or replace existing designs without worrying about about a heavy cost in past or future test construction.
|
|
9
|
+
* Create tests with immediate confidence, since you can't introduce mistakes when writing test code.
|
|
12
10
|
|
|
13
11
|
|
|
14
12
|
|
|
15
13
|
|
|
16
14
|
## The Risei approach
|
|
17
15
|
|
|
18
|
-
Risei replaces coded tests with simple declarative syntax
|
|
16
|
+
Risei replaces coded tests with simple declarative syntax.
|
|
19
17
|
|
|
20
18
|
Here are two example tests. `SortModel.countSort()` is being tested using the inputs from `.in` and the expected output from `.out`:
|
|
21
19
|
|
|
@@ -27,12 +25,16 @@ Here is the terminal output of these two example tests. Tests are grouped
|
|
|
27
25
|

|
|
28
26
|
|
|
29
27
|
|
|
30
|
-
- An individual test may appear on one line or multiple lines, depending on how wide the terminal window is.
|
|
31
28
|
- Any failing tests appear in light red.
|
|
32
|
-
- Your latest
|
|
29
|
+
- Your latest tests always sort to the bottom so it's easy to find their results.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
Test runs also feature a title bar at the top:
|
|
33
|
+
|
|
34
|
+

|
|
33
35
|
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
As well as a summary bar at the bottom:
|
|
36
38
|
|
|
37
39
|

|
|
38
40
|
|
|
@@ -41,9 +43,30 @@ Test runs also feature a title bar at the top, as well as a summary bar at the b
|
|
|
41
43
|
|
|
42
44
|
## Using Risei
|
|
43
45
|
|
|
44
|
-
Risei is under active development.
|
|
46
|
+
Risei is under active development. The newest release, **2.0.0**, brings many major improvements:
|
|
47
|
+
|
|
48
|
+
- You can now test properties just like methods.
|
|
49
|
+
- You can now spoof properties on the targeted class instance.
|
|
50
|
+
- Risei now can determine automatically if tested or spoofed methods and properties are static.
|
|
51
|
+
- You can now perform arbitrary operations if needed.
|
|
52
|
+
- You can now change a test property without accidentally creating a new test.
|
|
53
|
+
- `Error` objects are now compared accurately.
|
|
54
|
+
- Outputs for `throw` tests are now the entire `Error` objects (breaking change).
|
|
55
|
+
|
|
56
|
+
Risei has been reengineered internally along with these improvements.
|
|
57
|
+
|
|
58
|
+
- In addition, `ATestSource` is now a default export (breaking change).
|
|
59
|
+
- This means a simple adjustment from `import { ATestSource }` to `import ATestSource`.
|
|
60
|
+
|
|
61
|
+
These changes and others are detailed at the new external Risei documentation website:
|
|
62
|
+
|
|
63
|
+
&cruft, new site
|
|
64
|
+
[https://deusware.com/risei-docs/index.html](https://deusware.com/risei-docs/index.html)
|
|
65
|
+
|
|
66
|
+
If you've been here before, check out [what's new in Risei](#whats-new-in-risei) for the latest. Also see [known issues and workarounds](#known-issues-and-workarounds) and [limitations in Risei](#limitations-in-risei).
|
|
67
|
+
|
|
68
|
+
Risei works with Typescript, requiring only a few additional or different steps, described in [using Typescript with Risei](#using-typescript-with-risei).
|
|
45
69
|
|
|
46
|
-
There are a few additional or different steps for [using Typescript with Risei](#using-typescript-with-risei).
|
|
47
70
|
|
|
48
71
|
|
|
49
72
|
|
|
@@ -55,7 +78,7 @@ Install Risei for development time only:
|
|
|
55
78
|
npm install --save-dev risei
|
|
56
79
|
```
|
|
57
80
|
|
|
58
|
-
Make sure your `package.json` specifies that
|
|
81
|
+
Make sure your `package.json` specifies that ECMAScript modules are in use:
|
|
59
82
|
|
|
60
83
|
```json
|
|
61
84
|
"type": "module"
|
|
@@ -69,99 +92,20 @@ And add Risei's metadata to `package.json`:
|
|
|
69
92
|
}
|
|
70
93
|
```
|
|
71
94
|
|
|
72
|
-
Just a [few extra steps](#using-typescript-with-risei) are required for Risei to work with TypeScript.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
### Siting tests
|
|
77
|
-
|
|
78
|
-
Add tests in files ending in `.rt.js` like this:
|
|
79
|
-
|
|
80
|
-
```javascript
|
|
81
|
-
import { ATestSource } from "risei/ATestSource";
|
|
82
|
-
import { ClassToBeTested } from "somewhere";
|
|
83
|
-
|
|
84
|
-
export class SomeTests extends ATestSource {
|
|
85
|
-
tests = [ ... ]; // This array is where test definitions are written.
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
### Writing tests
|
|
92
|
-
|
|
93
|
-
Write tests with Risei's easy syntax:
|
|
94
|
-
|
|
95
|
-
```javascript
|
|
96
|
-
tests = [ ...
|
|
97
|
-
{ on: ContainerModelClass, with: [ "a", "b", "c" ], // Target class and constructor args.
|
|
98
|
-
of: "doesContain", // Target method.
|
|
99
|
-
for: "When the input arg is present, returns true.", // Description of test.
|
|
100
|
-
in: [ "c" ], // Inputs.
|
|
101
|
-
out: true }, // Expected output.
|
|
102
|
-
...];
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
#### Write more tests with less syntax:
|
|
108
|
-
|
|
109
|
-
You can save a lot of time by putting repeated test properties into an object once, just before the related tests:
|
|
110
|
-
|
|
111
|
-
```javascript
|
|
112
|
-
/* All of the following tests are of ContainerModelClass. */
|
|
113
|
-
{ on: ContainerModelClass, with: [ "a", "b", "c", "a", "b" ] },
|
|
114
|
-
|
|
115
|
-
/* Two tests for ContainerModelClass .doesContain(). */
|
|
116
|
-
{ of: "doesContain" },
|
|
117
|
-
{ for: "When the input arg is present, returns true.",
|
|
118
|
-
in: [ "c" ], out: true },
|
|
119
|
-
{ for: "When the input arg is not present, returns false.",
|
|
120
|
-
in: [ "d" ], out: false },
|
|
121
|
-
|
|
122
|
-
/* First test for ContainerModelClass .countOf(). */
|
|
123
|
-
{ of: "countOf", for: "Returns the number present.", in: [ "b" ], out: 2 }
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
- This _collapsing forward_ is reset when you change the class in `.on`, when you give the property a new value, or you erase it with an empty array `[]`.
|
|
95
|
+
> Just a [few extra steps](#using-typescript-with-risei) are required for Risei to work with TypeScript.
|
|
127
96
|
|
|
128
|
-
|
|
97
|
+
&cruft, new site / section
|
|
98
|
+
- Further general options can be found [here](https://deusware.com/risei-docs/index.html#installation).
|
|
129
99
|
|
|
100
|
+
&cruft, new site / section
|
|
101
|
+
- Further Typescript details can be found [here](https://deusware.com/risei-docs/index.html#using-typescript).
|
|
130
102
|
|
|
131
103
|
|
|
132
|
-
#### Spoof away code dependencies:
|
|
133
|
-
|
|
134
|
-
When your tests need certain results from code dependencies, just _spoof_ what you want using a `.plus` test property:
|
|
135
|
-
|
|
136
|
-
```javascript
|
|
137
|
-
{ on: CombinerClass, with: [],
|
|
138
|
-
of: "combineResults",
|
|
139
|
-
plus: [
|
|
140
|
-
{ on: ClassA, of: "someMethod", as: 10 }, // Spoof this ClassA method to return 10.
|
|
141
|
-
{ on: ClassB, of: "someMethod" }, // Spoof this ClassB method not to return (or do) anything.
|
|
142
|
-
{ of: "firstMethod", as: [ 7, 8, 9, 10 ] }, // Spoof a method on the tested class (CombinerClass).
|
|
143
|
-
{ of: "secondMethod" }, // Spoof a method on CombinerClass not to do anything.
|
|
144
|
-
{ on: ClassC, // Spoof this ClassC method to be this nonce code.
|
|
145
|
-
of: "someMethod",
|
|
146
|
-
as: (arg) => { return { color: arg }; } },
|
|
147
|
-
{ on: ClassD, as: [ // Spoof two methods on ClassD at the same time.
|
|
148
|
-
{ of: "firstMethod", as: 11 },
|
|
149
|
-
{ of: "secondMethod", as: 12 }
|
|
150
|
-
] },
|
|
151
|
-
],
|
|
152
|
-
for: "When called, returns an array of values from sources.",
|
|
153
|
-
in: [ "green" ], out: [ 7, 8, 9, 10, 10, 11, 12, { color: "green" } ] }
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
- It's just like _fakes_, _mocks_, or _test doubles_ in other test systems, but much easier to write and read.
|
|
157
|
-
|
|
158
|
-
- Spoofed code is fully isolated within tests, even though spoof definitions collapse forward across tests (and within `.plus`).
|
|
159
|
-
|
|
160
104
|
|
|
161
105
|
|
|
162
106
|
### Running tests
|
|
163
107
|
|
|
164
|
-
|
|
108
|
+
Once you've written your tests, run them by invoking Risei's `index.js` file:
|
|
165
109
|
|
|
166
110
|
```bash
|
|
167
111
|
node ./node_modules/risei/index.js
|
|
@@ -181,298 +125,132 @@ And then run that script:
|
|
|
181
125
|
npm test
|
|
182
126
|
```
|
|
183
127
|
|
|
184
|
-
Risei can be used alongside other test frameworks, and even run with them from the same test script if you want.
|
|
185
|
-
|
|
186
|
-
|
|
128
|
+
- Risei can be used alongside other test frameworks, and even run with them from the same test script if you want.
|
|
187
129
|
|
|
188
|
-
|
|
130
|
+
&cruft, new site / section
|
|
131
|
+
- Find more information about this mixed testing and other config / run options [here](https://deusware.com/risei-docs/index.html#running-tests).
|
|
189
132
|
|
|
190
|
-
Read through the rest of this doc to learn more about Risei's many capabilities, and about where Risei is headed.
|
|
191
|
-
|
|
192
|
-
- For instance, learn about using `.and` to test static methods or throws.
|
|
193
|
-
- Or learn about using `.from` to test property results or other state.
|
|
194
|
-
- Don't miss out: Once you've tried the basics, read the rest...!
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
## Risei in depth
|
|
200
|
-
|
|
201
|
-
<details>
|
|
202
|
-
<summary>
|
|
203
|
-
There's plenty more to learn about Risei and how it makes testing easy...
|
|
204
|
-
</summary>
|
|
205
|
-
|
|
206
|
-
### Installation
|
|
207
|
-
|
|
208
|
-
- You can use any file extension you want in Risei's metadata in `package.json`, and Risei will scan those files for tests.
|
|
209
|
-
|
|
210
|
-
- You can install Risei outside of development time the usual way, but as with any test system, this is definitely not recommended.
|
|
211
|
-
|
|
212
|
-
- Risei uses ESM syntax, and may not work in older environments where that's not available or is patched in.
|
|
213
133
|
|
|
214
134
|
|
|
215
135
|
|
|
216
136
|
### Siting tests
|
|
217
137
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
- Test classes must inherit from `ATestSource` in `"risei/ATestSource"`: this type name is looked for specifically, so duck-typing doesn't work.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
### Writing tests
|
|
225
|
-
|
|
226
|
-
- The order and placement of test properties doesn't matter, although the order seen in the examples is probably most readable.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
#### Basic test properties and options for each:
|
|
231
|
-
|
|
232
|
-
| Name | Contents |
|
|
233
|
-
|--------|-----------------------------------------------------------------------------------------------------------|
|
|
234
|
-
| `on` | The class under test, as a symbol / name (already imported into the test file) |
|
|
235
|
-
| `with` | An array of any arguments to pass to the constructor of the tested class, or an empty array `[]` if none |
|
|
236
|
-
| `of` | The name of the method under test, as a string, no `()` needed |
|
|
237
|
-
| `for` | A description of what the test proves, for test output |
|
|
238
|
-
| `in` | An array of the input arguments to pass to the tested method, or an empty array `[]` if none |
|
|
239
|
-
| `out` | The expected return value, not in an array |
|
|
240
|
-
|
|
241
|
-
- There are additional properties for extended functionality, covered later.
|
|
242
|
-
- The property names were chosen to be easy to remember and type, but longer alternatives are available, covered later.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
### Test-property reuse _AKA_ Collapsing forward
|
|
247
|
-
|
|
248
|
-
- To save time and effort, any property you write is collapsed forward to subsequent tests unless you replace it or erase it with an empty array `[]`.
|
|
249
|
-
- Property values are gathered across partial test objects until they add up to a runnable test, which is then run.
|
|
250
|
-
- Changes to properties are combined with previous ones to produce intended new tests.
|
|
251
|
-
- For a rare and avoidable side-effect of this system, see [known issues and workarounds](#known-issues-and-workarounds).
|
|
252
|
-
|
|
253
|
-
- Test contents, reused or not, are automatically reset when it makes the most sense:
|
|
254
|
-
- Changing the tested class in `.on` wipes out all prior test properties, so the new class has a fresh start.
|
|
255
|
-
- Changing the tested method in `.of` wipes out only test properties related to methods, to preserve class values you usually want.
|
|
256
|
-
|
|
257
|
-
- Individual tests remain isolated, except for when args are mutated by the code under test.
|
|
258
|
-
- Restate args for each test when the code mutates them.
|
|
259
|
-
- This limitation is the result of limits on what can be copied reliably in JavaScript.
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
### Choosing test-only dependency inputs _AKA_ Spoofing
|
|
263
|
-
|
|
264
|
-
- Spoofing is Risei's way of providing test-only inputs from dependencies the tested code uses, written in simple declarative syntax.
|
|
265
|
-
- It's therefore the equivalent of test doubles, mocks, fakes, and so on.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
- As the earlier examples and this table show, you can spoof in many ways, both on the dependencies, and on the class being tested.
|
|
269
|
-
- All classes whose members are being spoofed have to be imported.
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
#### Spoof-definition properties:
|
|
274
|
-
|
|
275
|
-
| Name | Necessary or Optional | Contents |
|
|
276
|
-
|------|-----------------------|----------------------------------------------------------------------------|
|
|
277
|
-
| `on` | Optional | Symbol for a type (class); if omitted, the targeted model class is assumed |
|
|
278
|
-
| `of` | Necessary | Name of the method to spoof, as a string, trailing `()` not needed |
|
|
279
|
-
| `as` | Optional | Value to return or nonce implementation; if omitted, an empty method with no return value is used<br> — or —<br>A list of partial spoof definitions for the same class |
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
- You can spoof multiple methods of a class individually, or list them together with partial definitions as seen in the example, with the same effect either way.
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
#### Partial spoof-definition properties:
|
|
286
|
-
|
|
287
|
-
| Name | Necessary or Optional | Contents |
|
|
288
|
-
|------|-----------------------|---------------------------------------------------------------------------------------------------|
|
|
289
|
-
| `of` | Necessary | Name of the method to spoof, as a string, trailing `()` not needed |
|
|
290
|
-
| `as` | Optional | Value to return or nonce implementation; if omitted, an empty method with no return value is used |
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
- Defining new spoofing wipes out all old definitions.
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
- Spoofing is done at the start of each test and undone at the end of each test, keeping all tests isolated.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
## Advanced Risei usage
|
|
302
|
-
|
|
303
|
-
### Testing special test conditions with `.and`
|
|
304
|
-
|
|
305
|
-
You can use the special test property `.and`, always a string, to indicate special conditions that apply to your test.
|
|
306
|
-
- At present, the values available are `"static"` and `"throw"` / `"throws"` (either one works).
|
|
307
|
-
- You can list `static` and `throw` / `throws` together if needed, separated by a space.
|
|
308
|
-
|
|
309
|
-
The `.and` property is an expansion point for supporting more special conditions in the future. Values will always be listable together (as long as any particular grouping makes sense).
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
#### Testing static methods
|
|
314
|
-
|
|
315
|
-
To test a static method, use an `.and` of `"static"`:
|
|
138
|
+
Add tests in files ending in `.rt.js` like this:
|
|
316
139
|
|
|
317
140
|
```javascript
|
|
318
|
-
|
|
141
|
+
import ATestSource from "risei/ATestSource";
|
|
142
|
+
import { ClassToBeTested } from "somewhere";
|
|
319
143
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
and: "static",
|
|
323
|
-
in: [ "This is a short sentence." ],
|
|
324
|
-
out: { isFullSentence: true, characters: 25, words: 5 }
|
|
144
|
+
export class SomeTests extends ATestSource {
|
|
145
|
+
tests = [ ... ]; // Test definitions are added here.
|
|
325
146
|
}
|
|
326
147
|
```
|
|
327
148
|
|
|
328
149
|
|
|
329
150
|
|
|
330
|
-
|
|
151
|
+
### Writing tests
|
|
331
152
|
|
|
332
|
-
|
|
153
|
+
Write tests with Risei's simple syntax:
|
|
333
154
|
|
|
334
155
|
```javascript
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
156
|
+
tests = [ ...
|
|
157
|
+
{ on: ContainerModelClass, with: [ "a", "b", "c" ], // Target class and constructor args.
|
|
158
|
+
of: "doesContain", // Target method name.
|
|
159
|
+
for: "When the arg is present, returns true.", // Description of test.
|
|
160
|
+
in: [ "c" ], // Inputs to method.
|
|
161
|
+
out: true }, // Expected output.
|
|
162
|
+
...];
|
|
343
163
|
```
|
|
344
164
|
|
|
165
|
+
- To test a throw path in a method, add an `.and` test property with the text value `"throws"`.
|
|
345
166
|
|
|
167
|
+
- To test a property of the target instance after running code, add a `.from` property with the property's name as a string.
|
|
346
168
|
|
|
347
|
-
|
|
169
|
+
- To test a value derived from the initial actual value, or otherwise from any available context, add a `from` property that's an arrow function taking (at present) `target` and `test` parameters: `(target, test) => { return test.actual.someProperty; }`.
|
|
348
170
|
|
|
349
|
-
To
|
|
171
|
+
- To perform operations like creating files temporarily, use the `.do` property (encompassing two stages, `.before` and `.after`) to set up isolated test state, and `.undo` to restore normal state.
|
|
172
|
+
- The `.do`-`.before` steps are taken before the target class instance is created, the `.do`-`.after steps are taken after that but before the target method / property is run.
|
|
173
|
+
- The `.undo` is an arrow function taking a `test` arg. It is run after all other steps of the test have been run. **(2.0.0)**
|
|
350
174
|
|
|
351
|
-
|
|
352
|
-
|--------------------------------|-------------------------------------------------------------------------|
|
|
353
|
-
| Property name as string | Retrieves the actual from the named property on the test's target class |
|
|
354
|
-
| Specialized function | Retrieves the actual from either its `target` or `test` parameter |
|
|
175
|
+
- To maintain the benefits of using Risei's declarative style, avoid arbitrary options as much as possible.
|
|
355
176
|
|
|
177
|
+
- If you prefer test property names that aren't JavaScript keywords, alternatives are available for all of them.
|
|
356
178
|
|
|
357
|
-
-
|
|
358
|
-
- Retrieving definitions collapse forward across tests unless replaced with new definitions, or erased by setting `.from` to an empty array `[]`.
|
|
179
|
+
- Further details about syntax options can be found [here](https://deusware.com/risei-docs/index.html#test-syntax).
|
|
359
180
|
|
|
360
181
|
|
|
361
|
-
<details>
|
|
362
|
-
<summary>
|
|
363
|
-
More information
|
|
364
|
-
</summary>
|
|
365
|
-
<br>
|
|
366
182
|
|
|
367
|
-
|
|
183
|
+
|
|
184
|
+
#### Write more tests with less syntax:
|
|
185
|
+
|
|
186
|
+
To save a lot of time, state repeated test values just once, and let them _collapse forward_ into following tests:
|
|
368
187
|
|
|
369
188
|
```javascript
|
|
370
|
-
|
|
189
|
+
/* All of the following tests are of ContainerModelClass. */
|
|
190
|
+
{ on: ContainerModelClass, with: [ "a", "b", "c", "a", "b" ] },
|
|
371
191
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
192
|
+
/* Two tests for ContainerModelClass .doesContain(). */
|
|
193
|
+
{ of: "doesContain" },
|
|
194
|
+
{ for: "When the input arg is present, returns true.",
|
|
195
|
+
in: [ "c" ], out: true },
|
|
196
|
+
{ for: "When the input arg is not present, returns false.",
|
|
197
|
+
in: [ "d" ], out: false },
|
|
198
|
+
|
|
199
|
+
/* First test for ContainerModelClass .countOf(). */
|
|
200
|
+
{ of: "countOf", for: "Returns the number present.", in: [ "b" ], out: 2 }
|
|
375
201
|
```
|
|
376
202
|
|
|
377
|
-
-
|
|
203
|
+
- When you change the class in `.on`, all test properties are wiped away, and when you change the method in `.of`, only test properties about the class (like `.with`) are retained.
|
|
378
204
|
|
|
379
|
-
|
|
205
|
+
- Tests remain isolated, in effect, except when a test mutates input arguments. In that case, restate them in each test so the mutations aren't carried forward.
|
|
380
206
|
|
|
381
|
-
|
|
382
|
-
|----------|---------------------------------------------------------------------------------------------------|
|
|
383
|
-
| `target` | The instance of the class being tested |
|
|
384
|
-
| `test` | The test definition itself, whose properties may have been mutated by the tested method |
|
|
207
|
+
- Change test contents without possibly adding an unintended new test by adding a `.just` property (with any value, such as `true`) alongside the changed properties. **(2.0.0)**
|
|
385
208
|
|
|
209
|
+
&cruft, new site / details
|
|
210
|
+
- Further options and details can be found [here](https://deusware.com/risei-docs/index.html#collapsing-forward).
|
|
386
211
|
|
|
387
|
-
- The `test` parameter to a `.from` function contains all of the properties of your test definition, including those that collapsed forward.
|
|
388
|
-
- These properties are available by both short or long names (covered later).
|
|
389
|
-
- The `test.on` property always references the class under test, rather than an instance of it.
|
|
390
212
|
|
|
391
213
|
|
|
392
|
-
- You can write a function for `.from` that uses `test.on` to get the values of static properties, in conjunction with `and: "static"` in the encompassing test.
|
|
393
214
|
|
|
215
|
+
#### Ensure desired inputs from dependencies
|
|
394
216
|
|
|
395
|
-
|
|
217
|
+
To make code dependencies return what your tests need, just _spoof_ what you want using a `.plus` test property:
|
|
396
218
|
|
|
397
219
|
```javascript
|
|
398
|
-
{ on:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
220
|
+
{ on: CombinerClass, with: [],
|
|
221
|
+
of: "combineResults",
|
|
222
|
+
plus: [
|
|
223
|
+
{ on: ClassA, of: "someMethod", as: 10 }, // Spoofing one method to return 10.
|
|
224
|
+
{ on: ClassB, of: "someMethod" }, // Spoofing one method not to return anything.
|
|
225
|
+
{ on: ClassC, as: [ // Spoofing two class methods together.
|
|
226
|
+
{ of: "firstMethod", as: 11 },
|
|
227
|
+
{ of: "secondMethod", as: 12 }
|
|
228
|
+
] },
|
|
229
|
+
],
|
|
230
|
+
for: "When called, returns an array of values from sources.",
|
|
231
|
+
in: [ "green" ], out: [ 7, 8, 9, 10, 10, 11, 12, { color: "green" } ] }
|
|
406
232
|
```
|
|
407
233
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
### Property long names
|
|
413
|
-
|
|
414
|
-
Property names are short so they're easy to use. Some of them overlap with JavaScript keywords, but this causes no harm.
|
|
415
|
-
|
|
416
|
-
All test properties have long names that you can use instead of the short ones if you prefer, mixed together as much as you want. None of the long names are JavaScript keywords.
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
<details>
|
|
420
|
-
<summary>
|
|
421
|
-
Test properties' short and long names
|
|
422
|
-
</summary>
|
|
423
|
-
|
|
424
|
-
| Short Name | Long Name |
|
|
425
|
-
|------------|-----------|
|
|
426
|
-
| `on` | `type` |
|
|
427
|
-
| `with` | `initors` |
|
|
428
|
-
| `of` | `method` |
|
|
429
|
-
| `for` | `nature` |
|
|
430
|
-
| `in` | `inputs` |
|
|
431
|
-
| `out` | `output` |
|
|
432
|
-
| `plus` | `spoofed` |
|
|
433
|
-
| `from` | `source` |
|
|
434
|
-
| `and` | `factors` |
|
|
435
|
-
|
|
436
|
-
</details>
|
|
437
|
-
|
|
438
|
-
<br>
|
|
234
|
+
- It's just like _fakes_, _mocks_, or _test doubles_ in other test systems, but easier to write and read.
|
|
439
235
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
Spoof properties' short and long names
|
|
443
|
-
</summary>
|
|
236
|
+
&cruft, site / section
|
|
237
|
+
- There are many further spoofing options that save effort, including using nonce methods as spoofs and spoofing target-instance properties. **(2.0.0)** Check out all your options [here](https://deusware.com/risei-docs/index.html#collapsing-forward).
|
|
444
238
|
|
|
445
|
-
| Short Name | Long Name |
|
|
446
|
-
|------------|-----------|
|
|
447
|
-
| `on` | `target` |
|
|
448
|
-
| `of` | `method` |
|
|
449
|
-
| `as` | `output` |
|
|
450
239
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
### Further capabilities of Risei
|
|
456
|
-
|
|
457
|
-
Constructors can be tested with no special test properties or keywords.
|
|
458
|
-
- The method name in `.of` is simply `"constructor"`.
|
|
459
|
-
- Any `.with` args are completely ignored for a constructor test. Only those in the test's `.in` property are used.
|
|
460
|
-
- However, a `.with` must still be provided. It can simply be an empty array `[]`.
|
|
461
|
-
|
|
462
|
-
</details>
|
|
240
|
+
- Spoofed code is fully isolated within tests, even though spoof definitions collapse forward across tests (and within `.plus`).
|
|
463
241
|
|
|
464
242
|
|
|
465
243
|
|
|
466
244
|
|
|
467
245
|
## Using TypeScript with Risei
|
|
468
246
|
|
|
469
|
-
Testing TypeScript code with Risei basically just means transpiling before running the tests, and
|
|
247
|
+
Testing TypeScript code with Risei basically just means transpiling before running the tests, and pointing Risei to the transpiled JS files.
|
|
470
248
|
|
|
471
249
|
- Anything beyond those basics is intended to keep JS files separate from TS files and the output of web frameworks' own, complex build processes.
|
|
472
250
|
|
|
473
251
|
If you follow the general Risei set-up, you can just make the following few modifications for TypeScript applications.
|
|
474
252
|
- These steps have worked with both Angular and React.
|
|
475
|
-
-
|
|
253
|
+
- Varying other approaches are also sure to work, depending on the other technical choices in play.
|
|
476
254
|
|
|
477
255
|
|
|
478
256
|
|
|
@@ -511,7 +289,6 @@ You set up the transpiler to output files to a directory with these settings:
|
|
|
511
289
|
|
|
512
290
|
|
|
513
291
|
|
|
514
|
-
|
|
515
292
|
### In test files:
|
|
516
293
|
|
|
517
294
|
All `import` statements have to point to the Javascript (`.js`) files in the `outDir` path or subfolders there, using relative-path syntax:
|
|
@@ -525,70 +302,72 @@ import { TestedClass } from "../../dist/out-tsc/SubPath/TestedClass.js";
|
|
|
525
302
|
|
|
526
303
|
|
|
527
304
|
|
|
528
|
-
##
|
|
305
|
+
## What's new in Risei
|
|
529
306
|
|
|
530
|
-
|
|
531
|
-
- Use of `async` syntax
|
|
532
|
-
- Code written in ESM `export` modules, but not within classes
|
|
533
|
-
- Standalone functions and other functionality not built into classes, AKA _loose code_
|
|
534
|
-
- CJS syntax using `require()`
|
|
535
|
-
- Spoofing mixes of properties and methods, such as `something.method.property.method`
|
|
536
|
-
- Debugging model code during tests
|
|
537
|
-
- Comparing rare JS object types like `Proxy` or `ArrayBuffer` in test assertions
|
|
307
|
+
- Release **2.0.0** (month, 2024) introduces many [improvements](#using-risei), including new capabilities, bug fixes, and two breaking changes with only minor impacts on consuming code.
|
|
538
308
|
|
|
539
|
-
|
|
309
|
+
- Release **1.3.4** (March, 2024) fixed a bug that caused class display problems in some cases.
|
|
540
310
|
|
|
311
|
+
- Release **1.3.3** (March, 2024) fixed a major bug that prevented tests from running in Windows.
|
|
541
312
|
|
|
313
|
+
- Release **1.3.2** (February, 2024) only improved this read-me's contents.
|
|
542
314
|
|
|
315
|
+
- Release **1.3.1** (February, 2024) reversed some changes in 1.3.0 that did not work as hoped.
|
|
543
316
|
|
|
544
|
-
|
|
317
|
+
- Release **1.3.0** (February, 2024) added the loading-error gold bar and fixed a test-sorting bug.
|
|
545
318
|
|
|
546
|
-
|
|
319
|
+
- Release **1.2.0** (January, 2024) changed test sorting to move last-edited tests to the end.
|
|
547
320
|
|
|
548
|
-
|
|
549
|
-
|---------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
550
|
-
| Gold bar appears below the summary, and the number of tests run drops | A syntax error caused a test file not to load; error output in the gold bar explains why |
|
|
551
|
-
| `"Test loading failed for... SyntaxError: Unexpected token ':'"` | Missing comma in your tests in the named file |
|
|
552
|
-
| `"Test loading failed for... SyntaxError: Unexpected token '.'"` | Using `this.tests = []` instead of `tests = []` in the file named |
|
|
553
|
-
| Other `... Unexpected token ...` errors | Some other syntax error in the file named, most likely a missing or extra delimiter |
|
|
554
|
-
| Unexpected extra, failing test/s | Partial test properties in a mid-list object have produced extra tests |
|
|
555
|
-
| Unexpected actual values, or unexpected passes / fails in test runs | Test properties from previous tests not replaced or reset with `[]` <br>— or —<br> Args mutated by tested code were not restated in following tests to isolate them |
|
|
321
|
+
- Release **1.1.2** of Risei (January, 2024) fixed class displays and inaccurate `Date` comparisons.
|
|
556
322
|
|
|
323
|
+
- The oldest releases are not listed here, and old releases are dropped progressively over time. Using the latest release is recommended.
|
|
557
324
|
|
|
558
325
|
|
|
559
326
|
|
|
560
|
-
## Known issues and workarounds
|
|
561
327
|
|
|
562
|
-
|
|
328
|
+
## Troubleshooting
|
|
563
329
|
|
|
564
|
-
|
|
565
|
-
- To avoid this problem, just restate the args in each test of this code.
|
|
566
|
-
- The workaround for this — copying and initing objects to bypass mutation — requires too many assumptions to be reliable.
|
|
330
|
+
Problems loading tests are almost always a missing or extra comma, brace, or similar. When a test file can't be loaded, loading continues with the next file. The number of tests drops (or doesn't increase as expected), and a gold bar appears naming the file and problem:
|
|
567
331
|
|
|
332
|
+

|
|
568
333
|
|
|
569
|
-
-
|
|
570
|
-
|
|
571
|
-
- Rs is actually working as intended when this happens, but ways to optionally prevent it are being considered.
|
|
334
|
+
- Unfortunately, there is no way to list the problem line number.
|
|
335
|
+
- A sudden fail of many test files is usually due to a problem in the tested code, not the tests themselves.
|
|
572
336
|
|
|
337
|
+
Problems with test results themselves are usually due to omissions or other mistakes in test definitions.
|
|
573
338
|
|
|
339
|
+
For far more information about troubleshooting, including some specific error messages, check out the documentation [here](https://deusware.com/risei-docs/index.html#troubleshooting).
|
|
574
340
|
|
|
575
|
-
## What's new in Risei
|
|
576
341
|
|
|
577
|
-
- Release **1.3.3** (March, 2024) fixes a major bug related to file paths that prevented any tests from loading or running in Windows environments.
|
|
578
342
|
|
|
579
|
-
- Release **1.3.2** (February, 2024) does not change the code at all, but improves this read-me, notably explaining the easiest way to deal with mutable args (which is just restating the args), and correcting a few mistakes.
|
|
580
343
|
|
|
581
|
-
|
|
344
|
+
## Known issues and workarounds
|
|
345
|
+
|
|
346
|
+
At present, there are two known issues, both with simple workarounds:
|
|
347
|
+
|
|
348
|
+
- When tested code mutates its args, the mutated forms are used in subsequent tests if collapsed forward.
|
|
349
|
+
- To avoid this, simply restate the args for each test that mutates them.
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
- When a few properties are changed in separate objects, they are treated as whole new tests, which usually fail because of their unintended mix of old and new properties.
|
|
353
|
+
- To avoid this problem, just add a `.just` or `.only` property, of any value, in the same objects as those tests.change properties as part of whole new tests, or else restate `.of` along with the changed properties.
|
|
354
|
+
- You can also clear existing properties with `.on` or `.of` and then do this, since then there aren't enough test properties present yet to comprise a full test.
|
|
582
355
|
|
|
583
|
-
- Release **1.3.0** (February, 2024) moves the display of test-loading error messages to a new gold bar that appears at the bottom of the summary when there are any loading errors. A sorting error that occurs when no test files exist yet has also been fixed.
|
|
584
356
|
|
|
585
|
-
- Release **1.2.0** (January, 2024) changes sorting of test files. Previously they were displayed in the order found. Now the order remains the same, except that the last-edited file is moved to the bottom, making it easy to see the latest test results.
|
|
586
357
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
358
|
+
## Limitations in Risei
|
|
359
|
+
|
|
360
|
+
The following are not supported at present:
|
|
361
|
+
- Use of `async` syntax
|
|
362
|
+
- Code written in ESM `export` modules, but not within classes
|
|
363
|
+
- Standalone functions and other functionality not built into classes, AKA _loose code_
|
|
364
|
+
- CJS syntax using `require()`
|
|
365
|
+
- Debugging model code during tests
|
|
366
|
+
- Comparing rare JS object types like `Proxy` or `ArrayBuffer` in test assertions
|
|
367
|
+
|
|
368
|
+
Some of these are on the tentative future-development list.
|
|
369
|
+
- In the meantime, Risei can be used to save development time for most of your JavaScript code, while these cases can be tested using another framework invoked alongside Risei.
|
|
590
370
|
|
|
591
|
-
- Don't use release **1.1.1**, which contains an internal path error.
|
|
592
371
|
|
|
593
372
|
|
|
594
373
|
|
|
@@ -620,3 +399,5 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
620
399
|
|
|
621
400
|
|
|
622
401
|
|
|
402
|
+
|
|
403
|
+
|