UNPKG

hana-cli

Version:
792 lines (553 loc) 22.8 kB
# 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 | Aspect | E2E Tests | Unit Tests | |--------|-----------|------------| | **Execution** | Subprocess (child_process) | Direct function calls | | **Scope** | Full command workflow | Individual functions | | **Speed** | Slower (~seconds per test) | Faster (~milliseconds) | | **Dependencies** | Requires complete CLI setup | Mocked dependencies | | **Purpose** | Validate user experience | Validate 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: - **Windows**: <https://www.google.com/chrome/> - **macOS**: `brew install --cask google-chrome` - **Linux**: `sudo apt-get install google-chrome-stable` #### 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 Type | Location | What it Tests | Tools | Browser? | Server? | |-----------|----------|---------------|-------|----------|---------| | **E2E CLI** | `tests/e2e/` | Command execution, help, server startup | Mocha, Node exec | ❌ No | ❌ No | | **UI Tests** | `tests/ui/` | SAPUI5 interface interaction | WDI5, 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 - **WDI5 Documentation**: <https://ui5-community.github.io/wdi5/> - **WebdriverIO Docs**: <https://webdriver.io/> - **SAPUI5 Test Automation**: <https://ui5.sap.com/#/topic/ae448243822448d8ba04b4784f4b09a0> - **WDI5 Setup Guide**: See [WDI5-SETUP.md](../../WDI5-SETUP.md) in project root ## 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 ``` ### Print Debug Info ```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: - [Development Guide](./index.md) - [Architecture](./architecture/) - [Troubleshooting](../../troubleshooting/)