-
Notifications
You must be signed in to change notification settings - Fork 3
Sprimber Customization
By the nature Sprimber very flexible framework. Main architecture principle that was used in design - everything should be public and everything is bean. It is mean, that in Sprimber Core(Engine) no inner classes, no package private access modifiers. Also, each class developed as a POJO(exclude Spring @Componnent
annotation). So, there is no object instantiation inside of the class and all the objects required for class work can be passed outside the class during initialization phase.
Since Sprimber is a Spring based framework for Spring based applications, all classes marked as a component and available for Sprimg class path scan. Third party dependencies declared as beans in one common class SprimberBeans
. You can refer to his class to simply find the dependencies. In addition some beans marked with ConditionalOnMissingBean
annotation - that's help to put the bean definition at the client side and Spring will automatically resolve the priority for the component.
Usually two ways for customization available:
- Autowire Sprimber beans to client classes and make the tuning for them
- Add bean definition in client configuration that will override default.
In below sections typical uses cases described.
Cucumber introduced feature named CucumberExpressions
. Main benefits that end user will be able to register own types and use them across the steps.
Sprimber simplify the procedure of new types registration. Since TypeRegistry
already declared as a bean in default Sprimber configuration then it is already available everywhere in application. Simple autowire it where the configuration should happens and use standard methods from TypeRegistry
to tune it. Example below:
@Configuration
public class Configuration {
private final TypeRegistry typeRegistry;
public Configuration(TypeRegistry typeRegistry) {
this.typeRegistry = typeRegistry;
}
@PostConstruct
public void registerNewTypes() {
defineNewType();
}
private void defineNewType() {
typeRegistry.defineParameterType(new ParameterType<>(...));
}
}
Internally Sprimber support 5 types:
- Passed - everything working fine
- Skipped - something skipped by design
- Pending - step not yet implemented
- Failed - if there is expected failures during execution, like assertion errors
- Broken - if there is unexpected failures during execution, like OutOfMemmory error.
Spimber provide the ability to precisely select and match exception by types. ErrorMapper
the main class very decision happens. To add Pending status it is required to throw custom exception in some steps and this custom exception should be annotated with one of the Pending marker annotations. To tell Sprimber what is a Pending marker annotations bean next bean exists. To add new annotation simply autowire it and using add
method add custom marker annotations. Note: Marker annotation on top of custom exception should be added not raw custom exception.
@Bean
public List<Class<? extends Annotation>> pendingExceptionAnnotations() {
List<Class<? extends Annotation>> pendingAnnotations = new ArrayList<>();
pendingAnnotations.add(Pending.class);
return pendingAnnotations;
}
To tell Sprimber which exception should provide Failed or Skipped status next beans available:
@Bean
public Set<String> skippedExceptionNames() {
Set<String> skippedExceptions = new HashSet<>();
skippedExceptions.add("org.junit.AssumptionViolatedException");
skippedExceptions.add("org.junit.internal.AssumptionViolatedException");
skippedExceptions.add("org.testng.SkipException");
return skippedExceptions;
}
@Bean
public Set<String> failedExceptionNames() {
Set<String> failedExceptions = new HashSet<>();
failedExceptions.add("java.lang.AssertionError");
return failedExceptions;
}
By default all exception that not in lists above treated as Broken
status.
Similar strategy exist for Sprimber allure plugin. Next bean available by default, and if there is no needs to treat Failed and Broken scenarios in different ways, this map can be adjusted at the client side.
@Bean
@ConditionalOnMissingBean
public Map<ExecutionResult.Status, Status> allureToSprimberStatusMapping() {
HashMap<ExecutionResult.Status, Status> statusMapping = new HashMap<>();
statusMapping.put(ExecutionResult.Status.PASSED, Status.PASSED);
statusMapping.put(ExecutionResult.Status.SKIPPED, Status.SKIPPED);
statusMapping.put(ExecutionResult.Status.FAILED, Status.FAILED);
statusMapping.put(ExecutionResult.Status.PENDING, Status.BROKEN);
statusMapping.put(ExecutionResult.Status.BROKEN, Status.BROKEN);
return statusMapping;
}
By default Sprimber treat each test case as atomic execution unit. So, parallel execution available at scenario level. By default next Executor
responsible for scenario exection
@Bean(SPRIMBER_EXECUTOR_NAME)
@ConditionalOnMissingBean // part of core code. in the client code conditional annotation doesn't required
public Executor asyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(3);
taskExecutor.setMaxPoolSize(3);
taskExecutor.setThreadNamePrefix("TCExecutor-");
taskExecutor.initialize();
return taskExecutor;
}
Overriding this bean in client configuration simply add ability to increase the thread numbers(default is 3) and add additional tuning.