Skip to content

Commit

Permalink
Merge pull request #4 from LisiLisenok/develop
Browse files Browse the repository at this point in the history
0.5.0
  • Loading branch information
LisiLisenok committed Mar 9, 2016
2 parents 4e1b9bc + 32d3a6a commit 188383e
Show file tree
Hide file tree
Showing 77 changed files with 4,041 additions and 2,455 deletions.
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
#### asyncTest
is an extension to SDK `ceylon.test` module with following capabilities:
* testing asynchronous multithread code
* common initialization for a set of test functions
* storing initialized values on test context and retrieving them during test execution
* executing tests concurrently or sequentially
* parameterized testing
* conditional test execution
* organizing complex test conditions into a one flexible expression with matchers
* multi-reporting, i.e. several failures or successes can be reported for a one particular test execution (test function)
* reporting test results using charts (or graphs)

The module is available on [CeylonHerd](https://herd.ceylon-lang.org/modules/herd.asynctest)
* testing asynchronous multithread code
* common initialization for a test suite
* controlling test execution order
* executing tests concurrently or sequentially
* parameterized testing
* conditional test execution
* organizing complex test conditions into a one flexible expression with matchers
* multi-reporting: several failures or successes can be reported for a one particular test execution (test function),
each report is represented as test variant and might be marked with `String` title
* reporting test results using charts (or graphs)


The module is available on [CeylonHerd](https://herd.ceylon-lang.org/modules/herd.asynctest).


#### Ceylon compiler / platform
Expand All @@ -24,14 +26,15 @@ Available on JVM only
* ceylon.collection/1.2.1
* ceylon.file/1.2.1
* ceylon.language/1.2.1
* ceylon.promise/1.2.1 shared
* ceylon.test/1.2.1 shared
* java.base/8 JDK


#### Usage and documentation

The extension is aimed to be run using Ceylon test tool.
See usage details in [API documentation](https://modules.ceylon-lang.org/repo/1/herd/asynctest/0.4.0/module-doc/api/index.html)
See usage details in [API documentation](https://modules.ceylon-lang.org/repo/1/herd/asynctest/0.5.0/module-doc/api/index.html).


#### Examples
Expand All @@ -41,4 +44,5 @@ See usage details in [API documentation](https://modules.ceylon-lang.org/repo/1/
* [Time scheduler](examples/herd/examples/asynctest/scheduler) testing.
* [Microbenchmark](examples/herd/examples/asynctest/mapperformance) -
comparative performance test of Ceylon / Java HashMap and TreeMap.
* [Matchers](examples/herd/examples/asynctest/matchers) - mathcers usage.
* [Matchers](examples/herd/examples/asynctest/matchers) - matchers usage.
* [Maintainer](examples/herd/examples/asynctest/maintainer) - controlling test execution order.
145 changes: 72 additions & 73 deletions examples/herd/examples/asynctest/fibonacci/fibonacci.ceylon
Original file line number Diff line number Diff line change
@@ -1,75 +1,74 @@
import ceylon.promise {
import ceylon.promise {

Deferred,
Promise
}
import java.lang {
Deferred,
Promise
}
import java.lang {

Runnable,
Thread
}

"Calculates Fibonacci number by its index.
"
throws( `class AssertionError`, "passed index of Fibonacci number `indexOfFibonacciNumber` is less or equals to zero" )
shared Integer positiveFibonacciNumber( Integer indexOfFibonacciNumber ) {
"Fibonnachi number index must be positive"
assert ( indexOfFibonacciNumber > 0 );
variable Integer n0 = 0;
variable Integer n1 = 1;
variable Integer ret = 1;
variable Integer currentIndex = 1;
while ( currentIndex < indexOfFibonacciNumber ) {
ret = n0 + n1;
n0 = n1;
n1 = ret;
currentIndex ++;
}
return ret;
}

"Calculates index of positive Fibonacci number. That's may not be correct for index 1 and 2,
which corresponds to equals Fibonacci numbers."
throws( `class AssertionError`, "passed `fibonacciNumber` is not a Fibonacci number" )
shared Integer fibonacciNumberIndex( Integer fibonacciNumber ) {
"fibonacci number must be positive"
assert ( fibonacciNumber > 0 );
variable Integer n0 = 0;
variable Integer n1 = 1;
variable Integer ret = 1;
variable Integer currentIndex = 1;
while ( ret < fibonacciNumber ) {
ret = n0 + n1;
n0 = n1;
n1 = ret;
currentIndex ++;
}
"passed `fibonacciNumber` is not a Fibonacci number"
assert ( ret == fibonacciNumber );
return currentIndex;
}


"Calculates Fibonacci number by its index in separated thread and returns result as promise.
This is function to be tested."
shared Promise<Integer> asyncPositiveFibonacciNumber( Integer indexOfFibonacciNumber ) {
Deferred<Integer> ret = Deferred<Integer>();

Thread th = Thread (
object satisfies Runnable {
shared actual void run() {
try {
ret.fulfill( positiveFibonacciNumber( indexOfFibonacciNumber ) );
}
catch ( Throwable err ) {
ret.reject( err );
}
}
}
);
th.start();

return ret.promise;
}

Runnable,
Thread
}

"Calculates Fibonacci number by its index.
Function returns incorrect result in order to demonstrate test framework output.
"
throws( `class AssertionError`, "passed index of Fibonacci number `indexOfFibonacciNumber` is less or equals to zero" )
shared Integer positiveFibonacciNumber( Integer indexOfFibonacciNumber ) {
"Fibonnachi number index must be positive"
assert ( indexOfFibonacciNumber > 0 );
variable Integer n0 = 0;
variable Integer n1 = 1;
variable Integer ret = 1;
variable Integer currentIndex = 0; // use 1 to succeed the test!
while ( currentIndex < indexOfFibonacciNumber ) {
ret = n0 + n1;
n0 = n1;
n1 = ret;
currentIndex ++;
}
return ret;
}

"Calculates index of positive Fibonacci number. That's may not be correct for index 1 and 2,
which corresponds to equals Fibonacci numbers."
throws( `class AssertionError`, "passed `fibonacciNumber` is not a Fibonacci number" )
shared Integer fibonacciNumberIndex( Integer fibonacciNumber ) {
"fibonacci number must be positive"
assert ( fibonacciNumber > 0 );
variable Integer n0 = 0;
variable Integer n1 = 1;
variable Integer ret = 1;
variable Integer currentIndex = 1;
while ( ret < fibonacciNumber ) {
ret = n0 + n1;
n0 = n1;
n1 = ret;
currentIndex ++;
}
"passed `fibonacciNumber` is not a Fibonacci number"
assert ( ret == fibonacciNumber );
return currentIndex;
}


"Calculates Fibonacci number by its index in separated thread and returns result as promise.
This is function to be tested."
shared Promise<Integer> asyncPositiveFibonacciNumber( Integer indexOfFibonacciNumber ) {
Deferred<Integer> ret = Deferred<Integer>();

Thread th = Thread (
object satisfies Runnable {
shared actual void run() {
try {
ret.fulfill( positiveFibonacciNumber( indexOfFibonacciNumber ) );
}
catch ( Throwable err ) {
ret.reject( err );
}
}
}
);
th.start();

return ret.promise;
}

127 changes: 53 additions & 74 deletions examples/herd/examples/asynctest/fibonacci/fibonacciTest.ceylon
Original file line number Diff line number Diff line change
@@ -1,76 +1,55 @@
import ceylon.test {
import ceylon.test {

parameters,
test,
testExecutor
}
import herd.asynctest {
parameters,
test,
testExecutor
}
import herd.asynctest {

AsyncTestContext,
AsyncTestExecutor
}


"Fibonnachi test parameters."
see( `function runFibonacciTest` )
{[Integer, Integer]*} fibonacciNumbers =>
{
[3, 2], [4, 3], [5, 5], [6, 8], [7, 13], [8, 21], [9, 34], [10, 55]
};


"Runs test of Fibonacci numbers calculations.
Testing:
* comparison of expected value to calculated one
* comparison of calculated index of Fibonacci number with passed one - this will fail if pass index `2`
The function is marked with `testExecutor` annotation in order to perform asynchronous test.
Alternatively `testExecutor` annotation can be used at module level."
test parameters( `value fibonacciNumbers` )
testExecutor( `class AsyncTestExecutor` )
shared void runFibonacciTest (
"Context to send test results." AsyncTestContext context,
"Index of fibonnachi number to be calculated." Integer indexOfFibonacciNumber,
"Expected results of the calculations." Integer expectedFibonacciNumber
) {
// starts testing on context
context.start();

// do testing procedure
asyncPositiveFibonacciNumber( indexOfFibonacciNumber ).completed (
( Integer calculatedFibonacciNumber ) {
// compare calculated and expected values and notify context if fails
// Don't use `ceylon.test.assert...` here. It will throw on separated thread and will cause abnormal program termination
context.assertTrue (
calculatedFibonacciNumber == expectedFibonacciNumber,
"calculated Fibonacci number ``calculatedFibonacciNumber`` is not equal to expected one ``expectedFibonacciNumber``",
"number equality"
);

// calculates index from resulting Fibonacci number and compare it with passed one
try {
value index = fibonacciNumberIndex( calculatedFibonacciNumber );
context.assertTrue (
index == indexOfFibonacciNumber,
"calculated index of Fibonacci number ``index`` is not equal to expected one ``indexOfFibonacciNumber``",
"index equality"
);
}
catch ( Throwable err ) {
context.fail( err );
}

// completes the test when results reported
context.complete( "Fibonacci number is ``calculatedFibonacciNumber``" );
},
( Throwable reason ) {
// fail the test with error
// Don't use `ceylon.test.fail` here. It will throw on separated thread and will cause abnormal program termination
context.fail( reason );
// completes the test when fail reported
context.complete();
}
);

// just return whithout completion - the test will be completed later when promise is resolved
}
AsyncTestContext,
AsyncTestExecutor
}
import herd.asynctest.match {

EqualTo,
Mapping,
MatchResult
}


"Fibonacci test parameters."
see( `function runFibonacciTest` )
{[Integer, Integer]*} fibonacciNumbers =>
{
[3, 2], [4, 3], [5, 5], [6, 8], [7, 13], [8, 21], [9, 34], [10, 55]
};


"Runs test of Fibonacci numbers calculations.
Testing:
* comparison of expected value to calculated one
* comparison of calculated index of Fibonacci number with passed one - this will fail if pass index of `2`
The function is marked with `testExecutor` annotation in order to perform asynchronous test.
Alternatively `testExecutor` annotation can be used at module level."
test parameters( `value fibonacciNumbers` )
testExecutor( `class AsyncTestExecutor` )
shared void runFibonacciTest (
"Context to send test results." AsyncTestContext context,
"Index of Fibonacci number to be calculated." Integer indexOfFibonacciNumber,
"Expected results of the calculations." Integer expectedFibonacciNumber
) {
// start testing on context
context.start();

// perform calculation and checking
context.assertThat<Integer> (
asyncPositiveFibonacciNumber( indexOfFibonacciNumber ),
EqualTo( expectedFibonacciNumber ).and( Mapping( fibonacciNumberIndex, EqualTo( indexOfFibonacciNumber ) ) ),
"",
true
).onComplete( ( MatchResult|Throwable res ) => context.complete() );

// just return whithout completion
// the test will be completed later when promise returned by `asyncPositiveFibonacciNumber` is resolved
}
13 changes: 6 additions & 7 deletions examples/herd/examples/asynctest/fibonacci/package.ceylon
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"
Testing of asynchronous calculation of Fibonacci numbers.
Test is performed on [[asyncPositiveFibonacciNumber]] using [[runFibonacciTest]] test function.
>Function [[positiveFibonacciNumber]] returns incorrect results in order to demonstrate test framework output.
"
by( "Lis" )
shared package herd.examples.asynctest.fibonacci;
"
Testing of asynchronous calculation of Fibonacci numbers.
Test is performed on [[asyncPositiveFibonacciNumber]] using [[runFibonacciTest]] test function.
"
by( "Lis" )
shared package herd.examples.asynctest.fibonacci;
Loading

0 comments on commit 188383e

Please sign in to comment.