Skip to content

Testing & Quality Assurance ​

Comprehensive testing infrastructure for HANA CLI with over 1400 tests covering utilities, routes, and CLI integration.

Overview ​

This document describes the unit tests and integration tests that provide comprehensive coverage for:

  • Utility functions in /utils
  • Route handlers in /routes
  • CLI command integration
  • Cross-platform compatibility
  • HTTP API endpoints
  • WebSocket communication
  • End-to-end (E2E) command-line workflows
  • SAPUI5 user interface automation

Total Tests: 1500+ ​

  • Utils Tests: 438+ - Core utilities and helper functions
  • Routes Tests: 368+ - HTTP routes and API endpoints
  • CLI Integration Tests: 200+ - Command-line interface
  • HTTP Integration Tests: 128+ - HTTP request/response handling
  • Cross-Platform Tests: 165+ - Windows, Linux, macOS support
  • E2E Tests: 35 test files - End-to-end command execution workflows
  • UI Tests: 3 test files - SAPUI5 interface automation with WDI5

Test Execution Time ​

  • Unit & Integration Tests: ~25-35 minutes
  • E2E Tests: ~5-10 minutes (requires local connection)
  • UI Tests: ~2-5 minutes per test (requires server + Chrome)

Utilities Tests ​

Tests for utility functions in /utils folder covering database, connection, inspection, and CLI integration utilities.

Key Test Files ​

sqlInjection.Test.js - 40 tests Tests for SQL injection protection utilities covering whitespace handling, parameter validation, and quote escaping.

locale.Test.js - 8 tests Tests for locale detection with environment variable priority handling.

versionCheck.Test.js - 3 tests Tests for Node.js version validation.

base.Test.js - 33 tests Tests for core base utility functions including debug flag detection, GUI mode, command builders, and prompt schema generation.

database.Test.js - 14 tests Tests for database client class covering constructor initialization, wildcard conversion, and schema calculation.

connections.Test.js - 60+ tests Tests for connection management covering file discovery, environment detection, and connection creation from various sources.

dbInspect.Test.js - 85+ tests
Tests for database inspection and metadata retrieval including version detection, calculation view identification, and object definition retrieval.

btp.Test.js - 45+ tests Tests for BTP CLI interaction utilities covering version detection, info parsing, configuration reading, and target hierarchy.

cf.Test.js - 50+ tests Tests for Cloud Foundry CLI interaction including org/space management and HANA instance discovery.

xs.Test.js - 60+ tests Tests for XSA CLI interaction covering configuration parsing and service discovery.

massConvert.Test.js - 40+ tests Tests for mass conversion utility module structure and export validation.

profileIntegration.Test.js - 70+ tests Integration tests for PostgreSQL and SQLite profile functionality with actual database client behavior.

Routes Tests ​

Tests for HTTP route handlers and API endpoints accessed through the web server.

Route Test Files (HTTP Endpoints) ​

index.Test.js - 30 tests (enhanced) Integration tests for the index route handler covering GET and PUT operations with mocked HTTP requests/responses.

hanaList.Test.js - 50+ tests (enhanced) Integration tests for HANA list routes covering route registration and path validation.

docs.Test.js - 45 tests Integration tests for documentation routes (README, changelog) with markdown to HTML conversion.

hanaInspect.Test.js - 55 tests Integration tests for HANA inspect routes covering table and view inspection operations.

webSocket.Test.js - 40 tests Integration tests for WebSocket routes and HTTP endpoints.

webSocket.e2e.Test.js - 60+ tests End-to-end tests for WebSocket real-time communication with real client-server interaction.

excel.Test.js - 17 tests Integration tests for Excel export routes (currently disabled with 503 status).

dfa.Test.js - 53 tests Integration tests for Digital Foundation Adapter routes with catalogue and context help.

static.Test.js - 38 tests Integration tests for static file serving and Fiori sandbox configuration.

HTTP Integration Tests (with supertest) ​

Additional HTTP integration tests for full end-to-end request/response validation:

  • index.http.Test.js - 17 tests
  • docs.http.Test.js - 26 tests
  • static.http.Test.js - 32 tests
  • fullApp.http.Test.js - 53 tests

CLI Integration Tests ​

CLI Flag Integration Tests ​

genericFlags.Test.js - 200+ tests ​

Comprehensive cross-command integration tests for generic CLI flags tested across 60+ commands:

  • --debug / --Debug - Enables debug output
  • --quiet / --disableVerbose - Suppresses verbose output
  • --help / -h - Displays command help
  • --admin / -a - Uses admin connection
  • --conn - Specifies connection file

Commands Tested: Database commands, inspect commands, HDI commands, system queries, cloud instances, utilities, connections, and BTP commands.

errorHandling.Test.js - 30+ tests ​

Error handling validation for invalid parameters, connection errors, SQL injection prevention, and special character handling.

flagValidation.Test.js - 40+ tests ​

Command-line flag validation covering limit values, schema/table names, output formats, and boolean flags.

outputFormats.Test.js - 25+ tests ​

Output format validation for SQL, JSON, YAML, CDS, CDL, EDMX, OpenAPI, GraphQL, and database-specific formats.

commandAliases.Test.js - 30+ tests ​

Command alias testing ensuring all aliases work identically to main commands.

edgeCases.Test.js - 50+ tests ​

Edge case and boundary condition testing for empty results, wildcards, special characters, Unicode, case sensitivity, and concurrent execution.

tableOutput.Test.js - 20 tests ​

Unit tests for table output enhancements covering column width management, pagination, and type-aware formatting.

querySimple.Test.js - 8 tests (enhanced) ​

Integration tests for querySimple command with table format output and file export validation.

typeAwareFormatting.Test.js - 20 tests ​

Type-aware formatting tests for dates, numbers, text, and NULL values in text exports.

End-to-End (E2E) CLI Tests ​

End-to-end tests validate complete command-line workflows using subprocess execution. These tests focus on CLI behavior, not unit testing.

Purpose ​

E2E tests verify:

  • Command Execution: Commands run successfully from the command line
  • Help Text: --help displays correct information
  • Server Startup: UI commands start web servers without errors
  • Flag Handling: Command flags are parsed correctly
  • Output Validation: Command output matches expected format
  • Alias Support: Command aliases work identically to main commands
  • Error Messages: Invalid inputs produce helpful error messages

Test Location ​

text
tests/e2e/
├── backup.e2e.Test.js              # Backup command E2E tests
├── cds.e2e.Test.js                 # CDS command tests
├── compareData.e2e.Test.js         # Data comparison workflow
├── compareSchema.e2e.Test.js       # Schema comparison workflow
├── connect.e2e.Test.js             # Connection establishment
├── dataProfile.e2e.Test.js         # Data profiling workflow
├── dataValidator.e2e.Test.js       # Data validation workflow
├── duplicateDetection.e2e.Test.js  # Duplicate detection workflow
├── export.e2e.Test.js              # Export command workflow
├── import.e2e.Test.js              # Import command workflow
├── indexes.e2e.Test.js             # Index inspection
├── massExport.e2e.Test.js          # Mass export workflow
├── querySimple.e2e.Test.js         # Simple query execution
├── restore.e2e.Test.js             # Restore command workflow
├── schemas.e2e.Test.js             # Schema listing
├── status.e2e.Test.js              # System status
├── systemInfo.e2e.Test.js          # System information
├── tableCopy.e2e.Test.js           # Table copy workflow
├── tables.e2e.Test.js              # Table listing
├── version.e2e.Test.js             # Version command
├── containersUI.e2e.Test.js        # Containers UI command
├── dataTypesUI.e2e.Test.js         # Data Types UI command
├── featuresUI.e2e.Test.js          # Features UI command
├── featureUsageUI.e2e.Test.js      # Feature Usage UI command
├── functionsUI.e2e.Test.js         # Functions UI command
├── importUI.e2e.Test.js            # Import UI command
├── inspectTableUI.e2e.Test.js      # Inspect Table UI command
├── massConvertUI.e2e.Test.js       # Mass Convert UI command
├── systemInfoUI.e2e.Test.js        # System Info UI command
├── tablesUI.e2e.Test.js            # Tables UI command
└── routes/
    └── webSocket.e2e.Test.js       # WebSocket E2E tests

E2E Test Structure ​

E2E tests follow a consistent pattern:

javascript
import * as base from '../base.js'
import { expect } from 'chai'

describe('commandName - E2E Tests', function () {
  this.timeout(20000)

  describe('Help output', () => {
    it('shows help with --help flag', function (done) {
      base.exec('node bin/cli.js commandName --help', (error, stdout) => {
        expect(error).to.be.null
        expect(stdout).to.include('hana-cli commandName')
        expect(stdout).to.include('Options:')
        done()
      })
    })
  })

  describe('Command execution', () => {
    it('runs command successfully', function (done) {
      base.exec('node bin/cli.js commandName', (error, stdout) => {
        expect(error).to.be.null
        expect(stdout).to.not.be.empty
        done()
      })
    })
  })
})

Running E2E Tests ​

bash
# Run all E2E tests
npm run test:e2e

# Run specific E2E test file
npx mocha tests/e2e/tables.e2e.Test.js --config=tests/.mocharc.e2e.json

# Run E2E tests matching a pattern
npm run test:e2e:grep "systemInfo"

# Run E2E tests in strict mode (no pending tests)
npm run test:e2e:strict

E2E Configuration ​

Configuration in tests/.mocharc.e2e.json:

json
{
  "timeout": "20s",
  "slow": "5s",
  "parallel": true,
  "jobs": 16,
  "reporter": "spec",
  "exit": true
}
javascript

**Parallel Execution**: E2E tests run in parallel (16 jobs) for faster execution

**CI Awareness**: E2E tests are skipped in CI environments (require local database connections)

**Live Test Gating**: Helper functions control whether tests require live connections:

```javascript
import { getLiveTestControl, gateLiveTestInCI } from './helpers.js'

describe('Live database tests', function () {
before(function() {
  gateLiveTestInCI(this)  // Skip in CI
})
})

Connection Helpers: Utility functions provide connection credentials:

javascript
import { getLocalConnectionCredentials } from './helpers.js'

const credentials = getLocalConnectionCredentials()
// Returns: { host, port, user, password, schema }

E2E vs Unit Tests ​

AspectE2E TestsUnit Tests
ExecutionSubprocess (child_process)Direct function calls
ScopeFull command workflowIndividual functions
SpeedSlower (~seconds per test)Faster (~milliseconds)
DependenciesRequires complete CLI setupMocked dependencies
PurposeValidate user experienceValidate logic

UI Command E2E Tests ​

UI commands (e.g., tablesUI, systemInfoUI) have E2E tests that validate:

Important: E2E tests for UI commands do NOT test the actual SAPUI5 interface. Use WDI5 UI tests for that (see next section).

UI Automation Tests with WDI5 ​

WDI5 (WebDriver for UI5) tests validate the actual SAPUI5 user interface behavior through browser automation.

What UI Tests Validate ​

UI tests verify:

UI Test File Structure ​

text
tests/ui/
├── README.md                   # UI test documentation
├── global.d.ts                 # TypeScript definitions
├── tsconfig.json               # TypeScript config for UI tests
├── importUI.ui.test.js         # Import interface tests
├── systemInfoUI.ui.test.js     # System Info interface tests
└── tablesUI.ui.test.js         # Tables interface tests

WDI5 Test Structure ​

javascript
// @ts-check
/// <reference types="@wdio/globals/types" />

describe('TablesUI - SAPUI5 Interface Tests', function() {
  this.timeout(60000)

  const BASE_URL = 'http://localhost:3010'
  const UI_PATH = '/ui/tables/index.html'

  before(async function() {
    await browser.url(BASE_URL + UI_PATH)
    await browser.waitForUI5()
  })
  
  describe('Page Structure', () => {
    it('should load the tables UI page', async () => {
      const title = await browser.getTitle()
      expect(title).toContain('Tables')
    })
  })
  
  describe('UI Controls', () => {
    it('should display the tables table control', async () => {
      const table = await browser.asControl({
        selector: {
          controlType: 'sap.m.Table',
          viewName: 'sap.hanacli.tables.view.App'
        }
      })
      await expect(table).toBeDefined()
    })
  })
})

Prerequisites for UI Tests ​

1. Install WDI5 Dependencies ​

bash
npm install --save-dev @wdio/cli@9 @wdio/local-runner@9 @wdio/mocha-framework@9 @wdio/spec-reporter@9 @wdio/globals@9 wdio-ui5-service@3 wdio-chromedriver-service@8 webdriverio@9 --legacy-peer-deps

Note:

  • WebdriverIO v9 is required for wdio-ui5-service v3
  • --legacy-peer-deps flag handles peer dependency conflicts

2. Verify Chrome Installation ​

bash
# Windows
where chrome

# macOS/Linux
which google-chrome

Install Chrome if needed:

3. Start the HANA CLI Server ​

UI tests require the server to be running:

bash
# Start a UI command (keeps server running)
node bin/cli.js tablesUI --port 8080

Leave this terminal open while running tests.

Running UI Tests ​

bash
# Run all UI tests (headless Chrome)
npm run test:ui

# Run specific UI test file
npm run test:ui:single tests/ui/tablesUI.ui.test.js

# Run in debug mode (visible browser)
npm run test:ui:debug

UI Test Configuration ​

Configuration in wdio.conf.js:

  • Port: 3010 (default server port for tests)
  • Browser: Chrome (headless by default)
  • Framework: Mocha
  • Services: wdio-ui5-service (SAPUI5 integration)
  • Timeout: 60 seconds for UI5 initialization

E2E vs UI Tests Comparison ​

Test TypeLocationWhat it TestsToolsBrowser?Server?
E2E CLItests/e2e/Command execution, help, server startupMocha, Node exec❌ No❌ No
UI Teststests/ui/SAPUI5 interface interactionWDI5, WebdriverIO✅ Yes (Chrome)✅ Yes (port 8080)

Troubleshooting UI Tests ​

TypeScript Errors (Safe to Ignore) ​

TypeScript may show errors in UI test files. These are safe to ignore and don't affect test execution.

Common errors (expected):

text
- Object literal may only specify known properties
- Property 'require' does not exist on type 'typeof ui'
- Parameter implicitly has an 'any' type

Why: WDI5 and SAPUI5 have incomplete TypeScript definitions.

Optional fix: Remove // @ts-check from test files to disable TypeScript checking.

Connection Refused / ECONNREFUSED ​

Problem: Server is not running

Solution: Start the server first:

bash
node bin/cli.js tablesUI --port 8080

UI5 Framework Did Not Initialize ​

Problem: SAPUI5 took too long to load

Solution: Increase timeout in wdio.conf.js:

javascript
waitforTimeout: 60000,  // Increase from 30000

ChromeDriver Version Mismatch ​

Problem: ChromeDriver version doesn't match Chrome

Solution: Update Chrome or ChromeDriver:

bash
# Update Chrome (recommended)
# Chrome menu → About Google Chrome → Auto-updates

# OR update ChromeDriver
npm install --save-dev chromedriver --legacy-peer-deps

Cannot Find Control ​

Problem: Control selector is incorrect

Solution:

  1. Check viewName matches your SAPUI5 component
  2. Verify controlType spelling (case-sensitive)
  3. Use browser dev tools to inspect DOM

Tests Pass But Nothing Visible ​

Problem: Tests run in headless mode by default

Solution: Use debug mode:

bash
npm run test:ui:debug

Or edit wdio.conf.js and remove --headless from Chrome args.

UI Test Best Practices ​

  1. Wait for UI5: Always use await browser.waitForUI5() before interactions
  2. Use Control Selectors: Prefer browser.asControl() over DOM selectors
  3. Descriptive Names: Test names should describe user behavior
  4. Independent Tests: Each test should work in isolation
  5. Cleanup: Reset state between tests if needed
  6. Timeouts: Set reasonable timeouts for slow-loading UIs

Writing New UI Tests ​

When adding new SAPUI5 interfaces:

  1. Create E2E test first (in tests/e2e/) - validates command execution
  2. Create UI test (in tests/ui/) - validates actual UI behavior
  3. Test core workflows - focus on critical user paths
  4. Test error cases - validate error messages display
  5. Test data loading - ensure data binds correctly to controls
  6. Test interactions - validate clicks, navigation, input

Example:

javascript
// tests/e2e/newCommandUI.e2e.Test.js
describe('newCommandUI - E2E Tests', function () {
  it('starts server successfully', function (done) {
    base.exec('node bin/cli.js newCommandUI --help', (error, stdout) => {
      expect(error).to.be.null
      done()
    })
  })
})

// tests/ui/newCommandUI.ui.test.js
describe('NewCommandUI - SAPUI5 Tests', function() {
  it('should display the main table', async () => {
    const table = await browser.asControl({
      selector: { controlType: 'sap.m.Table' }
    })
    await expect(table).toBeDefined()
  })
})

Additional Resources ​

Test Framework ​

Test Runner: Mocha
Assertion Library: Node.js built-in assert
Reporter: Mochawesome (generates HTML reports)
Configuration: tests/.mocharc.json

Running Tests ​

Run All Tests ​

bash
npm test

Run Specific Test Suites ​

bash
# Utils tests only
npm run test:utils

# Routes tests only  
npm run test:routes

# CLI tests only
npm run test:cli

# Generic flags tests
npm test tests/genericFlags.Test.js

Run Specific Test Files ​

bash
# Database utilities
npm test tests/utils/database.Test.js

# Connection utilities
npm test tests/utils/connections.Test.js

# Route integration
npm test tests/routes/index.Test.js

# WebSocket end-to-end
npm test tests/e2e/routes/webSocket.e2e.Test.js

Run HTTP Integration Tests ​

bash
# All HTTP tests
npm test tests/routes/*.http.Test.js

# Specific HTTP test
npm test tests/routes/index.http.Test.js

Test Reports ​

After running tests, Mochawesome generates HTML reports in:

bash
mochawesome-report/test-report_XXX.html

Open in a browser for detailed results with pass/fail statistics and execution times.

Code Coverage ​

The project uses nyc (Istanbul) for code coverage reporting.

Running Coverage Reports ​

bash
# Run all tests with coverage
npm run coverage

# Run specific suites with coverage
npm run coverage:cli
npm run coverage:utils
npm run coverage:routes

# Check coverage meets thresholds
npm run coverage:check

Coverage Configuration ​

Coverage settings in .nycrc.json:

  • Lines: 80% target
  • Statements: 80% target
  • Functions: 80% target
  • Branches: 80% target

HTML coverage reports generated in ./coverage/index.html

Cross-Platform Testing ​

Tests validate behavior across Windows, Linux, and macOS:

  • Path handling with platform-specific separators
  • Environment variable detection
  • Platform-specific config paths
  • Line ending management (LF vs CRLF)
  • ES module compatibility

Test Organization ​

bash
describe('Feature @all', () => {
  // Runs on all platforms
})

describe('Windows Paths @windows', () => {
  if (process.platform !== 'win32') this.skip()
  // Windows-only tests
})

CI/CD Integration ​

GitHub Actions runs full test suite on:

  • Operating Systems: Ubuntu, Windows, macOS
  • Node.js Versions: 20.x, 22.x, 24.x

Testing Best Practices ​

Unit Tests ​

  • Focus on pure function testing
  • Cover edge cases and error conditions
  • Validate input/output contracts
  • Test both success and failure paths

Integration Tests ​

  • Test route registration and structure
  • Validate HTTP request/response handling
  • Test error propagation through middleware
  • Test mocked database connections

CLI Tests ​

  • Execute actual CLI commands as subprocess
  • Validate flag parsing and behavior
  • Ensure consistent behavior across commands
  • Test cross-command consistency

End-to-End Tests ​

  • Test complete workflows
  • Real network communication (WebSocket tests)
  • Concurrent execution scenarios
  • Performance under load

Writing New Tests ​

When adding new features:

  1. Add unit tests for utility functions
  2. Add integration tests for route handlers
  3. Add CLI tests for commands
  4. Test error cases and edge conditions
  5. Test cross-command consistency
  6. Validate output formats
  7. Test flag combinations

Test Development Guidelines ​

When writing tests, follow these patterns:

  1. Clear Test Names: Describe what is being tested
  2. Arrange-Act-Assert: Organize test logic clearly
  3. Single Responsibility: Test one thing per test
  4. Error Path Testing: Include failure scenarios
  5. Mocked Dependencies: Mock external systems
  6. Isolated Tests: Tests should run independently

Debugging Tests ​

Run with Debug Output ​

bash
npm test -- --reporter spec tests/targetTest.js
javascript
console.log('Debug info:', variable)

Inspect Specific Test ​

Add .only() to run single test:

javascript
it.only('should test this', () => {
  // Only this test runs
})

See Also: