-
Notifications
You must be signed in to change notification settings - Fork 10
0.8.x Tutorial
The new test runner is called JCUnit8 (com.github.dakusui.jcunit8.runners.junit4.JCUnit8).
When you use the runner, a configuration factory for the test class can
be specified it with another annotation @ConfigureWith. With it, you
can control various features of JCUnit such as negative test generation,
test suite strength, etc.
@RunWith(JCUnit8.class)
@ConfigureWith(BankAccountExample.BankAccountConfigFactory.class)
public class BankAccountExample {
...You can also configure a class from which parameters, constraints, and
non-constraint conditions are generated using parameterSpace attribute.
Methods annotated with @Test are considered to be test methods, but
unlike conventional JUnit test methods, they can take parameters. But each of
those parameters must be annotated with @From, which specifies how
actual argument values of the parameter should be supplied.
@Test
@Given("overdraftNotHappens")
public void whenPerformScenario$thenBalanceIsCorrect(
@From("scenario") List<String> scenario,
@From("depositAmount") int amountOfDeposit,
@From("withdrawAmount") int amountOfWithdraw,
@From("transferAmount") int amountOfTransfer
) {
...
}@From annotations specify a name of method defined from which actual parameter
values should be generated. Those methods must be defined in a class specified by
@ConfigureWith#parameterSpace.
-
NOTE: Unlike previous versions, you will not need to use
@Usesannotations anymore because the factors used in your test method are already declared by parameter definitions.
Expected behaviours of test cases can be different depending on inputs of them. E.g., when a sequence of bank account operations is executed, the expected outcome will be different depending on whether an overdraft happens or not.
In JCUnit8, this can be expressed by using @Given annotation.
A @Given annotation specifies a condition on which this test method
should be executed. In the example above, the test method whenPerformScenario$thenBalanceIsCorrect
will be invoked when (and only when) a method overdraftNotHappens, defined
in the class specified by @ConfigureWith#parameterSpace attribute,
returns true.
Currently JCUnit allows you to create composite conditions using three operators, AND, OR, and NOT from simple ones. With them, you should be able to express any boolean forms in theory (because you can transform any boolean form into DNF)
But parentheses cannot be used.
If you want to express ANDed conditions, you can do it by following.
@Test
@Given("condition1&&condition2")
public void aTestMethod(...) {
...To express ORed conditions,
@Test
@Given({"condition1", "condition2"})
public void aTestMethod(...) {
...And to negate a condition, you can do
@Test
@Given({"!condition1", "condition2&&!condition3"})
public void aTestMethod(...) {
...As mentioned already, parentheses are not supported and you cannot write a condition like this.
@Given("(condition1||!condition2)&&condition3")You will need to rewrite this to following.
@Given({"condition1&&condition3", "!condition2&&condition3"})The model from which JCUnit generates test cases consists of three elements which are
- Parameters
- Constraints
- Test oracles
Test oracles are defined as methods in a test class and associated with test cases
using @Given annotations. In this section it will be discussed how to define
parameters and constraints.
When you can list actual values of a parameter and it's sufficient, you can (and should) use "Simple" parameter model. Following is an example.
@ParameterSource
public Simple.Factory<Integer> depositAmount() {
return Simple.Factory.of(asList(100, 200, 300, 400, 500, 600, -1));
}The annotation @ParameterSource tells JCUnit that it is a method
that supplies actual values of parameter depositAmount (method name).
@From annotations reference methods defined in a class that implements
Config.Factory and is referred to by @ConfiguredWith annotation.
A method annotated with @ParameterSource must return a factory of a
parameter class. And the parameter object created by the returned factory
should hold actual values to be used in the generated test suite.
When you want to use a simple parameter, it can be done just by doing
return Simple.Factory.of(asList(100, 200, 300, 400, 500, 600, -1));The values 100, 200, 300, ..., passed to (Arrays.)asList are values
that you can use the parameter depositAmount.
To define a constraint, you can do following.
@Condition(constraint = true)
public boolean overdraftNotHappens(
@From("scenario") List<String> scenario,
@From("depositAmount") int amountOfDeposit,
@From("withdrawAmount") int amountOfWithdraw,
@From("transferAmount") int amountOfTransfer
) {
return calculateBalance(scenario, amountOfDeposit, amountOfWithdraw, amountOfTransfer) >= 0;
}When you want to make it a non-constraint-condition, you can omit the
attribute constraint or explicitly set the value to false.
@Condition(constraint = false)
public boolean overdraftNotHappens(-
NOTE: Unlike previous versions, you will not need to use
@Usesannotations anymore because the factors used in your test method are already declared by parameter definitions.
Copyright 2013 Hiroshi Ukai.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.