Help:Pickle/Expect
Pickle Portal |
---|
Documentation
Examples
Technical Misc |
There is a test-lib based on expectations, that is a we say what the subject is expected to do, not what is a failed response. This is slightly different from the assert style testing libs. Expectations are common in several testing frameworks, but the style implemented has its own quirks to make it work in our environment.
The main difference is that while an assertion says whats wrong and stops execution, while expectation says whats right and continue execution. In addition there are some magic behind the scenes to allow the subjects and expectations to be set up for repeated testing.
expect()
should not set the subject but the expectation. Not quite sure whats easier to understand.Core idea
[edit]There are three access functions; subject
, expect
, and reports
.
They all act as accessors to several internal structures, but in particular the first two act as accessors to a condition
object.
The first two also has their own stacks for storing objects assigned to them.
That makes it possible to keep subjects and expectations for later testing, and especially to set up partial fixtures for repeated testing.
There are several ways to implement objects in Lua, but we can safely assume that most objects we want to test will be based on tables. By implementing additional accessors we can test other types of objects too, but most of the time we we will be testing tables.
Assume we have a rather simple library foo
on the form
local h = {
bar = function() return 'baz' end
}
return h
This i pretty typical for most libraries, and we can include it in other libraries as
local foo = require 'foo'
and this can set in our test fixtures as
subject = require 'foo'
The form local subject = require 'foo'
should not be used, as this will not work.
This creates a local variable, while we want to assign the required lib to an existing variable. Or really assign to the table.
It is also possible to set the testee as a temporal, by instead use a call syntax, like subject( require 'foo' )
.
This will place the object in a temporary store in the condition object created by the access method.
There is one important thing; note one important thing; we are testing the object returned from the library, and if that maintain a state it will be retained from call to call. We may say that we are testing a specific instance of the object and not the library. This can lead to bogus tests, so be careful!
In its simple form it is already ready for testing. The instance from the submerges in the subject = require 'foo'
line and emerges in the conditions
structure.
Because that is available through subject
and expect
we can add simple tests like
subject = require 'foo'
subject :bar() :toBe( 'baz' )
or in call-style
subject(require 'foo') :toBe( 'baz' )
The final toBe( 'baz' )
does a little magic, it sets the opposite value of the initial access method.
If the initial access method is subject
then it sets the temporal expect, if it is expect
then it sets the temporal subject.
It will not push the value on the subject or expect stacks.
Note in particular that these gives the same result (here the testee is not a table and is defined inline)
subject = 'a'
expect :toBe( 'a' )
expect( 'a' ) :toBeSame()
and that also this is the same
subject = 'a'
expect = 'a'
subject :toBeSame()
expect :toBeSame()
condition :toBeSame()
The results from the tests are accessible through reports
.
In a Mediawiki-context the reports can be shown by calling mw.log
expect( 'baz' ) :toBe( 'baz' )
mw.log( report() )
Library
[edit]Preprocesses
[edit]Preprocesses or conditioners are those methods that are run before the similarity test, which is our idea of what is a correct answer. After the similarity test there are additional postprocesses to transform the test into our final outcome. That makes it possible to do a positive identification of a state and then negate that state, which is often easier to do than to test for the negative outcome.
Preprocesses can be attached to both subjects and expectations, which gives slightly different testing styles.
If the chain is started by subject
then the preprocesses attach to the subject, while if it starts with expect
then the preprocesses attach to the expectation.
It is possible to start attaching to one of them and then shift to the other one.
Picks
[edit]Functions may return multiple values, and there are a number of methods to extract a specific value. Typical use is like
expect('a', 'b', 'c') :second() :toBe('a')
The methods are named
- first
- second
- third
- fourth
- fifth
- sixth
- seventh
- eight
- ninth
- tenth
- eleventh
- twelfth
Casting
[edit]A few methods for casting
subject( '42' ) :asNumber() :toBe( 42 )
subject( 42 ) :asString() :toBe( '42' )
- asNumber
- number
- asString
- string
Formatters
[edit]There are formatters to shift from one format to another
Formatters for strings (second levels are aliases)
- asUpper
- upper
- asUC
- uc
- asLower
- lower
- asLC
- lc
- asUpperFirst
- upperfirst
- asUCFirst
- asUCfirst
- ucfirst
- asLowerFirst
- lowerfirst
- asLCFirst
- asLCfirst
- lcfirst
Formatters for ustrings (second levels are aliases)
- … same as methods for strings, except they has an "u" attached
- asNFC
- nfc
- asNFD
- nfd
Formatters for numbers
- asInteger
- integer
- asFraction
- fraction
- asRound
- round
- asFloor
- floor
- as Ceil
- ceil