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

adamsaghy 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 cb7ead208f FINERACT-1724: Document integration and e2e testing in 
fineract
cb7ead208f is described below

commit cb7ead208f05ff8ba8b5dfa5d0712f49d6702791
Author: Attila Budai <[email protected]>
AuthorDate: Tue Sep 30 13:55:46 2025 +0200

    FINERACT-1724: Document integration and e2e testing in fineract
---
 .../src/docs/en/chapters/testing/cucumber.adoc     | 554 +++++++++++++-
 .../src/docs/en/chapters/testing/integration.adoc  | 804 ++++++++++++++++++++-
 2 files changed, 1355 insertions(+), 3 deletions(-)

diff --git a/fineract-doc/src/docs/en/chapters/testing/cucumber.adoc 
b/fineract-doc/src/docs/en/chapters/testing/cucumber.adoc
index 272fc89531..40b63cf900 100644
--- a/fineract-doc/src/docs/en/chapters/testing/cucumber.adoc
+++ b/fineract-doc/src/docs/en/chapters/testing/cucumber.adoc
@@ -1,6 +1,556 @@
 [[testing-cucumber]]
-= Cucumber
+= Cucumber E2E Tests
 
-TBD
+Apache Fineract's E2E test suite provides comprehensive coverage of business 
functionality using Cucumber BDD (Behavior-Driven Development) framework. These 
tests serve as both functional validation and living documentation of the 
system's capabilities.
+
+== Overview
+
+=== Architecture
+
+* *fineract-e2e-tests-runner*: Contains all Cucumber feature files and test 
scenarios
+* *fineract-e2e-tests-core*: Contains step definitions, test utilities, and 
supporting code
+* *Framework*: Cucumber with Java, using Gherkin syntax for readable test 
specifications
+* *Prerequisites*: Running Apache Fineract instance (typically on port 8443 
with HTTPS)
+
+=== Test Organization
+
+* Feature files located in: 
`fineract-e2e-tests-runner/src/test/resources/features/`
+* Step definitions in: 
`fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/`
+* Tests are tagged with TestRail IDs for traceability (e.g., `@TestRailId:C16`)
+* Special tags include `@Smoke` for quick validation tests
+
+== Prerequisites
+
+=== Required Software
+
+* *Java 21*: Apache Fineract requires Java 21 (Azul Zulu JDK recommended)
+* *Database*: MariaDB 11.5.2, PostgreSQL 17.4, or MySQL 9.1
+* *Git*: For source code management
+* *Gradle 8.14.3*: Included via wrapper
+
+=== Database Setup
+
+Before running E2E tests, ensure the databases are created:
+
+[source,bash]
+----
+# Create required databases
+./gradlew createDB -PdbName=fineract_tenants
+./gradlew createDB -PdbName=fineract_default
+----
+
+== Configuration
+
+=== Connection Configuration
+
+E2E tests connect to the running Fineract instance. Default configuration in 
`fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties`:
+
+[source,properties]
+----
+# Connection details to running backend
+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}
+----
+
+To override defaults, use environment variables:
+
+[source,bash]
+----
+export BASE_URL=http://localhost:8080
+export TEST_USERNAME=mifos
+export TEST_PASSWORD=password
+export TEST_TENANT_ID=default
+----
+
+=== Test Data Initialization
+
+IMPORTANT: Many E2E tests require pre-configured test data (loan products, 
charges, configurations). This initialization is controlled by the 
`fineract-test.initialization.enabled` property.
+
+*Default Behavior*:
+
+* By default, initialization is *DISABLED* 
(`fineract-test.initialization.enabled=false`)
+* Without initialization, tests will fail with errors like:
+
+[source]
+----
+java.lang.IllegalArgumentException: Loan product 
[LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL] not found
+----
+
+*How to Enable Initialization*:
+
+Method 1 - Environment Variable (Recommended):
+[source,bash]
+----
+cd fineract-e2e-tests-runner
+INITIALIZATION_ENABLED=true ../gradlew cucumber
+----
+
+Method 2 - System Property:
+[source,bash]
+----
+cd fineract-e2e-tests-runner
+../gradlew cucumber -DINITIALIZATION_ENABLED=true
+----
+
+Method 3 - Modify Properties File:
+Edit 
`fineract-e2e-tests-core/src/test/resources/fineract-test-application.properties`:
+[source,properties]
+----
+fineract-test.initialization.enabled=true
+----
+
+*What Initialization Creates*:
+
+* 100+ loan products with specific configurations
+* Various charge types (NSF fees, processing fees, etc.)
+* Payment allocation rules
+* Interest calculation configurations
+* Advanced payment allocation strategies
+* Progressive loan schedule configurations
+
+*When to Use Initialization*:
+
+* First-time test execution on a fresh database
+* After database reset/recreation
+* When running tests that require specific loan products
+* Testing new features that depend on pre-configured products
+
+NOTE: Initialization takes additional time (2-5 minutes) as it creates 
extensive test data. Consider running it once and reusing the database for 
multiple test runs.
+
+=== Business Date Configuration
+
+CRITICAL: The Business Date feature must be enabled in the database for many 
E2E tests to function correctly.
+
+*Default Behavior*:
+
+* Business Date is *DISABLED* by default in fresh Fineract installations
+* Without Business Date enabled, tests fail with:
+
+[source,json]
+----
+{"errors":[{
+  "defaultUserMessage":"Business date functionality is not enabled",
+  "developerMessage":"Business date functionality is not enabled",
+  "userMessageGlobalisationCode":"business.date.is.not.enabled"
+}]}
+----
+
+*How to Enable Business Date*:
+
+Method 1 - Via SQL (Direct Database):
+[source,bash]
+----
+mysql -u root -pmysql fineract_default -e \
+  "UPDATE c_configuration SET enabled = 1 WHERE name = 'enable-business-date';"
+----
+
+Method 2 - Via API (After Fineract is Running):
+[source,bash]
+----
+curl -X PUT 
https://localhost:8443/fineract-provider/api/v1/configurations/name/enable-business-date
 \
+  -H "Authorization: Basic bWlmb3M6cGFzc3dvcmQ=" \
+  -H "Content-Type: application/json" \
+  -d '{"enabled": true}'
+----
+
+*Verification*:
+[source,bash]
+----
+mysql -u root -pmysql fineract_default -e \
+  "SELECT * FROM c_configuration WHERE name LIKE '%business%';"
+----
+
+== Running E2E Tests
+
+=== Complete Workflow
+
+==== Step 1: Start Fineract
+
+[source,bash]
+----
+# Start Fineract in background
+./gradlew bootRun
+----
+
+Wait for Fineract to be fully started. You can verify by checking:
+[source,bash]
+----
+curl -k https://localhost:8443/actuator/health
+----
+
+==== Step 2: Enable Business Date (if needed)
+
+[source,bash]
+----
+mysql -u root -pmysql fineract_default -e \
+  "UPDATE c_configuration SET enabled = 1 WHERE name = 'enable-business-date';"
+----
+
+==== Step 3: Run E2E Tests
+
+Navigate to the E2E tests module:
+[source,bash]
+----
+cd fineract-e2e-tests-runner
+----
+
+*Run All E2E Tests*:
+[source,bash]
+----
+# First run with initialization
+INITIALIZATION_ENABLED=true ../gradlew cucumber
+
+# Subsequent runs without initialization (faster)
+../gradlew cucumber
+----
+
+*Run Specific Feature File*:
+[source,bash]
+----
+../gradlew cucumber 
-Pcucumber.features="src/test/resources/features/Loan.feature"
+----
+
+*Run Tests by Tag*:
+[source,bash]
+----
+# Run only smoke tests
+../gradlew cucumber -Pcucumber.tags="@Smoke"
+
+# Run specific TestRail test
+../gradlew cucumber -Pcucumber.tags="@TestRailId:C16"
+
+# Run multiple tags
+../gradlew cucumber -Pcucumber.tags="@Smoke and @TestRailId:C16"
+----
+
+*Run Tests with Custom Configuration*:
+[source,bash]
+----
+BASE_URL=http://localhost:8080 \
+TEST_USERNAME=admin \
+TEST_PASSWORD=admin123 \
+INITIALIZATION_ENABLED=true \
+../gradlew cucumber
+----
+
+=== Gradle Command Options
+
+==== Basic Cucumber Task
+
+[source,bash]
+----
+../gradlew cucumber
+----
+
+==== Feature File Selection
+
+[source,bash]
+----
+# Single feature
+../gradlew cucumber 
-Pcucumber.features="src/test/resources/features/Client.feature"
+
+# Multiple features
+../gradlew cucumber 
-Pcucumber.features="src/test/resources/features/Client.feature:src/test/resources/features/Loan.feature"
+
+# Specific scenario by line number
+../gradlew cucumber 
-Pcucumber.features="src/test/resources/features/Loan.feature:45"
+----
+
+==== Tag-Based Execution
+
+[source,bash]
+----
+# Single tag
+../gradlew cucumber -Pcucumber.tags="@Smoke"
+
+# Multiple tags (AND)
+../gradlew cucumber -Pcucumber.tags="@Smoke and @TestRailId:C16"
+
+# Multiple tags (OR)
+../gradlew cucumber -Pcucumber.tags="@Smoke or @TestRailId:C16"
+
+# Exclude tags
+../gradlew cucumber -Pcucumber.tags="not @ignore"
+
+# Complex tag expression
+../gradlew cucumber -Pcucumber.tags="@Smoke and not @ignore"
+----
+
+==== Report Generation
+
+[source,bash]
+----
+# Generate HTML report
+../gradlew cucumber 
-Dcucumber.plugin="pretty,html:build/cucumber-reports/cucumber.html"
+
+# Generate JSON report
+../gradlew cucumber 
-Dcucumber.plugin="json:build/cucumber-reports/cucumber.json"
+
+# Multiple report formats
+../gradlew cucumber 
-Dcucumber.plugin="pretty,html:build/cucumber-reports/cucumber.html,json:build/cucumber-reports/cucumber.json"
+
+# Generate Allure report (comprehensive visual reporting)
+../gradlew cucumber allureReport
+----
+
+After running tests with Allure, the report is available at:
+[source]
+----
+fineract-e2e-tests-runner/build/reports/allure-report/index.html
+----
+
+NOTE: Allure provides rich visual reports with test history, statistics, and 
detailed execution information. Open the `index.html` file in a browser to view 
the interactive report.
+
+==== Clean and Run
+
+[source,bash]
+----
+# Clean previous test results and run
+../gradlew clean cucumber
+----
+
+=== Advanced Execution Scenarios
+
+==== Running Against Different Environment
+
+[source,bash]
+----
+# Against staging environment
+BASE_URL=https://staging.example.com:8443 \
+TEST_USERNAME=staging_user \
+TEST_PASSWORD=staging_pass \
+../gradlew cucumber
+----
+
+==== Running with External Event Verification
+
+[source,bash]
+----
+# Enable external event verification (requires ActiveMQ)
+ACTIVEMQ_BROKER_URL=tcp://localhost:61616 \
+ACTIVEMQ_BROKER_USERNAME=admin \
+ACTIVEMQ_BROKER_PASSWORD=admin \
+ACTIVEMQ_TOPIC_NAME=fineract-events \
+EVENT_VERIFICATION_ENABLED=true \
+../gradlew cucumber
+----
+
+==== Running with TestRail Integration
+
+[source,bash]
+----
+TESTRAIL_ENABLED=true \
+TESTRAIL_BASEURL=https://testrail.example.com \
[email protected] \
+TESTRAIL_PASSWORD=testrail_password \
+TESTRAIL_RUN_ID=123 \
+../gradlew cucumber
+----
+
+== Test Development
+
+=== Feature Coverage
+
+The E2E tests cover the following functional domains:
+
+==== Client Management
+* Client creation and management
+* Address management
+* Document management
+* Family member tracking
+
+==== Loan Management
+* Loan application and approval
+* Disbursement
+* Repayment processing
+* Charges and fees
+* Advanced features: chargeback, charge-off, re-aging, re-amortization
+* Specialized loans: down payment, merchant-issued refund
+
+==== Savings Account Management
+* Account opening and activation
+* Deposits and withdrawals
+* Interest calculation
+* Account closure
+
+==== Accounting
+* Journal entry validation
+* Asset externalization
+* GL account mapping
+
+==== Operational Processes
+* Close of Business (COB)
+* Inline COB
+* Business date management
+* Batch API operations
+
+=== Writing New E2E Tests
+
+When writing new Cucumber tests:
+
+1. *Create Feature File*: Add new `.feature` file in 
`fineract-e2e-tests-runner/src/test/resources/features/`
+
+2. *Use Gherkin Syntax*:
+[source,gherkin]
+----
+Feature: Loan Disbursement
+
+  Scenario: Successful loan disbursement
+    Given A client named "John Doe"
+    When Admin creates a loan for client with amount "1000"
+    And Admin approves the loan
+    And Admin disburses the loan on business date
+    Then Loan status is "Active"
+    And Loan outstanding balance is "1000"
+----
+
+3. *Implement Step Definitions*: Add corresponding step definitions in 
`fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/`
+
+4. *Add Tags*: Tag scenarios appropriately:
+[source,gherkin]
+----
+@TestRailId:C1234 @Smoke
+Scenario: Critical loan test
+----
+
+5. *Verify with Gradle*:
+[source,bash]
+----
+cd fineract-e2e-tests-runner
+../gradlew cucumber 
-Pcucumber.features="src/test/resources/features/YourNewFeature.feature"
+----
+
+== Troubleshooting
+
+=== Common Test Failures
+
+==== Connection Issues
+
+*Symptom*: Tests fail with connection refused errors
+
+*Solutions*:
+[source,bash]
+----
+# Verify Fineract is running
+curl -k https://localhost:8443/actuator/health
+
+# Check if port is in use
+netstat -tulpn | grep 8443
+
+# Check logs (logs go to console/stdout)
+# If running in background, redirect output:
+# ./gradlew bootRun > build/bootRun.log 2>&1 &
+# tail -f build/bootRun.log
+----
+
+==== Business Date Issues
+
+*Symptom*: Tests fail with "Business date functionality is not enabled"
+
+*Solutions*:
+[source,bash]
+----
+# Enable Business Date
+mysql -u root -pmysql fineract_default -e \
+  "UPDATE c_configuration SET enabled = 1 WHERE name = 'enable-business-date';"
+
+# Verify
+mysql -u root -pmysql fineract_default -e \
+  "SELECT * FROM c_configuration WHERE name = 'enable-business-date';"
+----
+
+==== Data Dependencies
+
+*Symptom*: Tests fail due to missing products or charges
+
+*Solutions*:
+[source,bash]
+----
+# Run with initialization enabled
+cd fineract-e2e-tests-runner
+INITIALIZATION_ENABLED=true ../gradlew cucumber
+----
+
+==== Authentication Failures
+
+*Symptom*: 401 or 403 errors
+
+*Solutions*:
+[source,bash]
+----
+# Verify credentials
+TEST_USERNAME=mifos TEST_PASSWORD=password ../gradlew cucumber
+
+# Check user permissions in database
+mysql -u root -pmysql fineract_default -e \
+  "SELECT * FROM m_appuser WHERE username = 'mifos';"
+----
+
+=== Debugging Tips
+
+==== Enable Detailed Logging
+
+[source,bash]
+----
+# Run with verbose output
+../gradlew cucumber -Dcucumber.plugin="pretty" --info
+
+# Save output to file
+../gradlew cucumber > test-output.log 2>&1
+----
+
+==== Check Database State
+
+[source,bash]
+----
+# Check loan products after initialization
+mysql -u root -pmysql fineract_default -e \
+  "SELECT id, product_name FROM m_product_loan LIMIT 20;"
+
+# Check configurations
+mysql -u root -pmysql fineract_default -e \
+  "SELECT name, enabled FROM c_configuration WHERE name LIKE '%enable%';"
+----
+
+==== View Test Reports
+
+After test execution, reports are available in:
+[source]
+----
+fineract-e2e-tests-runner/build/cucumber-reports/
+fineract-e2e-tests-runner/build/reports/tests/
+----
+
+== Best Practices
+
+=== Test Organization
+
+* Keep feature files focused on specific business domains
+* Use descriptive scenario names
+* Include business context in scenario descriptions
+* Tag tests appropriately for organization and execution
+
+=== Test Isolation
+
+* Each test should be independent
+* Don't rely on state from other tests
+* Clean up test data in `@After` hooks
+* Use unique identifiers for test entities
+
+=== Test Data Management
+
+* Use initialization for complex test data setup
+* Create minimal required data in test scenarios
+* Document test data dependencies
+* Reuse database for multiple test runs when possible
+
+=== Performance Optimization
+
+* Run initialization once per database
+* Use tags to run subset of tests during development
+* Run full suite in CI/CD pipelines
+* Consider parallel execution for large test suites
 
 include::cucumber-cheatsheet.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/testing/integration.adoc 
b/fineract-doc/src/docs/en/chapters/testing/integration.adoc
index b802ec0ef6..2df8236d42 100644
--- a/fineract-doc/src/docs/en/chapters/testing/integration.adoc
+++ b/fineract-doc/src/docs/en/chapters/testing/integration.adoc
@@ -1,3 +1,805 @@
 = Integration Testing
 
-TBD
+Integration tests in Apache Fineract validate the complete API layer and 
business logic by making HTTP calls to a running Fineract instance. These tests 
ensure that different components work together correctly and that the API 
behaves as expected.
+
+== Overview
+
+=== Architecture
+
+* *Location*: 
`integration-tests/src/test/java/org/apache/fineract/integrationtests`
+* *Framework*: JUnit 5 with REST Assured for HTTP communication
+* *Base Class*: Most tests extend `BaseLoanIntegrationTest` or 
`IntegrationTest`
+* *Client Library*: Uses Fineract client library for type-safe API interactions
+* *Prerequisites*: Running Apache Fineract instance (default: 
https://localhost:8443)
+
+=== Key Characteristics
+
+* Tests run against a live Fineract instance
+* Validates end-to-end API functionality
+* Tests business logic, validation rules, and workflows
+* Includes accounting verification and data integrity checks
+* Uses real database transactions
+* Tests can be run individually or as a suite
+
+== Prerequisites
+
+=== Required Software
+
+* *Java 21*: Apache Fineract requires Java 21 (Azul Zulu JDK recommended)
+* *Database*: MariaDB 11.5.2, PostgreSQL 17.4, or MySQL 9.1
+* *Git*: For source code management
+* *Gradle 8.14.3*: Included via wrapper
+* *12GB RAM*: Recommended for test execution
+
+=== Database Setup
+
+Before running integration tests, ensure the databases are created:
+
+[source,bash]
+----
+# Create required databases
+./gradlew createDB -PdbName=fineract_tenants
+./gradlew createDB -PdbName=fineract_default
+----
+
+=== Fineract Instance
+
+Integration tests run fineract instance from cargo plugin by default.
+
+== Configuration
+
+=== Default Connection Settings
+
+Integration tests use the following default connection settings:
+
+[source,properties]
+----
+BACKEND_PROTOCOL=https
+BACKEND_HOST=localhost
+BACKEND_PORT=8443
+BACKEND_USERNAME=mifos
+BACKEND_PASSWORD=password
+BACKEND_TENANT=default
+----
+
+=== Override Configuration
+
+To override default values, set environment variables:
+
+[source,bash]
+----
+# Set custom connection details
+export BACKEND_PROTOCOL=http
+export BACKEND_HOST=localhost
+export BACKEND_PORT=8080
+export BACKEND_USERNAME=admin
+export BACKEND_PASSWORD=admin123
+export BACKEND_TENANT=default
+----
+
+== Running Integration Tests
+
+=== Complete Workflow
+
+==== Step 1: Start Fineract
+
+[source,bash]
+----
+# Start Fineract in background
+./gradlew bootRun &
+
+# Wait for startup (manual check)
+curl -k https://localhost:8443/actuator/health
+----
+
+Expected response:
+[source,json]
+----
+{"status":"UP"}
+----
+
+==== Step 2: Run Integration Tests
+
+Navigate to the project root and execute tests:
+
+[source,bash]
+----
+# Run all integration tests
+./gradlew :integration-tests:test
+
+# Run with clean build
+./gradlew clean :integration-tests:test
+----
+
+=== Running Specific Tests
+
+==== Run Single Test Class
+
+[source,bash]
+----
+# Run entire test class
+./gradlew :integration-tests:test --tests ClientLoanIntegrationTest
+
+# Run with verbose output
+./gradlew :integration-tests:test --tests ClientLoanIntegrationTest --info
+----
+
+==== Run Specific Test Method
+
+[source,bash]
+----
+# Run single test method
+./gradlew :integration-tests:test --tests 
ClientLoanIntegrationTest.testLoanSchedule
+
+# Run multiple specific tests
+./gradlew :integration-tests:test --tests 
ClientLoanIntegrationTest.testLoanSchedule \
+  --tests ClientLoanIntegrationTest.testLoanRepayment
+----
+
+==== Run Tests by Pattern
+
+[source,bash]
+----
+# Run all loan-related tests
+./gradlew :integration-tests:test --tests "*Loan*"
+
+# Run all client-related tests
+./gradlew :integration-tests:test --tests "*Client*"
+
+# Run all accounting tests
+./gradlew :integration-tests:test --tests "*Accounting*"
+
+# Run all COB tests
+./gradlew :integration-tests:test --tests "*COB*"
+----
+
+=== Advanced Test Execution
+
+==== Run with Test Filtering
+
+[source,bash]
+----
+# Run tests excluding specific packages
+./gradlew :integration-tests:test --tests "*" \
+  --exclude "*Deprecated*"
+
+# Run only fast tests (custom tag)
+./gradlew :integration-tests:test --tests "*Fast*"
+----
+
+==== Parallel Execution
+
+[source,bash]
+----
+# Run tests in parallel
+./gradlew :integration-tests:test --parallel --max-workers=4
+
+# Set custom thread count
+./gradlew :integration-tests:test --parallel --max-workers=8
+----
+
+WARNING: Some integration tests may have dependencies on shared state. Use 
parallel execution carefully and ensure tests are properly isolated.
+
+==== Run with Custom JVM Arguments
+
+[source,bash]
+----
+# Increase heap size for large test suites
+./gradlew :integration-tests:test -Xmx4g
+
+# Enable debugging
+./gradlew :integration-tests:test --debug-jvm
+----
+
+==== Generate Test Reports
+
+[source,bash]
+----
+# Run tests and generate HTML reports
+./gradlew :integration-tests:test
+
+# Reports are generated at:
+# integration-tests/build/reports/tests/test/index.html
+----
+
+==== Continuous Execution
+
+[source,bash]
+----
+# Watch for changes and re-run tests
+./gradlew :integration-tests:test --continuous
+
+# Run specific test continuously
+./gradlew :integration-tests:test --continuous --tests 
ClientLoanIntegrationTest
+----
+
+=== Test Execution Examples
+
+==== Basic Loan Workflow Test
+
+[source,bash]
+----
+# Test complete loan lifecycle
+./gradlew :integration-tests:test --tests LoanApplicationTest
+----
+
+==== Progressive Loan Tests
+
+[source,bash]
+----
+# Run all progressive loan tests
+./gradlew :integration-tests:test --tests "*Progressive*"
+----
+
+==== Accounting Integration Tests
+
+[source,bash]
+----
+# Run accounting-related tests
+./gradlew :integration-tests:test --tests AccountingScenarioIntegrationTest
+----
+
+==== Business Date Tests
+
+[source,bash]
+----
+# Run business date functionality tests
+./gradlew :integration-tests:test --tests BusinessDateTest
+----
+
+==== Charge-Off Tests
+
+[source,bash]
+----
+# Run charge-off related tests
+./gradlew :integration-tests:test --tests "*ChargeOff*"
+----
+
+== Test Structure
+
+=== BaseLoanIntegrationTest Overview
+
+`BaseLoanIntegrationTest` is the comprehensive base test class for 
loan-related integration tests. It provides:
+
+==== Pre-configured Loan Product Creation
+
+[source,java]
+----
+// Create standard loan products
+createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct()
+create4IProgressive() // Progressive loan products
+create4IProgressiveWithCapitalizedIncome() // With capitalized income
+createOnePeriod30DaysPeriodicAccrualProductWithAdvancedPaymentAllocation()
+----
+
+==== Transaction Management
+
+[source,java]
+----
+// Validate loan transactions
+verifyTransactions(loanId,
+    transaction(100.0, "Disbursement", "01 January 2024"),
+    transaction(50.0, "Repayment", "15 January 2024")
+);
+
+// Verify accounting journal entries
+verifyJournalEntries(loanId, expectedEntries);
+
+// Create transaction test data
+Transaction txn = transaction(amount, type, date);
+----
+
+==== Loan Lifecycle Operations
+
+[source,java]
+----
+// Disburse loan
+disburseLoan(loanId, BigDecimal.valueOf(100), "01 January 2024");
+
+// Undo disbursement
+undoDisbursement(loanId);
+
+// Re-age loan
+reAgeLoan(loanId, reAgeRequest);
+
+// Re-amortize loan
+reAmortizeLoan(loanId, reAmortizeRequest);
+
+// Execute Close of Business
+executeInlineCOB(loanId);
+----
+
+==== Business Date Management
+
+[source,java]
+----
+// Execute code at specific business date
+runAt("01 January 2024", () -> {
+    Long loanId = applyAndApproveProgressiveLoan(...);
+    disburseLoan(loanId, BigDecimal.valueOf(100), "01 January 2024");
+});
+
+// Execute over date range
+runFromToInclusive("01 January 2024", "31 January 2024", () -> {
+    // Operations for each date in the range
+});
+
+// Execute without bypass privileges
+runAsNonByPass(() -> {
+    // Test operations with regular user permissions
+});
+----
+
+==== Verification Methods
+
+[source,java]
+----
+// Validate repayment schedule
+verifyRepaymentSchedule(loanId, expectedSchedule);
+
+// Check loan status
+verifyLoanStatus(loanId, "ACTIVE");
+
+// Verify outstanding amounts
+verifyOutstanding(loanId, expectedOutstanding);
+
+// Check arrears status
+verifyArrears(loanId, expectedArrears);
+----
+
+=== Common Test Patterns
+
+==== Test Setup Pattern
+
+[source,java]
+----
+@BeforeEach
+public void setup() {
+    Utils.initializeRESTAssured();
+    this.requestSpec = new RequestSpecBuilder()
+        .setContentType(ContentType.JSON)
+        .build();
+    this.requestSpec.header("Authorization", "Basic " +
+        Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+    this.responseSpec = new ResponseSpecBuilder()
+        .expectStatusCode(200)
+        .build();
+}
+----
+
+==== Date-Specific Operations
+
+[source,java]
+----
+runAt("01 January 2024", () -> {
+    // Create client
+    Long clientId = clientHelper.createClient(...);
+
+    // Apply for loan
+    Long loanId = applyLoan(clientId, productId, amount);
+
+    // Approve loan
+    approveLoan(loanId, "01 January 2024");
+
+    // Disburse loan
+    disburseLoan(loanId, amount, "01 January 2024");
+});
+----
+
+==== Structured Verification
+
+[source,java]
+----
+// Verify transactions
+verifyTransactions(loanId,
+    transaction(100.0, "Disbursement", "01 January 2024"),
+    transaction(50.0, "Capitalized Income", "01 January 2024"),
+    transaction(0.55, "Capitalized Income Amortization", "01 January 2024")
+);
+
+// Verify journal entries using convenience methods
+verifyJournalEntries(loanId,
+    debit(account.getLoansReceivable(), 100.0),
+    credit(account.getSuspenseClearingAccount(), 100.0)
+);
+
+// Or using full journalEntry method with Account objects
+verifyJournalEntries(loanId,
+    journalEntry(100.0, account.getLoansReceivable(), "DEBIT"),
+    journalEntry(100.0, account.getSuspenseClearingAccount(), "CREDIT")
+);
+----
+
+==== Progressive Loan Testing
+
+[source,java]
+----
+// Create progressive loan product
+Long productId = create4IProgressive();
+
+// Apply and approve
+Long loanId = applyAndApproveProgressiveLoan(clientId, productId,
+    amount, numberOfRepayments, interestRate);
+
+// Test advanced features
+testCapitalizedIncome(loanId);
+testDownPayment(loanId);
+testAdvancedPaymentAllocation(loanId);
+----
+
+== Writing Integration Tests
+
+=== Test Development Guidelines
+
+==== 1. Create Test Class
+
+Create a new test class in 
`integration-tests/src/test/java/org/apache/fineract/integrationtests/`:
+
+[source,java]
+----
+package org.apache.fineract.integrationtests;
+
+import org.apache.fineract.integrationtests.common.Utils;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
+
+public class MyNewFeatureIntegrationTest extends BaseLoanIntegrationTest {
+
+    @BeforeEach
+    public void setup() {
+        Utils.initializeRESTAssured();
+        this.requestSpec = new RequestSpecBuilder()
+            .setContentType(ContentType.JSON)
+            .build();
+        this.requestSpec.header("Authorization", "Basic " +
+            Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+        this.responseSpec = new ResponseSpecBuilder()
+            .expectStatusCode(200)
+            .build();
+    }
+
+    @Test
+    public void testMyNewFeature() {
+        // Test implementation
+    }
+}
+----
+
+==== 2. Use Helper Classes
+
+Leverage existing helper classes:
+
+[source,java]
+----
+// Client operations
+ClientHelper clientHelper = new ClientHelper(requestSpec, responseSpec);
+Long clientId = clientHelper.createClient(...);
+
+// Loan operations
+LoanTransactionHelper loanHelper = new LoanTransactionHelper(requestSpec, 
responseSpec);
+Long loanId = loanHelper.applyLoan(...);
+
+// Account operations
+AccountHelper accountHelper = new AccountHelper(requestSpec, responseSpec);
+
+// Business date operations
+BusinessDateHelper businessDateHelper = new BusinessDateHelper();
+businessDateHelper.updateBusinessDate(...);
+
+// COB operations
+InlineLoanCOBHelper cobHelper = new InlineLoanCOBHelper(requestSpec, 
responseSpec);
+cobHelper.executeInlineCOB(loanId);
+----
+
+==== 3. Follow Best Practices
+
+* *Self-Contained Tests*: Each test should be independent
+* *Clear Setup*: Use `@BeforeEach` for test initialization
+* *Date Management*: Use `runAt()` for consistent date-based testing
+* *Comprehensive Verification*: Verify transactions, schedules, and accounting
+* *Helper Methods*: Use provided helper classes rather than direct API calls
+* *Error Testing*: Test both positive and negative scenarios
+* *Cleanup*: Clean up test data when necessary
+
+==== 4. Test Complex Scenarios
+
+[source,java]
+----
+@Test
+public void testLoanWithMultipleDisbursements() {
+    runAt("01 January 2024", () -> {
+        // Create client
+        Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
+
+        // Create multi-disbursement loan product
+        Long productId = createMultiDisbursementProduct();
+
+        // Apply for loan
+        Long loanId = applyAndApproveProgressiveLoan(clientId, productId,
+            BigDecimal.valueOf(1000), 12, BigDecimal.valueOf(10));
+
+        // First disbursement
+        disburseLoan(loanId, BigDecimal.valueOf(500), "01 January 2024");
+
+        // Verify first disbursement
+        verifyTransactions(loanId,
+            transaction(500.0, "Disbursement", "01 January 2024")
+        );
+    });
+
+    runAt("15 January 2024", () -> {
+        // Second disbursement
+        disburseLoan(loanId, BigDecimal.valueOf(500), "15 January 2024");
+
+        // Verify both disbursements
+        verifyTransactions(loanId,
+            transaction(500.0, "Disbursement", "01 January 2024"),
+            transaction(500.0, "Disbursement", "15 January 2024")
+        );
+
+        // Verify outstanding balance
+        verifyOutstanding(loanId, BigDecimal.valueOf(1000));
+    });
+}
+----
+
+==== 5. Run and Verify
+
+[source,bash]
+----
+# Run your new test
+./gradlew :integration-tests:test --tests MyNewFeatureIntegrationTest
+
+# Run with verbose output for debugging
+./gradlew :integration-tests:test --tests MyNewFeatureIntegrationTest --info
+
+# Run specific test method
+./gradlew :integration-tests:test --tests 
MyNewFeatureIntegrationTest.testMyNewFeature
+----
+
+== Troubleshooting
+
+=== Common Test Failures
+
+==== Connection Issues
+
+*Symptom*: Tests fail with connection refused errors
+
+*Solutions*:
+[source,bash]
+----
+# Verify Fineract is running
+curl -k https://localhost:8443/actuator/health
+
+# Check if port is available
+netstat -tulpn | grep 8443
+
+# Check Fineract logs (logs go to console/stdout)
+# If running in background with output redirection:
+# tail -f build/bootRun.log
+
+# Restart Fineract if needed
+pkill -f bootRun
+./gradlew bootRun &
+----
+
+==== Authentication Failures
+
+*Symptom*: Tests fail with 401 or 403 errors
+
+*Solutions*:
+[source,bash]
+----
+# Check default credentials
+mysql -u root -pmysql fineract_default -e \
+  "SELECT username, password FROM m_appuser WHERE username = 'mifos';"
+
+# Reset credentials if needed
+mysql -u root -pmysql fineract_default -e \
+  "UPDATE m_appuser SET password = '5jdQ3dNQXHPzCuBbZVdQZ2XnVlPc3l2l' \
+   WHERE username = 'mifos';"
+
+# Verify connection settings
+echo "Protocol: ${BACKEND_PROTOCOL:-https}"
+echo "Host: ${BACKEND_HOST:-localhost}"
+echo "Port: ${BACKEND_PORT:-8443}"
+----
+
+==== Data Inconsistency
+
+*Symptom*: Tests fail due to unexpected data state
+
+*Solutions*:
+[source,bash]
+----
+# Reset database
+mysql -u root -pmysql -e "DROP DATABASE fineract_default;"
+mysql -u root -pmysql -e "DROP DATABASE fineract_tenants;"
+
+# Recreate databases
+./gradlew createDB -PdbName=fineract_tenants
+./gradlew createDB -PdbName=fineract_default
+
+# Restart Fineract
+pkill -f bootRun
+./gradlew bootRun &
+----
+
+==== Test Timeout
+
+*Symptom*: Tests hang or timeout
+
+*Solutions*:
+[source,bash]
+----
+# Increase test timeout
+./gradlew :integration-tests:test -Dtest.timeout=600
+
+# Check for database locks
+mysql -u root -pmysql fineract_default -e "SHOW PROCESSLIST;"
+
+# Kill long-running queries
+mysql -u root -pmysql fineract_default -e "KILL <process_id>;"
+----
+
+==== Memory Issues
+
+*Symptom*: OutOfMemoryError during test execution
+
+*Solutions*:
+[source,bash]
+----
+# Increase heap size
+./gradlew :integration-tests:test -Xmx4g -Xms2g
+
+# Run fewer tests in parallel
+./gradlew :integration-tests:test --max-workers=2
+
+# Clean build directory
+./gradlew clean
+----
+
+=== Debugging Tips
+
+==== Enable Detailed Logging
+
+[source,bash]
+----
+# Run with debug output
+./gradlew :integration-tests:test --debug
+
+# Run with info level
+./gradlew :integration-tests:test --info
+
+# Save output to file
+./gradlew :integration-tests:test --info > test-output.log 2>&1
+----
+
+==== Check Test Reports
+
+After test execution, detailed reports are available:
+
+[source]
+----
+# HTML report
+integration-tests/build/reports/tests/test/index.html
+
+# XML reports (for CI/CD)
+integration-tests/build/test-results/test/
+
+# Gradle scan (upload for detailed analysis)
+----
+
+Generate Gradle build scan:
+[source,bash]
+----
+./gradlew :integration-tests:test --scan
+----
+
+==== Database State Verification
+
+[source,bash]
+----
+# Check loan status
+mysql -u root -pmysql fineract_default -e \
+  "SELECT id, account_no, loan_status_id, principal_amount \
+   FROM m_loan ORDER BY id DESC LIMIT 10;"
+
+# Check transactions
+mysql -u root -pmysql fineract_default -e \
+  "SELECT loan_id, transaction_type_enum, amount, transaction_date \
+   FROM m_loan_transaction WHERE loan_id = <loan_id>;"
+
+# Check journal entries
+mysql -u root -pmysql fineract_default -e \
+  "SELECT entry_date, account_id, type_enum, amount \
+   FROM acc_gl_journal_entry WHERE loan_id = <loan_id>;"
+
+# Check configurations
+mysql -u root -pmysql fineract_default -e \
+  "SELECT name, enabled FROM c_configuration \
+   WHERE name LIKE '%business%' OR name LIKE '%enable%';"
+----
+
+==== API Response Debugging
+
+Add logging to test methods:
+
+[source,java]
+----
+Response response = loanHelper.applyLoan(...);
+System.out.println("Response: " + response.asString());
+System.out.println("Status Code: " + response.getStatusCode());
+
+// Or use logger
+log.info("Response: {}", response.asString());
+----
+
+==== Isolate Failing Tests
+
+[source,bash]
+----
+# Run only the failing test
+./gradlew :integration-tests:test --tests FailingTest --info
+
+# Run with rerun-tasks option
+./gradlew :integration-tests:test --tests FailingTest --rerun-tasks
+
+# Run with fail-fast to stop on first failure
+./gradlew :integration-tests:test --fail-fast
+----
+
+== Best Practices
+
+=== Test Organization
+
+* Extend appropriate base classes (`BaseLoanIntegrationTest`, 
`IntegrationTest`)
+* Use descriptive test method names that explain what is being tested
+* Group related tests in the same test class
+* Use `@BeforeEach` for setup and `@AfterEach` for cleanup
+* Follow existing naming conventions
+
+=== Test Isolation
+
+* Each test should be independent and not rely on other tests
+* Create fresh test data for each test
+* Clean up test data after test execution
+* Use unique identifiers to avoid conflicts
+* Don't share mutable state between tests
+
+=== Performance Optimization
+
+* Reuse Fineract instance across test runs
+* Use `runAt()` for efficient date management
+* Minimize unnecessary API calls
+* Use bulk operations when appropriate
+* Consider parallel execution for independent tests
+* Run subset of tests during development
+
+=== Code Quality
+
+* Follow existing code patterns and conventions
+* Use helper methods instead of duplicating code
+* Add comments for complex business logic
+* Verify both positive and negative scenarios
+* Include edge cases in test coverage
+* Document test assumptions and prerequisites
+
+=== Comprehensive Verification
+
+* Always verify transaction creation
+* Check accounting journal entries
+* Validate repayment schedules
+* Verify loan status transitions
+* Test charge applications
+* Validate business date handling
+* Check error messages for validation failures
+
+=== Maintenance
+
+* Update tests when API changes
+* Remove deprecated test methods
+* Keep test data realistic
+* Document complex test scenarios
+* Review and refactor tests regularly
+* Keep tests aligned with current best practices


Reply via email to