-
Notifications
You must be signed in to change notification settings - Fork 16
WUnit Wollok Unit Testing
The whole flow of testing begins when a user requests a .wtest
file to be tested:
Every time you run a test, a program or REPL console, you are launching a new Wollok VM.
- You can run any dangerous expression (like a neverending loop) without hanging the original VM. It is a safer approach.
- It is Xtext recommended architecture
- It is resource and time-consuming (at least 5-6 seconds, every time you want to run the tests)
- It is hard to communicate both VMs. In order to do so, we use a lightweight library called LipeRMI
Let's make the overall picture of the whole process:
Before Wollok Launcher starts, we need to setup some things: WollokLauncherParameters object has
- a
tests
flag pointing totrue
value - and a
testPort
number-
WollokTestLaunchDelegate sets
testPort
toWollokContextStateNotifier.listeningPort
, from the UI-VM
-
WollokTestLaunchDelegate sets
WollokLauncherModule
has sets the test reporter to the corresponding one:
-
WollokRemoteTestNotifier
if launcher was fired from Wollok IDE (WollokContextStateNotifier
is responsible for finding the first free port in the VM 1) -
WollokConsoleTestsReporter
if launcher was run from wollok-cli
Wollok Launcher calls Wollok Interpreter which in turn calls to the WollokInterpreterEvaluator | WollokLauncherInterpreterEvaluator
.
WollokInterpreterEvaluator delegates to several dispatch methods, but one of them is the main for tests/suites: WollokLauncherInterpreterEvaluator.evaluate(WFile)
. If you need to change the way tests are evaluated, this is the right place. Take a look into SuiteBuilder
class.
override dispatch evaluate(WTest test) {
try {
test.elements.forEach [ expr |
interpreter.performOnStack(expr, currentContext) [ | expr.eval ]
]
wollokTestsReporter.reportTestOk(test)
null
} catch (Exception e) {
handleExceptionInTest(e, test)
}
}
protected def WollokObject handleExceptionInTest(Exception e, WTest test) {
if (e.isAssertionException) {
wollokTestsReporter.reportTestAssertError(test, e.generateAssertionError, e.lineNumber, e.URI)
} else {
wollokTestsReporter.reportTestError(test, e, e.lineNumber, e.URI)
}
null
}
- Every time a test passes, test reporter is notified (testOk)
- The same happens if a test has an assertion error or fails
- There are a lot of notifications for the test reporter inside WollokLauncherInterpreterEvaluator
WollokRemoteTestReporter
collects every test result until the whole testing process finishes:
override finished(long timeElapsedInMilliseconds) {
if (!processingManyFiles) {
remoteTestNotifier.testsResult(testsResult, timeElapsedInMilliseconds)
}
}
remoteTestNotifier
is an instance variable, pointing to WollokRemoteUITestNotifier
interface. The main implementation is in another project: wollok.ui.launch, in the UI VM (we mean, the VM where Wollok IDE is located):
The main view of WUnit -xUnit implementation- is WollokTestResultView
, an observer of WollokTestResults
(the view model or application model), which has a container of WollokTestResult
. Since RMI calls tend to be expensive, an optimization feature added in Wollok Freire sends the final results in a single message: testResults
. These results are shown in a tree view container implemented by WTestTreeContentProvider
and WTestTreeLabelProvider
. It would be nice to extend this view into a multi-level tree, considering nested folders, describe and tests as possible nodes (nowadays only a single level is available).