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: