Integrity v0.17.0 comes with the following major changes from its predecessor, 0.16.x:
Integrity now has its own in-code documentation format. It's very much inspired by JavaDoc (which is a time-tested and well-known solution to the in-code documentation problem, so I guess it's a good idea to just lean on established standards...) and allows you to attach documentation comments to packages, suites, fixture definitions, constants, forks and variants. In Eclipse, it looks a bit like in this example:
Of course the documentation texts support the same HTML-inspired formatting language that JavaDoc uses (well, at least all the well-known constructs, it's not 100% identical) so you can mark up your texts with headers, bold parts, paragraphs and lists.
The documentation comments are used in two ways. For one, they are displayed like JavaDoc in Java code in the Eclipse editor when writing tests. For example, the documentation for a fixture is displayed alongside that fixture in autocomplete or mouse-over scenarios. Likewise with suites, constants et cetera.
A typical task in automated testing is to validate the behavior of a system under specific, deterministic date/time environments. A common way to implement this is to re-route all relevant date/time queries via some kind of proxying mechanism, through which one can artificially set the time to be used by the system for business processes to something that deviates from realtime. It was already possible to configure such a proxying mechanism (= to actually set the time to be used) by using calls in Integrity, but especially when working with multiple forks, this can quickly get tedious, as you usually want the entire distributed system "in sync" with regard to your fake date/time. For this task, Integrity now adds a new command "timesync", which can be used to perform date/time setting on one or multiple forks. It looks like this:
You can use the timeset command anywhere in any suite, regardless whether it is called on a fork or on the master (timeset commands on forks are relayed to the master and executed from there, so one of the forks can even set the time of a different fork!). It supports progressing time as well as the more simpler concept of a "frozen" time that always stays the same. And in case of progressing time, where the previous mechanism inevitably led to deviations (due to your inability to call the "set the time" fixture on all forks at the exact same time) this new algorithm actually calculates the internal state of the test time generator on the master and pushes that to the forks, effectively resulting in a perfectly synchronized timebase across all forks and the master.
Besides setting absolute time as shown above, you may also "move" the test time relatively to the previously configured test time. To do this, specify the time difference instead of an absolute time, like this:
timeset + 1m timeset + 2minutes timeset - 3m 50s 100ms timeset + 1y on fork1 timeset + 1month on master timeset + 1mon 20d 2h on fork1
Basically you specify the duration in years, months, days, hours, minutes, seconds and milliseconds and the direction (+ for a forward jump, - for a backward jump). As shown in the examples, you may use short units (y/mon/d/h/m/s/ms) or longer, descriptive units (year, month, day, hour, minute, second, the trailing 's' is optional), but the unit MUST follow the number without a space in between! Note that this feature only works since Integrity 0.17.20.
Of course, in order to actually apply the configured time in your application, you need to have some kind of override mechanism by which you can override the normal system time in place. A suggestion for such a mechanism is provided in Integrity (look at de.gebit.integrity.runner.time.TimeAndDateSingleton), but you could just as well use your own, especially if you do it right and don't want to get any dependencies on the Integrity test runner jar into your production application. The way in which Integrity pushes the necessary state to calculate the "fake time" into the application is via a de.gebit.integrity.runner.time.TestTimeAdapter. This adapter must be implemented by some part of your application (maybe the part where your fixtures reside in) that is available during automated testing, and you then have two ways of letting Integrity know about your adapter implementation:
- Either you set the system property integrity.runner.timeadapter to the class name of your adapter implementation. Integrity will then try to instantiate it and call the interfaces' method on it (the code that does this is in de.gebit.integrity.runner.time.SimpleTestTimeAdapter, just in case you're interested).
- Or you use the Google Guice override mechanism of creating your own subclass of IntegrityDSLSetup, where you can override any Guice-injected part of Integrity (and the time adapter just happens to be one of those).
There's extensive in-code documentation on all these interfaces/implementations, so you are greatly encouraged to take a look at them for further details! And there is also a Github Issue Link.
Besides these big two features, there have been some smaller changes as well:
- You can now define "inlined suitedef"s - that is, suites that are always inlined when they are called, so they always behave as if you would call them via "inlined suite". This spares you from having to add "inlined" in front of every call to such suites, like with short utility suites. Github Issue Link
- It is now possible to inherit parameters from other fork definitions, so you may create "forkdef hierarchies" now, with forks inheriting stuff from other forks. See the Github Issue Link for an example.
- Significant speed-ups have been achieved specifically for "full build" actions in Eclipse! If your projects contain LOTS of Integrity script (like, in the thousands) with LOTS of global variables or constants, full project builds could take some time, as all these scripts get linked against each other and validated in that phase. This should be much better now, with real-world speed-ups measured in the realm of 60-70% (from 2 minutes to 35-40 seconds). (Note that this is a feature that only got introduced in Integrity 0.17.5!)
- Constant resolution has been changed from being a pre-execution phase to a "lazy" resolution, which only resolves constant (and initial variable) values when they are actually needed for something. This has three effects: first of all, it fixes a rare occurrence of concurrency problems with constant resolution that could happen due to the rather "unclean" parallel constant resolving code added in 0.16. And secondly it results in quite a bit of startup time saved in cases where large numbers of constants are present (like multiple thousands), although only a small subset of them is used in an actual test run. Finally it does make the test results more readable by limiting the global constants being displayed at the top of the results to just those that have actually been used in the test run. Github Issue Link (Note that this is a feature that only got introduced in Integrity 0.17.8!)