Skip to content

Sprimber Customization

vvolverine edited this page Feb 4, 2019 · 2 revisions

Intro

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:

  1. Autowire Sprimber beans to client classes and make the tuning for them
  2. Add bean definition in client configuration that will override default.

In below sections typical uses cases described.

TypeRegistry

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<>(...));
    }
}

Execution status customization

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.

Pending

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;
    }

Failed & Skipped

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;
    }

Broken

By default all exception that not in lists above treated as Broken status.

Allure Mapping

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;
}

Multi Threading

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.