Skip to content

Program flow

Under the hood, Carina uses TestNG framework, so the first class to initialize is RemoteTestNGStarter class. Program lifecycle logic can be observed at TestNG run() method.

The initializing turn comes to Carina when CarinaListenerChain object is created. It extends ListenerChain which will create, sort and attach IAbstractTest listeners CarinaListener.class, TestRunListener.class, FilterTestsListener.class. This whole sequence is described in TestRunner init() method.

These listeners are being attached and created when transform(IListenersAnnotation annotation, Class testClass) method is called.

Because CarinaListener object is created, the class static field is initialized in it. There are several important steps inside:

  • R.reinit(). This method loads default values for all parameters from carina-core, then overrides them with user's configurations (,,,,,
  • Configure log4j2x properties
  • Initialize L10N feature.

Then standard listeners according to their implementations in TestNG:

Report link

Then overridden TestNG methods

  • FilterTestsListener->onStart(ISuite suite)

  • TestRunListener->onStart(ISuite suite)

  • CarinaListener->onStart(ISuite suite)

  • Now your test class is considered initialized and onStart(ITestContext testContext) method is called.

  • onBeforeClass(ITestClass testClass). Complete the steps described in @BeforeClass annotation from your test.

  • onTestStart(ITestResult result) provides described data to test.

Next, TestRunner.class runs code described in your test class. The following route depends on what you are doing in your test:

UI (web, mobile)

@Test @MethodOwner()
public void webTest() {
   HomePage chromeHomePage = new HomePage(getDriver());;
   Assert.assertTrue(chromeHomePage.isPageOpened(), "Chrome home page is not opened!"); 

Debug entry point at : AbstractPage constructor and IDriverPool getDriver() method.


public void testCreateUser() throws Exception {
   PostUserMethod api = new PostUserMethod();

Debug entry point at : AbstractApiMethodV2 constructor.


public void createUser() {

   User USER = new User() {{

   try (SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession(true)) {
     UserMapper userMapper = session.getMapper(UserMapper.class);

These are user's classes, samples at carina-demo: UserMapper, ConnectionFactory, User.


Dependent vs. independent tests. Which approach is better?

Try to develop fully independent tests to reuse all the benefits of the multi-threading execution. For example, Zebrunner Selenium Grid provides 1000 threads as default limitation and allows to execute your full regression scenarios in minutes! Use dependent methods via dependsOnMethods Test Annotation only if it is really required by Test logic. Carina will preserve all drivers for dependent methods so you can start a driver in one method and proceed with the page in another.

public class WebSampleSingleDriver implements IAbstractTest {
    HomePage homePage = null;
    CompareModelsPage comparePage = null;
    List<ModelSpecs> specs = new ArrayList<>();

    public void startDriver() {
        // Open GSM Arena home page and verify page is opened
        homePage = new HomePage(getDriver());

    public void testOpenPage() {;
        Assert.assertTrue(homePage.isPageOpened(), "Home page is not opened");

    @Test(dependsOnMethods="testOpenPage") //for dependent tests Carina keeps driver sessions by default
    public void testOpenCompare() {
        // Open GSM Arena home page and verify page is opened
        // Open model compare page
        FooterMenu footerMenu = homePage.getFooterMenu();
        Assert.assertTrue(footerMenu.isUIObjectPresent(2), "Footer menu wasn't found!");
        comparePage = footerMenu.openComparePage();


    @Test(dependsOnMethods="testOpenCompare") //for dependent tests Carina keeps driver sessions by default
    public void testReadSpecs() {
        // Compare 3 models
        specs = comparePage.compareModels("Samsung Galaxy J3", "Samsung Galaxy J5", "Samsung Galaxy J7 Pro");

    @Test(dependsOnMethods="testReadSpecs") //for dependent tests Carina keeps driver sessions by default
    public void testCompareModels() {
        // Verify model announced dates
        SoftAssert() softAssert = new SoftAssert();
        softAssert.assertEquals(specs.get(0).readSpec(SpecType.ANNOUNCED), "2016, March 31");
        softAssert.assertEquals(specs.get(1).readSpec(SpecType.ANNOUNCED), "2015, June 19");
        softAssert.assertEquals(specs.get(2).readSpec(SpecType.ANNOUNCED), "2017, June");