This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 014144f61 FINERACT-2070: Integrate the new test framework into the 
public build pipeline
014144f61 is described below

commit 014144f61475b6e6b1d053b723dac206f6b2c89b
Author: Aleks <[email protected]>
AuthorDate: Mon Mar 25 05:55:29 2024 +0100

    FINERACT-2070: Integrate the new test framework into the public build 
pipeline
---
 .github/workflows/build-mariadb.yml                |   4 +-
 .github/workflows/build-mysql.yml                  |   4 +-
 .github/workflows/build-postgresql.yml             |   4 +-
 .github/workflows/build-tests.yml                  |  42 +++++++
 build.gradle                                       |   7 +-
 fineract-e2e-tests-core/build.gradle               |  64 ++++++++++
 .../apache/fineract/test/api/ApiConfiguration.java |  49 ++++++++
 .../apache/fineract/test/api/ApiProperties.java    |  37 ++++++
 .../test/api/FineractClientConfiguration.java      |  47 ++++++++
 .../test/config/TestApplicationConfiguration.java  |  29 +++++
 .../test/factory/ClientRequestFactory.java         |  49 ++++++++
 .../apache/fineract/test/helper/CodeHelper.java    |  61 ++++++++++
 .../apache/fineract/test/helper/ErrorHelper.java   |  37 ++++++
 .../fineract/test/helper/ErrorMessageHelper.java   |  35 ++++++
 .../org/apache/fineract/test/helper/Utils.java     |  45 +++++++
 .../fineract/test/stepdef/AbstractStepDef.java     |  28 +++++
 .../test/stepdef/common/ClientStepDef.java         | 118 +++++++++++++++++++
 .../apache/fineract/test/support/TestContext.java  |  49 ++++++++
 .../fineract/test/support/TestContextKey.java      | 129 +++++++++++++++++++++
 .../resources/fineract-test-application.properties |  39 +++++++
 fineract-e2e-tests-runner/build.gradle             |  91 +++++++++++++++
 .../java/org/apache/fineract/test/TestRunner.java  |  29 +++++
 .../test/config/TestCucumberConfiguration.java     |  26 +++++
 .../test/resources/META-INF/fineract-test.config   |   2 +
 .../src/test/resources/allure.properties           |  20 ++++
 .../src/test/resources/cucumber.properties         |  20 ++++
 .../src/test/resources/features/Client.feature     |  29 +++++
 .../src/test/resources/logback.xml                 |  35 ++++++
 .../fineract/integrationtests/common/Utils.java    |   4 +-
 settings.gradle                                    |   2 +
 30 files changed, 1124 insertions(+), 11 deletions(-)

diff --git a/.github/workflows/build-mariadb.yml 
b/.github/workflows/build-mariadb.yml
index ae7982874..586367f0f 100644
--- a/.github/workflows/build-mariadb.yml
+++ b/.github/workflows/build-mariadb.yml
@@ -81,8 +81,8 @@ jobs:
           FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports
         run: |
             ./gradlew --no-daemon --console=plain build -x cucumber -x test -x 
doc
-            ./gradlew --no-daemon --console=plain cucumber
-            ./gradlew --no-daemon --console=plain test -x 
:twofactor-tests:test -x :oauth2-test:test
+            ./gradlew --no-daemon --console=plain cucumber -x 
:fineract-e2e-tests-runner:cucumber
+            ./gradlew --no-daemon --console=plain test -x 
:twofactor-tests:test -x :oauth2-test:test -x :fineract-e2e-tests-runner:test
             ./gradlew --no-daemon --console=plain :twofactor-tests:test
             ./gradlew --no-daemon --console=plain :oauth2-tests:test
 
diff --git a/.github/workflows/build-mysql.yml 
b/.github/workflows/build-mysql.yml
index 59e4de1a8..50a388633 100644
--- a/.github/workflows/build-mysql.yml
+++ b/.github/workflows/build-mysql.yml
@@ -81,8 +81,8 @@ jobs:
           FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports
         run: |
             ./gradlew --no-daemon --console=plain build -x cucumber -x test -x 
doc
-            ./gradlew --no-daemon --console=plain cucumber
-            ./gradlew --no-daemon --console=plain test -x 
:twofactor-tests:test -x :oauth2-test:test -PdbType=mysql
+            ./gradlew --no-daemon --console=plain cucumber -x 
:fineract-e2e-tests-runner:cucumber
+            ./gradlew --no-daemon --console=plain test -x 
:twofactor-tests:test -x :oauth2-test:test :fineract-e2e-tests-runner:test 
-PdbType=mysql
             ./gradlew --no-daemon --console=plain :twofactor-tests:test 
-PdbType=mysql
             ./gradlew --no-daemon --console=plain :oauth2-tests:test 
-PdbType=mysql
 
diff --git a/.github/workflows/build-postgresql.yml 
b/.github/workflows/build-postgresql.yml
index 6a43c2274..c5093bd6b 100644
--- a/.github/workflows/build-postgresql.yml
+++ b/.github/workflows/build-postgresql.yml
@@ -82,8 +82,8 @@ jobs:
           FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports
         run: |
             ./gradlew --no-daemon --console=plain build -x cucumber -x test -x 
doc
-            ./gradlew --no-daemon --console=plain cucumber
-            ./gradlew --no-daemon --console=plain test -x 
:twofactor-tests:test -x :oauth2-test:test -PdbType=postgresql
+            ./gradlew --no-daemon --console=plain cucumber -x 
:fineract-e2e-tests-runner:cucumber
+            ./gradlew --no-daemon --console=plain test -x 
:twofactor-tests:test -x :oauth2-test:test :fineract-e2e-tests-runner:test 
-PdbType=postgresql
             ./gradlew --no-daemon --console=plain :twofactor-tests:test 
-PdbType=postgresql
             ./gradlew --no-daemon --console=plain :oauth2-tests:test 
-PdbType=postgresql
 
diff --git a/.github/workflows/build-tests.yml 
b/.github/workflows/build-tests.yml
new file mode 100644
index 000000000..289efc6e3
--- /dev/null
+++ b/.github/workflows/build-tests.yml
@@ -0,0 +1,42 @@
+name: Fineract Tests
+
+on: [push, pull_request]
+
+permissions:
+  contents: read
+
+jobs:
+  build:
+    runs-on: ubuntu-22.04
+    env:
+      GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_TOKEN }}
+
+    steps:
+      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
+        with:
+          fetch-depth: 0
+      - name: Set up JDK 17
+        uses: actions/setup-java@9704b39bf258b59bc04b50fa2dd55e9ed76b47a8 # v4
+        with:
+          java-version: '17'
+          distribution: 'zulu'
+          cache: gradle
+      - name: Build the image
+        run: ./gradlew --no-daemon --console=plain :fineract-provider:clean 
:fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
+      - name: Start the Fineract stack
+        run: docker compose -f docker-compose-postgresql.yml up -d
+      - name: Wait for stack to come up
+        run: sleep 400
+      - name: Check the stack
+        run: docker ps
+      - name: Check health Manager
+        run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
+      - name: Execute tests
+        env:
+          BASE_URL: https://localhost:8443
+          TEST_USERNAME: mifos
+          TEST_PASSWORD: password
+          TEST_TENANT_ID: default
+          INITIALIZATION_ENABLED: true
+          EVENT_VERIFICATION_ENABLED: false
+        run: ./gradlew --no-daemon --console=plain 
fineract-e2e-tests-runner:cucumber --tags 'not @Skip' allureReport
diff --git a/build.gradle b/build.gradle
index 104d5af10..b46af2b55 100644
--- a/build.gradle
+++ b/build.gradle
@@ -37,7 +37,9 @@ buildscript {
                 'twofactor-tests',
                 'oauth2-tests',
                 'fineract-client',
-                'fineract-avro-schemas'
+                'fineract-avro-schemas',
+                'fineract-e2e-tests-core',
+                'fineract-e2e-tests-runner'
             ].contains(it.name)
         }
         fineractPublishProjects = subprojects.findAll{
@@ -282,7 +284,8 @@ allprojects  {
             ".mailmap",
             '**/images/diag-*.svg',
             '**/*.avsc',
-            "**/generated/**/*MapperImpl.java"
+            "**/generated/**/*MapperImpl.java",
+            '**/META-INF/fineract-test.config'
         ]
     }
 }
diff --git a/fineract-e2e-tests-core/build.gradle 
b/fineract-e2e-tests-core/build.gradle
new file mode 100644
index 000000000..79032d3e8
--- /dev/null
+++ b/fineract-e2e-tests-core/build.gradle
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+
+plugins {
+    id 'java'
+}
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    testImplementation(project(':fineract-avro-schemas'))
+    testImplementation(project(':fineract-client'))
+
+    testImplementation 'org.springframework:spring-context'
+    implementation 'org.springframework:spring-test'
+    testImplementation 'org.springframework:spring-jms'
+
+    testImplementation 'com.squareup.retrofit2:retrofit:2.9.0'
+    testImplementation 'commons-httpclient:commons-httpclient:3.1'
+    testImplementation 'org.apache.commons:commons-lang3:3.14.0'
+    testImplementation 'com.googlecode.json-simple:json-simple:1.1.1'
+    testImplementation 'com.google.code.gson:gson:2.10.1'
+
+    testImplementation 'io.cucumber:cucumber-java:7.15.0'
+    testImplementation 'io.cucumber:cucumber-junit:7.15.0'
+    testImplementation 'io.cucumber:cucumber-spring:7.15.0'
+
+    testImplementation 'io.qameta.allure:allure-cucumber7-jvm:2.25.0'
+
+    testImplementation 'org.assertj:assertj-core:3.25.3'
+    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
+    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
+
+    testCompileOnly 'org.projectlombok:lombok:1.18.30'
+    testAnnotationProcessor 'org.projectlombok:lombok:1.18.30'
+
+    testImplementation "ch.qos.logback:logback-core:1.5.3"
+    testImplementation "ch.qos.logback:logback-classic:1.5.3"
+
+    testImplementation 'org.apache.activemq:activemq-client:6.0.1'
+    testImplementation "org.apache.avro:avro:1.11.3"
+    testImplementation "org.awaitility:awaitility:4.2.0"
+    testImplementation 'io.github.classgraph:classgraph:4.8.168'
+
+    testImplementation 'org.apache.commons:commons-collections4:4.4'
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java
new file mode 100644
index 000000000..db8576355
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.api;
+
+import org.apache.fineract.client.services.ClientApi;
+import org.apache.fineract.client.services.CodeValuesApi;
+import org.apache.fineract.client.services.CodesApi;
+import org.apache.fineract.client.util.FineractClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ApiConfiguration {
+
+    @Autowired
+    private FineractClient fineractClient;
+
+    @Bean
+    public ClientApi clientApi() {
+        return fineractClient.createService(ClientApi.class);
+    }
+
+    @Bean
+    public CodesApi codesApi() {
+        return fineractClient.createService(CodesApi.class);
+    }
+
+    @Bean
+    public CodeValuesApi codeValuesApi() {
+        return fineractClient.createService(CodeValuesApi.class);
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java
new file mode 100644
index 000000000..417685a13
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiProperties.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.api;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+@Getter
+public class ApiProperties {
+
+    @Value("${fineract-test.api.base-url}")
+    private String baseUrl;
+    @Value("${fineract-test.api.username}")
+    private String username;
+    @Value("${fineract-test.api.password}")
+    private String password;
+    @Value("${fineract-test.api.tenant-id}")
+    private String tenantId;
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/FineractClientConfiguration.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/FineractClientConfiguration.java
new file mode 100644
index 000000000..dcdff97c9
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/FineractClientConfiguration.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.api;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.client.util.FineractClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@Slf4j
+public class FineractClientConfiguration {
+
+    @Autowired
+    private ApiProperties apiProperties;
+
+    @Bean
+    public FineractClient fineractClient() {
+        String baseUrl = apiProperties.getBaseUrl();
+        String username = apiProperties.getUsername();
+        String password = apiProperties.getPassword();
+        String tenantId = apiProperties.getTenantId();
+
+        String apiBaseUrl = baseUrl + "/fineract-provider/api/";
+
+        log.info("Using base URL '{}'", apiBaseUrl);
+
+        return FineractClient.builder().basicAuth(username, 
password).tenant(tenantId).baseURL(apiBaseUrl).insecure(true).build();
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/TestApplicationConfiguration.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/TestApplicationConfiguration.java
new file mode 100644
index 000000000..d75564c84
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/TestApplicationConfiguration.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.config;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.context.annotation.PropertySource;
+
+@Configuration
+@ComponentScan(value = "org.apache.fineract.test", excludeFilters = 
@ComponentScan.Filter(type = FilterType.REGEX, pattern = 
"org\\.apache\\.fineract\\.test\\.initializer.*"))
+@PropertySource("classpath:fineract-test-application.properties")
+public class TestApplicationConfiguration {}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/ClientRequestFactory.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/ClientRequestFactory.java
new file mode 100644
index 000000000..b58660c40
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/ClientRequestFactory.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.factory;
+
+import org.apache.fineract.client.models.PostClientsRequest;
+import org.apache.fineract.test.helper.Utils;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ClientRequestFactory {
+
+    private static final Long HEAD_OFFICE_ID = 1L;
+    private static final Long LEGAL_FORM_ID_PERSON = 1L;
+    public static final String DATE_FORMAT = "dd MMMM yyyy";
+    public static final String DEFAULT_LOCALE = "en";
+
+    public PostClientsRequest defaultClientCreationRequest() {
+        return new PostClientsRequest()//
+                .officeId(HEAD_OFFICE_ID)//
+                .legalFormId(LEGAL_FORM_ID_PERSON)//
+                .firstname(Utils.randomNameGenerator("Client_FirstName_", 5))//
+                .lastname(Utils.randomNameGenerator("Client_LastName_", 5))//
+                .externalId(randomClientId("ID_", 7))//
+                .dateFormat(DATE_FORMAT)//
+                .locale(DEFAULT_LOCALE)//
+                .active(true)//
+                .activationDate("04 March 2011");//
+    }
+
+    private String randomClientId(final String prefix, final int 
lenOfRandomSuffix) {
+        return Utils.randomStringGenerator(prefix, lenOfRandomSuffix, 
"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/CodeHelper.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/CodeHelper.java
new file mode 100644
index 000000000..ff01ac874
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/CodeHelper.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.helper;
+
+import java.io.IOException;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.client.models.GetCodesResponse;
+import org.apache.fineract.client.models.PostCodeValueDataResponse;
+import org.apache.fineract.client.models.PostCodeValuesDataRequest;
+import org.apache.fineract.client.services.CodeValuesApi;
+import org.apache.fineract.client.services.CodesApi;
+import org.springframework.stereotype.Component;
+import retrofit2.Response;
+
+@Component
+@RequiredArgsConstructor
+public class CodeHelper {
+
+    private static final String COUNTRY_CODE_NAME = "COUNTRY";
+    private static final String STATE_CODE_NAME = "STATE";
+    private static final String ADDRESS_TYPE_CODE_NAME = "ADDRESS_TYPE";
+
+    private final CodesApi codesApi;
+    private final CodeValuesApi codeValuesApi;
+
+    public Response<PostCodeValueDataResponse> 
createAddressTypeCodeValue(String addressTypeName) throws IOException {
+        Long codeId = retrieveCodeByName(ADDRESS_TYPE_CODE_NAME).getId();
+        return codeValuesApi.createCodeValue(codeId, new 
PostCodeValuesDataRequest().name(addressTypeName)).execute();
+    }
+
+    public Response<PostCodeValueDataResponse> createCountryCodeValue(String 
countryName) throws IOException {
+        Long codeId = retrieveCodeByName(COUNTRY_CODE_NAME).getId();
+        return codeValuesApi.createCodeValue(codeId, new 
PostCodeValuesDataRequest().name(countryName)).execute();
+    }
+
+    public Response<PostCodeValueDataResponse> createStateCodeValue(String 
stateName) throws IOException {
+        Long codeId = retrieveCodeByName(STATE_CODE_NAME).getId();
+        return codeValuesApi.createCodeValue(codeId, new 
PostCodeValuesDataRequest().name(stateName)).execute();
+    }
+
+    public GetCodesResponse retrieveCodeByName(String name) throws IOException 
{
+        return codesApi.retrieveCodes().execute().body().stream().filter(r -> 
name.equals(r.getName())).findAny()
+                .orElseThrow(() -> new IllegalArgumentException("Code with 
name " + name + " has not been found"));
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java
new file mode 100644
index 000000000..594902362
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.helper;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import retrofit2.Response;
+
+public final class ErrorHelper {
+
+    private ErrorHelper() {}
+
+    public static void checkSuccessfulApiCall(Response response) throws 
IOException {
+        
assertThat(response.isSuccessful()).as(ErrorMessageHelper.requestFailed(response)).isTrue();
+
+        if (response.code() != 200 && response.code() != 202 && 
response.code() != 204) {
+            throw new 
AssertionError(ErrorMessageHelper.requestFailedWithCode(response));
+        }
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java
new file mode 100644
index 000000000..76cc7f51a
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.helper;
+
+import java.io.IOException;
+import retrofit2.Response;
+
+public final class ErrorMessageHelper {
+
+    private ErrorMessageHelper() {}
+
+    public static String requestFailed(Response response) throws IOException {
+        return String.format("Request failed. Error:%n%s", 
response.errorBody() != null ? response.errorBody().string() : null);
+    }
+
+    public static String requestFailedWithCode(Response response) {
+        return String.format("Response has error code: %2d", response.code());
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java
new file mode 100644
index 000000000..f4e882ddc
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/Utils.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.helper;
+
+import java.security.SecureRandom;
+
+public final class Utils {
+
+    private static final SecureRandom random = new SecureRandom();
+
+    private Utils() {}
+
+    public static String randomStringGenerator(final String prefix, final int 
len, final String sourceSetString) {
+        final int lengthOfSource = sourceSetString.length();
+        final StringBuilder sb = new StringBuilder(len);
+        for (int i = 0; i < len; i++) {
+            sb.append(sourceSetString.charAt(random.nextInt(lengthOfSource)));
+        }
+        return prefix + sb;
+    }
+
+    public static String randomStringGenerator(final String prefix, final int 
len) {
+        return randomStringGenerator(prefix, len, 
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+    }
+
+    public static String randomNameGenerator(final String prefix, final int 
lenOfRandomSuffix) {
+        return randomStringGenerator(prefix, lenOfRandomSuffix);
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/AbstractStepDef.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/AbstractStepDef.java
new file mode 100644
index 000000000..61a52a9b4
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/AbstractStepDef.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.stepdef;
+
+import org.apache.fineract.test.support.TestContext;
+
+public class AbstractStepDef {
+
+    public TestContext testContext() {
+        return TestContext.INSTANCE;
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/ClientStepDef.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/ClientStepDef.java
new file mode 100644
index 000000000..7f0ae6e91
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/ClientStepDef.java
@@ -0,0 +1,118 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.stepdef.common;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.cucumber.java.en.Then;
+import io.cucumber.java.en.When;
+import java.io.IOException;
+import java.util.Arrays;
+import org.apache.fineract.client.models.PostClientsAddressRequest;
+import org.apache.fineract.client.models.PostClientsRequest;
+import org.apache.fineract.client.models.PostClientsResponse;
+import org.apache.fineract.client.services.ClientApi;
+import org.apache.fineract.test.factory.ClientRequestFactory;
+import org.apache.fineract.test.helper.CodeHelper;
+import org.apache.fineract.test.helper.ErrorHelper;
+import org.apache.fineract.test.helper.ErrorMessageHelper;
+import org.apache.fineract.test.helper.Utils;
+import org.apache.fineract.test.stepdef.AbstractStepDef;
+import org.apache.fineract.test.support.TestContextKey;
+import org.springframework.beans.factory.annotation.Autowired;
+import retrofit2.Response;
+
+public class ClientStepDef extends AbstractStepDef {
+
+    @Autowired
+    private ClientApi clientApi;
+
+    @Autowired
+    private CodeHelper codeHelper;
+
+    @Autowired
+    private ClientRequestFactory clientRequestFactory;
+
+    @When("Admin creates a client with random data")
+    public void createClientRandomFirstNameLastName() throws IOException {
+        PostClientsRequest clientsRequest = 
clientRequestFactory.defaultClientCreationRequest();
+
+        Response<PostClientsResponse> response = 
clientApi.create6(clientsRequest).execute();
+        ErrorHelper.checkSuccessfulApiCall(response);
+        testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response);
+    }
+
+    @When("Admin creates a second client with random data")
+    public void createSecondClientRandomFirstNameLastName() throws IOException 
{
+        PostClientsRequest clientsRequest = 
clientRequestFactory.defaultClientCreationRequest();
+
+        Response<PostClientsResponse> response = 
clientApi.create6(clientsRequest).execute();
+        ErrorHelper.checkSuccessfulApiCall(response);
+        testContext().set(TestContextKey.CLIENT_CREATE_SECOND_CLIENT_RESPONSE, 
response);
+    }
+
+    @When("Admin creates a client with Firstname {string} and Lastname 
{string}")
+    public void createClient(String firstName, String lastName) throws 
IOException {
+        PostClientsRequest clientsRequest = 
clientRequestFactory.defaultClientCreationRequest().firstname(firstName).lastname(lastName);
+
+        Response<PostClientsResponse> response = 
clientApi.create6(clientsRequest).execute();
+        ErrorHelper.checkSuccessfulApiCall(response);
+        testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response);
+    }
+
+    @When("Admin creates a client with Firstname {string} and Lastname 
{string} with address")
+    public void createClientWithAddress(String firstName, String lastName) 
throws IOException {
+        Long addressTypeId = 
codeHelper.createAddressTypeCodeValue(Utils.randomNameGenerator("Residential 
address", 4)).body()
+                .getResourceId();
+        Long countryId = 
codeHelper.createCountryCodeValue(Utils.randomNameGenerator("Hungary", 
4)).body().getResourceId();
+        Long stateId = 
codeHelper.createStateCodeValue(Utils.randomNameGenerator("Budapest", 
4)).body().getResourceId();
+        String city = "Budapest";
+        boolean addressIsActive = true;
+        long postalCode = 1000L;
+
+        PostClientsAddressRequest addressRequest = new 
PostClientsAddressRequest().postalCode(postalCode).city(city).countryId(countryId)
+                
.stateProvinceId(stateId).addressTypeId(addressTypeId).isActive(addressIsActive);
+
+        PostClientsRequest clientsRequest = 
clientRequestFactory.defaultClientCreationRequest().firstname(firstName).lastname(lastName)
+                .address(Arrays.asList(addressRequest));
+
+        Response<PostClientsResponse> response = 
clientApi.create6(clientsRequest).execute();
+        ErrorHelper.checkSuccessfulApiCall(response);
+        testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response);
+
+    }
+
+    @When("Admin creates a client with Firstname {string} and Lastname 
{string} with {string} activation date")
+    public void createClientWithSpecifiedDates(String firstName, String 
lastName, String activationDate) throws IOException {
+
+        PostClientsRequest clientsRequest = 
clientRequestFactory.defaultClientCreationRequest().firstname(firstName).lastname(lastName)
+                .activationDate(activationDate);
+
+        Response<PostClientsResponse> response = 
clientApi.create6(clientsRequest).execute();
+        ErrorHelper.checkSuccessfulApiCall(response);
+        testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response);
+    }
+
+    @Then("Client is created successfully")
+    public void checkClientCreatedSuccessfully() throws IOException {
+        Response<PostClientsResponse> response = 
testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
+
+        
assertThat(response.isSuccessful()).as(ErrorMessageHelper.requestFailed(response)).isTrue();
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContext.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContext.java
new file mode 100644
index 000000000..f9beda2a5
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContext.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.support;
+
+import static java.lang.ThreadLocal.withInitial;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum TestContext {
+
+    INSTANCE;
+
+    @SuppressWarnings("ImmutableEnumChecker")
+    private final ThreadLocal<Map<String, Object>> testContexts = 
withInitial(HashMap::new);
+
+    public <T> T get(String name) {
+        Object storedValue = testContexts.get().get(name);
+        return (T) storedValue;
+    }
+
+    public Map<String, Object> get() {
+        return testContexts.get();
+    }
+
+    public <T> void set(String name, T object) {
+        testContexts.get().put(name, object);
+    }
+
+    public void reset() {
+        testContexts.get().clear();
+    }
+}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
new file mode 100644
index 000000000..ac1c7472e
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
@@ -0,0 +1,129 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.support;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public abstract class TestContextKey {
+
+    public static final String CLIENT_CREATE_RESPONSE = "clientCreateResponse";
+    public static final String CLIENT_CREATE_SECOND_CLIENT_RESPONSE = 
"clientCreateSecondClientResponse";
+    public static final String LOAN_CREATE_RESPONSE = "loanCreateResponse";
+    public static final String LOAN_CREATE_SECOND_LOAN_RESPONSE = 
"loanCreateSecondLoanResponse";
+    public static final String LOAN_MODIFY_RESPONSE = "loanModifyResponse";
+    public static final String ADD_DUE_DATE_CHARGE_RESPONSE = 
"addDueDateChargeResponse";
+    public static final String ADD_PROCESSING_FEE_RESPONSE = 
"addProcessingFeeResponse";
+    public static final String ADD_NSF_FEE_RESPONSE = "addNsfFeeResponse";
+    public static final String WAIVE_CHARGE_RESPONSE = "waiveChargeResponse";
+    public static final String UNDO_WAIVE_RESPONSE = "waiveNsfFeeResponse";
+    public static final String LOAN_APPROVAL_RESPONSE = "loanApprovalResponse";
+    public static final String LOAN_APPROVAL_SECOND_LOAN_RESPONSE = 
"loanApprovalSecondLoanResponse";
+    public static final String LOAN_UNDO_APPROVAL_RESPONSE = 
"loanUndoApprovalResponse";
+    public static final String LOAN_DISBURSE_RESPONSE = "loanDisburseResponse";
+    public static final String LOAN_DISBURSE_SECOND_LOAN_RESPONSE = 
"loanDisburseSecondLoanResponse";
+    public static final String LOAN_UNDO_DISBURSE_RESPONSE = 
"loanUndoDisburseResponse";
+    public static final String LOAN_REPAYMENT_RESPONSE = 
"loanRepaymentResponse";
+    public static final String LOAN_PAYMENT_TRANSACTION_RESPONSE = 
"loanPaymentTransactionResponse";
+    public static final String LOAN_REFUND_RESPONSE = "loanRefundResponse";
+    public static final String LOAN_REAGING_RESPONSE = "loanReAgingResponse";
+    public static final String LOAN_REAGING_UNDO_RESPONSE = 
"loanReAgingUndoResponse";
+    public static final String LOAN_REAMORTIZATION_RESPONSE = 
"loanReAmortizationResponse";
+    public static final String LOAN_REAMORTIZATION_UNDO_RESPONSE = 
"loanReAmortizationUndoResponse";
+    public static final String BUSINESS_DATE_RESPONSE = "businessDateResponse";
+    public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30 = 
"loanProductCreateResponsePin30";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_DUE_DATE = 
"loanProductCreateResponsePin30DueDate";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE = 
"loanProductCreateResponsePin30PaymentStrategyDueInAdvance";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_INTEREST_FLAT
 = "loanProductCreateResponsePin30PaymentStrategyDueInAdvanceInterestFlat";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE
 = 
"loanProductCreateResponsePin30PaymentStrategyDueInAdvancePenaltyInterestPrincipalFee";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_INTEREST_FLAT
 = 
"loanProductCreateResponsePin30PaymentStrategyDueInAdvancePenaltyInterestPrincipalFeeInterestFlat";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_FLAT = 
"loanProductCreateResponsePin30InterestFlat";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT = 
"loanProductCreateResponsePin30InterestFlatOverdueFromAmount";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT_INTEREST
 = "loanProductCreateResponsePin30InterestFlatOverdueFromAmountInterest";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_MULTI_DISBURSE
 = "loanProductCreateResponsePin30InterestFlatMultiDisburse";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_PERIOD_SAME_AS_PAYMENT
 = "loanProductCreateResponsePin30InterestDecliningPeriodSameAsPayment";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_1MONTH_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY
 = 
"loanProductCreateResponsePin30InterestDecliningPeriodSameAsPaymentRecalculation";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE
 = 
"loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationCompoundingNone";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE
 = 
"loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNone";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_SAR_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE_MULTI_DISBURSEMENT
 = 
"loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNoneMultiDisbursement";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_REDUCE_NR_INSTALLMENTS
 = 
"loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleReduceNrInstallments";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_NEXT_REPAYMENTS
 = 
"loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleNextRepayments";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_PERIOD_DAILY = 
"loanProductCreateResponsePin30InterestDecliningPeriodDaily";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION
 = "loanProductCreateResponsePin4DownPaymentAutoAdvancedPaymentAllocation";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT = 
"loanProductCreateResponsePin4DownPayment";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_INTEREST = 
"loanProductCreateResponsePin4DownPaymentInterest";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_INTEREST_AUTO = 
"loanProductCreateResponsePin4DownPaymentInterestAuto";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_AUTO = 
"loanProductCreateResponsePin4DownPaymentAuto";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE
 = "loanProductCreateResponsePin4DownPaymentProgressiveLoanSchedule";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_VERTICAL
 = "loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleVertical";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_INSTALLMENT_LEVEL_DELINQUENCY
 = 
"loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleInstallmentLevelDelinquency";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION
 = 
"loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleHorizontalInstallmentLevelDelinquencyCreditAllocation";
+    public static final String CHARGE_FOR_LOAN_PERCENT_LATE_CREATE_RESPONSE = 
"ChargeForLoanPercentLateCreateResponse";
+    public static final String 
CHARGE_FOR_LOAN_PERCENT_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE = 
"ChargeForLoanPercentLateAmountPlusInterestCreateResponse";
+    public static final String 
CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = 
"ChargeForLoanPercentProcessingCreateResponse";
+    public static final String CHARGE_FOR_LOAN_FIXED_LATE_CREATE_RESPONSE = 
"ChargeForLoanFixedLateCreateResponse";
+    public static final String 
CHARGE_FOR_LOAN_FIXED_RETURNED_PAYMENT_CREATE_RESPONSE = 
"ChargeForLoanFixedReturnedPaymentCreateResponse";
+    public static final String CHARGE_FOR_LOAN_SNOOZE_FEE_CREATE_RESPONSE = 
"ChargeForLoanSnoozeFeeCreateResponse";
+    public static final String CHARGE_FOR_LOAN_NSF_FEE_CREATE_RESPONSE = 
"ChargeForLoanNsfFeeCreateResponse";
+    public static final String 
CHARGE_FOR_LOAN_DISBURSEMENET_FEE_CREATE_RESPONSE = 
"ChargeForLoanDisbursementCreateResponse";
+    public static final String CHARGE_FOR_LOAN_INSTALLMENT_FEE_CREATE_RESPONSE 
= "ChargeForLoanInstallmentCreateResponse";
+    public static final String CHARGE_FOR_CLIENT_FIXED_FEE_CREATE_RESPONSE = 
"ChargeForClientFixedFeeCreateResponse";
+    public static final String LOAN_RESPONSE = "loanResponse";
+    public static final String LOAN_REPAYMENT_UNDO_RESPONSE = 
"loanRepaymentUndoResponse";
+    public static final String LOAN_TRANSACTION_UNDO_RESPONSE = 
"loanTransactionUndoResponse";
+    public static final String LOAN_CHARGEBACK_RESPONSE = 
"loanChargebackResponse";
+    public static final String LOAN_CHARGE_ADJUSTMENT_RESPONSE = 
"loanChargeAdjustmentResponse";
+    public static final String PUT_CURRENCIES_RESPONSE = 
"putCurrenciesResponse";
+    public static final String BATCH_API_CALL_RESPONSE = 
"batchApiCallResponse";
+    public static final String BATCH_API_CALL_IDEMPOTENCY_KEY = 
"batchApiIdempotencyKey";
+    public static final String BATCH_API_CALL_IDEMPOTENCY_KEY_2 = 
"batchApiIdempotencyKey2";
+    public static final String BATCH_API_CALL_CLIENT_EXTERNAL_ID = 
"batchApiClientExternalId";
+    public static final String BATCH_API_CALL_CLIENT_EXTERNAL_ID_2 = 
"batchApiClientExternalId2";
+    public static final String BATCH_API_CALL_LOAN_EXTERNAL_ID = 
"batchApiLoanExternalId";
+    public static final String BATCH_API_CALL_LOAN_EXTERNAL_ID_2 = 
"batchApiLoanExternalId2";
+    public static final String EUR_SAVINGS_ACCOUNT_CREATE_RESPONSE = 
"eurSavingsAccountCreateResponse";
+    public static final String USD_SAVINGS_ACCOUNT_CREATE_RESPONSE = 
"usdSavingsAccountCreateResponse";
+    public static final String EUR_SAVINGS_ACCOUNT_APPROVE_RESPONSE = 
"eurSavingsAccountApproveResponse";
+    public static final String USD_SAVINGS_ACCOUNT_APPROVE_RESPONSE = 
"usdSavingsAccountApproveResponse";
+    public static final String EUR_SAVINGS_ACCOUNT_ACTIVATED_RESPONSE = 
"eurSavingsAccountActivateResponse";
+    public static final String USD_SAVINGS_ACCOUNT_ACTIVATED_RESPONSE = 
"usdSavingsAccountActivateResponse";
+    public static final String EUR_SAVINGS_ACCOUNT_DEPOSIT_RESPONSE = 
"eurSavingsAccountDepositResponse";
+    public static final String USD_SAVINGS_ACCOUNT_DEPOSIT_RESPONSE = 
"usdSavingsAccountDepositResponse";
+    public static final String EUR_SAVINGS_ACCOUNT_WITHDRAW_RESPONSE = 
"eurSavingsAccountWithdrawResponse";
+    public static final String USD_SAVINGS_ACCOUNT_WITHDRAW_RESPONSE = 
"usdSavingsAccountWithdrawResponse";
+    public static final String LOAN_FRAUD_MODIFY_RESPONSE = 
"loanFraudModifyResponse";
+    public static final String DEFAULT_SAVINGS_PRODUCT_CREATE_RESPONSE_EUR = 
"defaultSavingsProductCreateResponseEur";
+    public static final String DEFAULT_SAVINGS_PRODUCT_CREATE_RESPONSE_USD = 
"defaultSavingsProductCreateResponseUsd";
+    public static final String TRANSACTION_IDEMPOTENCY_KEY = 
"transactionIdempotencyKey";
+    public static final String LOAN_CHARGE_OFF_RESPONSE = 
"loanChargeOffResponse";
+    public static final String LOAN_CHARGE_OFF_UNDO_RESPONSE = 
"loanChargeOffUndoResponse";
+    public static final String CREATED_SIMPLE_USER_RESPONSE = 
"createdSimpleUserResponse";
+    public static final String ASSET_EXTERNALIZATION_RESPONSE = 
"assetExternalizationResponse";
+    public static final String 
ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED = 
"assetExternalizationTransferExternalIdUserGenerated";
+    public static final String 
ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_FROM_RESPONSE = 
"assetExternalizationTransferExternalIdFromResponse";
+    public static final String 
ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE = 
"assetExternalizationSalesTransferExternalIdFromResponse";
+    public static final String 
ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_EXTERNAL_ID_FROM_RESPONSE = 
"assetExternalizationBuybackTransferExternalIdFromResponse";
+    public static final String ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_PREFIX = 
"assetExternalizationTransferPrefix";
+    public static final String ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID = 
"assetExternalizationOwnerExternalId";
+    public static final String TRANSACTION_EVENT = "transactionEvent";
+    public static final String LOAN_WRITE_OFF_RESPONSE = 
"loanWriteOffResponse";
+    public static final String LOAN_DELINQUENCY_ACTION_RESPONSE = 
"loanDelinquencyActionResponse";
+
+}
diff --git 
a/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties
 
b/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties
new file mode 100644
index 000000000..d9d724678
--- /dev/null
+++ 
b/fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties
@@ -0,0 +1,39 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License 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.
+#
+
+fineract-test.api.base-url=${BASE_URL:https://localhost:8443}
+fineract-test.api.username=${TEST_USERNAME:mifos}
+fineract-test.api.password=${TEST_PASSWORD:password}
+fineract-test.api.tenant-id=${TEST_TENANT_ID:default}
+
+fineract-test.initialization.enabled=${INITIALIZATION_ENABLED:false}
+
+fineract-test.testrail.enabled=${TESTRAIL_ENABLED:false}
+fineract-test.testrail.base-url=${TESTRAIL_BASEURL:}
+fineract-test.testrail.username=${TESTRAIL_USERNAME:}
+fineract-test.testrail.password=${TESTRAIL_PASSWORD:}
+fineract-test.testrail.run-id=${TESTRAIL_RUN_ID:0}
+
+fineract-test.messaging.jms.broker-url=${ACTIVEMQ_BROKER_URL:}
+fineract-test.messaging.jms.broker-username=${ACTIVEMQ_BROKER_USERNAME:}
+fineract-test.messaging.jms.broker-password=${ACTIVEMQ_BROKER_PASSWORD:}
+fineract-test.messaging.jms.topic-name=${ACTIVEMQ_TOPIC_NAME:}
+
+fineract-test.event.wait-timeout-in-sec=${EVENT_WAIT_TIMEOUT_IN_SEC:5}
+fineract-test.event.verification-enabled=${EVENT_VERIFICATION_ENABLED:false}
diff --git a/fineract-e2e-tests-runner/build.gradle 
b/fineract-e2e-tests-runner/build.gradle
new file mode 100644
index 000000000..170da9bd9
--- /dev/null
+++ b/fineract-e2e-tests-runner/build.gradle
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+
+plugins {
+    id 'se.thinkcode.cucumber-runner' version '0.0.11'
+    id 'io.qameta.allure' version '2.11.2'
+}
+
+apply plugin: 'java'
+apply plugin: 'eclipse'
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    testImplementation(project(':fineract-avro-schemas'))
+    testImplementation(project(':fineract-client'))
+    
testImplementation(project(':fineract-e2e-tests-core').sourceSets.test.output)
+
+    testImplementation 'org.springframework:spring-context'
+    implementation 'org.springframework:spring-test'
+    testImplementation 'org.springframework:spring-jms'
+
+    testImplementation 'com.squareup.retrofit2:retrofit:2.9.0'
+    testImplementation 'commons-httpclient:commons-httpclient:3.1'
+    testImplementation 'org.apache.commons:commons-lang3:3.14.0'
+    testImplementation 'com.googlecode.json-simple:json-simple:1.1.1'
+    testImplementation 'com.google.code.gson:gson:2.10.1'
+
+    testImplementation 'io.cucumber:cucumber-java:7.15.0'
+    testImplementation 'io.cucumber:cucumber-junit:7.15.0'
+    testImplementation 'io.cucumber:cucumber-spring:7.15.0'
+
+    testImplementation 'io.qameta.allure:allure-cucumber7-jvm:2.25.0'
+
+    testImplementation 'org.assertj:assertj-core:3.25.3'
+    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
+    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
+
+    testCompileOnly 'org.projectlombok:lombok:1.18.30'
+    testAnnotationProcessor 'org.projectlombok:lombok:1.18.30'
+
+    testImplementation "ch.qos.logback:logback-core:1.5.3"
+    testImplementation "ch.qos.logback:logback-classic:1.5.3"
+
+    testImplementation 'org.apache.activemq:activemq-client:6.0.1'
+    testImplementation "org.apache.avro:avro:1.11.3"
+    testImplementation "org.awaitility:awaitility:4.2.0"
+    testImplementation 'io.github.classgraph:classgraph:4.8.168'
+
+    testImplementation 'org.apache.commons:commons-collections4:4.4'
+}
+
+tasks.named('test') {
+    useJUnitPlatform()
+}
+
+tasks.named('cucumber').get().finalizedBy 'allureReport'
+
+tasks.named('cucumber').get().dependsOn 'spotlessCheck'
+
+cucumber {
+    tags = 'not @ignore'
+    main = 'io.cucumber.core.cli.Main'
+    shorten = 'argfile'
+    plugin = [
+        'pretty',
+        'io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm'
+    ]
+}
+
+allure {
+    version = '2.17.3'
+}
diff --git 
a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/TestRunner.java
 
b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/TestRunner.java
new file mode 100644
index 000000000..c07c0349d
--- /dev/null
+++ 
b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/TestRunner.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test;
+
+import io.cucumber.junit.Cucumber;
+import io.cucumber.junit.CucumberOptions;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(features = "src/test/resources/features", glue = { 
"org.apache.fineract.test.stepdef",
+        "org.apache.fineract.test.stepdef.common", 
"org.apache.fineract.test.stepdef.hook", 
"org.apache.fineract.test.stepdef.loan",
+        "org.apache.fineract.test.stepdef.saving", 
"org.apache.fineract.test.config" })
+public class TestRunner {}
diff --git 
a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/config/TestCucumberConfiguration.java
 
b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/config/TestCucumberConfiguration.java
new file mode 100644
index 000000000..9a85efb9d
--- /dev/null
+++ 
b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/config/TestCucumberConfiguration.java
@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License 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.
+ */
+package org.apache.fineract.test.config;
+
+import io.cucumber.spring.CucumberContextConfiguration;
+import org.springframework.test.context.ContextConfiguration;
+
+@CucumberContextConfiguration
+@ContextConfiguration(classes = TestApplicationConfiguration.class)
+public class TestCucumberConfiguration {}
diff --git 
a/fineract-e2e-tests-runner/src/test/resources/META-INF/fineract-test.config 
b/fineract-e2e-tests-runner/src/test/resources/META-INF/fineract-test.config
new file mode 100644
index 000000000..29e582985
--- /dev/null
+++ b/fineract-e2e-tests-runner/src/test/resources/META-INF/fineract-test.config
@@ -0,0 +1,2 @@
+org.apache.fineract.test.initializer.Configuration=org.apache.fineract.test.initializer.FineractInitializerConfiguration,\
+                                                   
org.apache.fineract.test.initializer.base.BaseFineractInitializerConfiguration
diff --git a/fineract-e2e-tests-runner/src/test/resources/allure.properties 
b/fineract-e2e-tests-runner/src/test/resources/allure.properties
new file mode 100644
index 000000000..d66fd8925
--- /dev/null
+++ b/fineract-e2e-tests-runner/src/test/resources/allure.properties
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License 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.
+#
+
+allure.results.directory=fineract-e2e-tests/fineract-e2e-tests-runner/build/allure-results
diff --git a/fineract-e2e-tests-runner/src/test/resources/cucumber.properties 
b/fineract-e2e-tests-runner/src/test/resources/cucumber.properties
new file mode 100644
index 000000000..d3b2786eb
--- /dev/null
+++ b/fineract-e2e-tests-runner/src/test/resources/cucumber.properties
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License 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.
+#
+
+cucumber.publish.quiet=true
diff --git 
a/fineract-e2e-tests-runner/src/test/resources/features/Client.feature 
b/fineract-e2e-tests-runner/src/test/resources/features/Client.feature
new file mode 100644
index 000000000..2728bd0bd
--- /dev/null
+++ b/fineract-e2e-tests-runner/src/test/resources/features/Client.feature
@@ -0,0 +1,29 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License 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.
+#
+
+@ClientFeature
+Feature: Client
+
+  @TestRailId:C14 @Smoke
+  Scenario Outline: Client creation functionality for Fineract
+    When Admin creates a client with Firstname <firstName> and Lastname 
<lastName>
+    Then Client is created successfully
+    Examples:
+      | firstName    | lastName |
+      | "FirstName1" | "Test1"  |
\ No newline at end of file
diff --git a/fineract-e2e-tests-runner/src/test/resources/logback.xml 
b/fineract-e2e-tests-runner/src/test/resources/logback.xml
new file mode 100644
index 000000000..28e220339
--- /dev/null
+++ b/fineract-e2e-tests-runner/src/test/resources/logback.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License 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.
+
+-->
+<configuration>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - 
%msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="org.apache.fineract.test.messaging.store.EventStore" 
level="DEBUG" />
+    <logger name="org.springframework" level="WARN" />
+
+    <root level="INFO" >
+        <appender-ref ref="STDOUT"/>
+    </root>
+</configuration>
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java
index d842eb55b..222bc0d13 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/Utils.java
@@ -95,9 +95,7 @@ public final class Utils {
     public static final String SOURCE_SET_NUMBERS_AND_LETTERS = 
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     public static final String SOURCE_SET_NUMBERS = "1234567890";
 
-    private Utils() {
-
-    }
+    private Utils() {}
 
     public static void initializeRESTAssured() {
         RestAssured.baseURI = "https://localhost";;
diff --git a/settings.gradle b/settings.gradle
index b9ee5672e..2a37c5397 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -61,6 +61,8 @@ include ':oauth2-tests'
 include ':fineract-client'
 include ':fineract-doc'
 include ':fineract-avro-schemas'
+include ':fineract-e2e-tests-core'
+include ':fineract-e2e-tests-runner'
 // NOTE: custom Docker image with all custom modules included
 include ':custom:docker'
 // NOTE: dynamically load custom modules with pattern "custom -> company -> 
category -> module"

Reply via email to