LambdaTest
LambdaTest - Lambda-enabled functional testing API on top of JUnit and TestNG
Install / Use
/learn @lefou/LambdaTestREADME
= Lambda Test :toc: :toc-placement: preamble :lambdatestversion: 0.8.0 :documentationversion: {lambdatestversion} :testngversion: 6.11 :junitversion: 4.12 :jupiterversion: 5.9.2 :lambdatest: LambdaTest ifndef::env-asciidoclet[:srcdir: src/main/java/] ifdef::env-asciidoclet[:srcdir:] ifndef::env-asciidoclet[:javasuffix: .java] ifdef::env-asciidoclet[:javasuffix: .html]
ifdef::env-github[] image:https://github.com/lefou/LambdaTest/workflows/.github/workflows/build.yml/badge.svg["Build Status", link="https://github.com/lefou/LambdaTest/actions"] image:https://api.codacy.com/project/badge/Grade/e886bd7ca9784ecfb00fe8afb59b8909["Codacy code quality", link="https://www.codacy.com/app/lefou/LambdaTest"] image:https://javadoc.io/badge2/de.tototec/de.tobiasroeser.lambdatest/javadoc.svg["JavaDoc", link="https://javadoc.io/doc/de.tototec/de.tobiasroeser.lambdatest"] image:https://badges.gitter.im/lefou/LambdaTest.svg["Chat on Gitter", link="https://gitter.im/lefou/LambdaTest"] endif::[]
ifndef::env-github[Project Homepage: https://github.com/lefou/LambdaTest]
Lambda-enabled functional testing on top of JUnit and TestNG.
Use the same DSL with any testing framework.
Documentation for LambdaTest {documentationversion}.
== Motivation
When constrained to work in a Java-only toolchain, I really miss http://scalatest.org[ScalaTest]. I tried some lambda enabled test frameworks, but until now (2014), did not find a suitable solution without compromizing the integration benefits.
Thus, I decided to write a small and generic test library that allows writing of functional test without reinventing the wheel. LambdaTest works on top of JUnit and TestNG, all you need is to add it to the test classpath. No further adaptions to your existing test setup are needed. You will immediately gain the joy of Lambda-enabled functional testing, better assertion messages and nicely colored output.
== Features
Most important features are:
- Write test via API (No longer required to have each test in a separate annotated method)
- Meaningful names for tests
- Nicely colored output per test case
- Easy to write data-centric tests (e.g. generate as much test cases as you need programmatically, e.g. in a loop)
- Easy to intercept exceptions with
intercept - Useful assertion message and difference highlighting in
expectXXX-methods - Opt-in to not fail fast when using
expectXXX-methods (see more than the first assertion error) - Easy to mark pending tests
- Contains useful tools to work with temporary files and directories
- Easy way to create proxies as mock dependencies
== Documentation
Beside this document, you can also read the https://javadoc.io/doc/de.tototec/de.tototec.utils.functional[JavadDoc for LambdaTest]
== Download from Maven Central
{lambdatest} is available from http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22de.tototec%22%20AND%20a%3A%22de.tobiasroeser.lambdatest%22[Maven central repository].
Maven users can use the following dependency declaration:
[source,xml,subs="attributes,verbatim"]
<dependencies> <dependency> <groupId>de.tototec</groupId> <artifactId>de.tobiasroeser.lambdatest</artifactId> <version>{lambdatestversion}</version> <scope>test</scope> </dependency> <!-- If you use LambdaTest with JUnit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>{junitversion}</version> <scope>test</scope> </dependency> <!-- If you use LambdaTest with TestNG --> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>{testngversion}</version> <scope>test</scope> </dependency> <!-- If you use LambdaTest with JUnit5 / Jupiter --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>{jupiterversion}</version> <scope>test</scope> </dependency> </dependencies> ----== Choose your favorite Unit-Test Runner: TestNG, JUnit, Junit5 (Jupiter)
With {lambdatest}, you need to only know LambdaTests very simple and minimalistic API but can use it to write test for JUnit and TestNG.
To avoid a dependency to both frameworks at the same time, your test class inherits a different base class, but besides that, everything else is the same.
For JUnit you inherit link:{srcdir}de/tobiasroeser/lambdatest/junit/FreeSpec{javasuffix}[de.tobiasroeser.lambdatest.junit.FreeSpec].
For Junit 5 (Jupiter) you inherit link:{srcdir}de/tobiasroeser/lambdatest/junit5/FreeSpec{javasuffix}[de.tobiasroeser.lambdatest.junit5.FreeSpec].
For TestNG you inherit
link:{srcdir}de/tobiasroeser/lambdatest/testng/FreeSpec{javasuffix}[de.tobiasroeser.lambdatest.testng.FreeSpec].
[NOTE]
If you use LambdaTest with mill.testng.TestNGFramework (in Mill or sbt), you may see extra verbose output.
You can disable the progress output of mill.testng.TestNGFramework by setting the mill.testng.printProgress property to 0.
.build.sc: Make mill.testng.TestNGFramework runner less verbose in Mill
[source,scala,subs="attributes"]
object test extends TestModule.TestNg { override def forkArgs = T{ super.forkArgs() ++ Seq("-Dmill.testng.printProgress=0") } }
--
== Writing tests with Lambda Test
The test cases can be defined in various places.
- in the class constructor
- in the
protected void initTests()method - in a class instance initializer
Here you see a basic test example, which produces a valid TestNG test class.
You need to extend from class de.tobiasroeser.lambdatest.testng.FreeSpec.
[source,java]
import static de.tobiasroeser.lambdatest.Expect.expectEquals; // You can also use JUnit or Junit 5 (Jupiter) based tests with // import de.tobiasroeser.lambdatest.junit.FreeSpec; // import de.tobiasroeser.lambdatest.junit5.FreeSpec; import de.tobiasroeser.lambdatest.testng.FreeSpec;
public class SimpleTest extends FreeSpec { public SimpleTest() {
test("1 + 1 = 2", () -> {
expectEquals(1 + 1, 2);
});
test("a pending test", () -> pending());
test("divide by zero", () -> {
int a = 2;
int b = 0;
intercept(ArithmeticException.class, () -> {
int c = a / b;
});
});
section("A String should", () -> {
final String aString = "A string";
test("match certain criteria", () -> {
expectString(aString)
.contains("string")
.containsIgnoreCase("String")
.startsWith("A")
.endsWith("ng")
.hasLength(8);
});
test("be not longer than 2", () -> {
expectString(aString).isLongerThan(2);
});
});
test("demo of a fail", () -> {
"yes".equals("yes and no");
});
{
test("test in initializer", () -> {
expectTrue(true);
});
}
}
// You can also define test here, to avoid // their initialization at class construction time @Override protected void initTests() { test("should succeed (lazy init)", () -> { expectTrue(true); }); } }
The methods test, pending and intercept are provided by FreeSpec
whereas the usual expectXXX methods are provided by Expect.
The output of this test suite above would look like this:
image:Screenshot_SimpleTest.jpg[]
[NOTE]
You can run the above test directly in the {lambdatest} project directory with:
mvn test -Dtest=SimpleTest
--
You should write your test cases so that they don't need to be executed in order.
{lambdatest} is able to run tests in parallel, if you enable it explicitly with FreeSpec.setRunInParallel(true).
By default expectXXX-methods fail fast, which means the first failing assertion will end the whole test.
This is also the behaviour you will get with most other test frameworks.
But you can disable fail-fast behaviour for assertions/expectations with FreeSpec.setExpectFailFast(false).
Then, the first failing expectXXX-error will not abort the test but the test is optimistically continued.
Further failing assertion errors are collected and the test fails at the end, reporting all collected errors.
== Writing assertions with Expect
{lambdatest} provides many methods in the class de.tobiasroeser.lambdatest.Expect to write assertion.
You can use these as an alternative to the assertion methods provides by other unit testing framework to gain the following advantages:
- Nice output of differences between expected and actual values. Especially for string and various collection types
expectXXX-methods provide a feature to collect multiple assertions (non-fail-fast behaviour), such that you can collect as much errors as possible in one test run, instead of giving up at the first error.
.Selected static methods of Expect
expectNull- Assert that a given value is nullexpectNotNull- Assert that a given value is not nullexpectEquals- Assert equality of two given objects or values.expectNotEquals- Assert non-equality of two given objects or values.expectTrue- Assert a value evaluates totrueexpectFalse- Assert a value evaluates tofalseexpectDouble- Assert that a given double is non-null and return an instance ofExpectDoublewith provides further checks on the actual double in a fluent APIexpectString- Assert that a given string is non-null and return an instance ofExpectStringwith provides further checks on the actual string in a fluent APIexpectCollection- Assert that a given collection is non-null and return an instance ofExpectCollectionwith provides further checks on the actual colletion in a fluent APIexpectMap- Assert that a given map is non-null and return an instance ofExpectMapwith provides further checks on the actual map in a fluent APIintercept- Assert that a code block throws an Exception of the given type and optional with an message matching a given regular expression. Returns the thrown exception for further analysis
There are more method in Expect with setup
Related Skills
gh-issues
337.3kFetch GitHub issues, spawn sub-agents to implement fixes and open PRs, then monitor and address PR review comments. Usage: /gh-issues [owner/repo] [--label bug] [--limit 5] [--milestone v1.0] [--assignee @me] [--fork user/repo] [--watch] [--interval 5] [--reviews-only] [--cron] [--dry-run] [--model glm-5] [--notify-channel -1002381931352]
node-connect
337.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Writing Hookify Rules
83.2kThis skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
