354 lines
10 KiB
Markdown
354 lines
10 KiB
Markdown
# @gitzone/tstest
|
|
🧪 **A powerful, modern test runner for TypeScript** - making your test runs beautiful and informative!
|
|
|
|
## Availabililty and Links
|
|
* [npmjs.org (npm package)](https://www.npmjs.com/package/@gitzone/tstest)
|
|
* [code.foss.global (source)](https://code.foss.global/gitzone/tstest)
|
|
|
|
## Why tstest?
|
|
|
|
**tstest** is a TypeScript test runner that makes testing delightful. It's designed for modern development workflows with beautiful output, flexible test execution, and powerful features that make debugging a breeze.
|
|
|
|
### ✨ Key Features
|
|
|
|
- 🎯 **Smart Test Execution** - Run all tests, single files, or use glob patterns
|
|
- 🎨 **Beautiful Output** - Color-coded results with emojis and clean formatting
|
|
- 📊 **Multiple Output Modes** - Choose from normal, quiet, verbose, or JSON output
|
|
- 🔍 **Automatic Discovery** - Finds all your test files automatically
|
|
- 🌐 **Cross-Environment** - Supports Node.js and browser testing
|
|
- 📝 **Detailed Logging** - Optional file logging for debugging
|
|
- ⚡ **Performance Metrics** - See which tests are slow
|
|
- 🤖 **CI/CD Ready** - JSON output mode for automation
|
|
- 🏷️ **Tag-based Filtering** - Run only tests with specific tags
|
|
- 🎯 **Parallel Test Execution** - Run tests in parallel groups
|
|
- 🔧 **Test Lifecycle Hooks** - beforeEach/afterEach support
|
|
- 📸 **Snapshot Testing** - Compare test outputs with saved snapshots
|
|
- ⏳ **Timeout Control** - Set custom timeouts for tests
|
|
- 🔁 **Retry Logic** - Automatically retry failing tests
|
|
- 🛠️ **Test Fixtures** - Create reusable test data
|
|
- 📦 **Browser-Compatible** - Full browser support with embedded tapbundle
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
npm install --save-dev @gitzone/tstest
|
|
# or with pnpm
|
|
pnpm add -D @gitzone/tstest
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Basic Test Execution
|
|
|
|
```bash
|
|
# Run all tests in a directory
|
|
tstest test/
|
|
|
|
# Run a specific test file
|
|
tstest test/test.mycomponent.ts
|
|
|
|
# Use glob patterns
|
|
tstest "test/**/*.spec.ts"
|
|
tstest "test/unit/*.ts"
|
|
```
|
|
|
|
### Execution Modes
|
|
|
|
**tstest** intelligently detects how you want to run your tests:
|
|
|
|
1. **Directory mode** - Recursively finds all test files
|
|
2. **File mode** - Runs a single test file
|
|
3. **Glob mode** - Uses pattern matching for flexible test selection
|
|
|
|
### Command Line Options
|
|
|
|
| Option | Description |
|
|
|--------|-------------|
|
|
| `--quiet`, `-q` | Minimal output - perfect for CI environments |
|
|
| `--verbose`, `-v` | Show all console output from tests |
|
|
| `--no-color` | Disable colored output |
|
|
| `--json` | Output results as JSON |
|
|
| `--logfile` | Save detailed logs to `.nogit/testlogs/[testname].log` |
|
|
| `--tags <tags>` | Run only tests with specific tags (comma-separated) |
|
|
|
|
### Example Outputs
|
|
|
|
#### Normal Output (Default)
|
|
```
|
|
🔍 Test Discovery
|
|
Mode: directory
|
|
Pattern: test
|
|
Found: 4 test file(s)
|
|
|
|
▶️ test/test.ts (1/4)
|
|
Runtime: node.js
|
|
✅ prepare test (1ms)
|
|
Summary: 1/1 PASSED
|
|
|
|
📊 Test Summary
|
|
┌────────────────────────────────┐
|
|
│ Total Files: 4 │
|
|
│ Total Tests: 4 │
|
|
│ Passed: 4 │
|
|
│ Failed: 0 │
|
|
│ Duration: 542ms │
|
|
└────────────────────────────────┘
|
|
|
|
ALL TESTS PASSED! 🎉
|
|
```
|
|
|
|
#### Quiet Mode
|
|
```
|
|
Found 4 tests
|
|
✅ test functionality works
|
|
✅ api calls return expected data
|
|
✅ error handling works correctly
|
|
✅ performance is within limits
|
|
|
|
Summary: 4/4 | 542ms | PASSED
|
|
```
|
|
|
|
#### Verbose Mode
|
|
Shows all console output from your tests, making debugging easier:
|
|
```
|
|
▶️ test/api.test.ts (1/1)
|
|
Runtime: node.js
|
|
Making API call to /users...
|
|
Response received: 200 OK
|
|
Processing user data...
|
|
✅ api calls return expected data (145ms)
|
|
Summary: 1/1 PASSED
|
|
```
|
|
|
|
#### JSON Mode
|
|
Perfect for CI/CD pipelines:
|
|
```json
|
|
{"event":"discovery","count":4,"pattern":"test","executionMode":"directory"}
|
|
{"event":"fileStart","filename":"test/test.ts","runtime":"node.js","index":1,"total":4}
|
|
{"event":"testResult","testName":"prepare test","passed":true,"duration":1}
|
|
{"event":"summary","summary":{"totalFiles":4,"totalTests":4,"totalPassed":4,"totalFailed":0,"totalDuration":542}}
|
|
```
|
|
|
|
## Test File Naming Conventions
|
|
|
|
tstest supports different test environments through file naming:
|
|
|
|
| Pattern | Environment | Example |
|
|
|---------|-------------|---------|
|
|
| `*.ts` | Node.js (default) | `test.basic.ts` |
|
|
| `*.node.ts` | Node.js only | `test.api.node.ts` |
|
|
| `*.chrome.ts` | Chrome browser | `test.dom.chrome.ts` |
|
|
| `*.browser.ts` | Browser environment | `test.ui.browser.ts` |
|
|
| `*.both.ts` | Both Node.js and browser | `test.isomorphic.both.ts` |
|
|
|
|
### Writing Tests
|
|
|
|
tstest includes a built-in TAP (Test Anything Protocol) test framework. Import it from the embedded tapbundle:
|
|
|
|
```typescript
|
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
|
|
|
tap.test('my awesome test', async () => {
|
|
const result = await myFunction();
|
|
expect(result).toEqual('expected value');
|
|
});
|
|
|
|
tap.start();
|
|
```
|
|
|
|
**Module Exports**
|
|
|
|
tstest provides multiple exports for different use cases:
|
|
|
|
- `@git.zone/tstest` - Main CLI and test runner functionality
|
|
- `@git.zone/tstest/tapbundle` - Browser-compatible test framework
|
|
- `@git.zone/tstest/tapbundle_node` - Node.js-specific test utilities
|
|
|
|
#### Test Features
|
|
|
|
**Tag-based Test Filtering**
|
|
```typescript
|
|
tap.tags('unit', 'api')
|
|
.test('should handle API requests', async () => {
|
|
// Test code
|
|
});
|
|
|
|
// Run with: tstest test/ --tags unit,api
|
|
```
|
|
|
|
**Test Lifecycle Hooks**
|
|
```typescript
|
|
tap.describe('User API Tests', () => {
|
|
let testUser;
|
|
|
|
tap.beforeEach(async () => {
|
|
testUser = await createTestUser();
|
|
});
|
|
|
|
tap.afterEach(async () => {
|
|
await deleteTestUser(testUser.id);
|
|
});
|
|
|
|
tap.test('should update user profile', async () => {
|
|
// Test code using testUser
|
|
});
|
|
});
|
|
```
|
|
|
|
**Parallel Test Execution**
|
|
```typescript
|
|
// Files with matching parallel group names run concurrently
|
|
// test.auth.para__1.ts
|
|
tap.test('authentication test', async () => { /* ... */ });
|
|
|
|
// test.user.para__1.ts
|
|
tap.test('user operations test', async () => { /* ... */ });
|
|
```
|
|
|
|
**Test Timeouts and Retries**
|
|
```typescript
|
|
tap.timeout(5000)
|
|
.retry(3)
|
|
.test('flaky network test', async (tools) => {
|
|
// This test has 5 seconds to complete and will retry up to 3 times
|
|
});
|
|
```
|
|
|
|
**Snapshot Testing**
|
|
```typescript
|
|
tap.test('should match snapshot', async (tools) => {
|
|
const result = await generateReport();
|
|
await tools.matchSnapshot(result);
|
|
});
|
|
```
|
|
|
|
**Test Fixtures**
|
|
```typescript
|
|
// Define a reusable fixture
|
|
tap.defineFixture('testUser', async () => ({
|
|
id: 1,
|
|
name: 'Test User',
|
|
email: 'test@example.com'
|
|
}));
|
|
|
|
tap.test('user test', async (tools) => {
|
|
const user = tools.fixture('testUser');
|
|
expect(user.name).toEqual('Test User');
|
|
});
|
|
```
|
|
|
|
**Skipping and Todo Tests**
|
|
```typescript
|
|
tap.skip.test('work in progress', async () => {
|
|
// This test will be skipped
|
|
});
|
|
|
|
tap.todo('implement user deletion', async () => {
|
|
// This marks a test as todo
|
|
});
|
|
```
|
|
|
|
**Browser Testing**
|
|
```typescript
|
|
// test.browser.ts
|
|
import { tap, webhelpers } from '@git.zone/tstest/tapbundle';
|
|
|
|
tap.test('DOM manipulation', async () => {
|
|
const element = await webhelpers.fixture(webhelpers.html`
|
|
<div>Hello World</div>
|
|
`);
|
|
expect(element).toBeInstanceOf(HTMLElement);
|
|
});
|
|
```
|
|
|
|
## Advanced Features
|
|
|
|
### Glob Pattern Support
|
|
|
|
Run specific test patterns:
|
|
```bash
|
|
# Run all unit tests
|
|
tstest "test/unit/**/*.ts"
|
|
|
|
# Run all integration tests
|
|
tstest "test/integration/*.test.ts"
|
|
|
|
# Run multiple patterns
|
|
tstest "test/**/*.spec.ts" "test/**/*.test.ts"
|
|
```
|
|
|
|
**Important**: Always quote glob patterns to prevent shell expansion. Without quotes, the shell will expand the pattern and only pass the first matching file to tstest.
|
|
|
|
### Automatic Logging
|
|
|
|
Use `--logfile` to automatically save test output:
|
|
```bash
|
|
tstest test/ --logfile
|
|
```
|
|
|
|
This creates detailed logs in `.nogit/testlogs/[testname].log` for each test file.
|
|
|
|
### Performance Analysis
|
|
|
|
In verbose mode, see performance metrics:
|
|
```
|
|
⏱️ Performance Metrics:
|
|
Average per test: 135ms
|
|
Slowest test: api integration test (486ms)
|
|
```
|
|
|
|
### Parallel Test Groups
|
|
|
|
Tests can be organized into parallel groups for concurrent execution:
|
|
|
|
```
|
|
━━━ Parallel Group: para__1 ━━━
|
|
▶️ test/auth.para__1.ts
|
|
▶️ test/user.para__1.ts
|
|
... tests run concurrently ...
|
|
──────────────────────────────────
|
|
|
|
━━━ Parallel Group: para__2 ━━━
|
|
▶️ test/db.para__2.ts
|
|
▶️ test/api.para__2.ts
|
|
... tests run concurrently ...
|
|
──────────────────────────────────
|
|
```
|
|
|
|
Files with the same parallel group suffix (e.g., `para__1`) run simultaneously, while different groups run sequentially.
|
|
|
|
### CI/CD Integration
|
|
|
|
For continuous integration, combine quiet and JSON modes:
|
|
```bash
|
|
# GitHub Actions example
|
|
tstest test/ --json > test-results.json
|
|
|
|
# Or minimal output
|
|
tstest test/ --quiet
|
|
```
|
|
|
|
## Changelog
|
|
|
|
### Version 1.8.0
|
|
- 📦 Embedded tapbundle directly into tstest project
|
|
- 🌐 Made tapbundle fully browser-compatible
|
|
- 📸 Added snapshot testing with base64-encoded communication protocol
|
|
- 🏷️ Introduced tag-based test filtering
|
|
- 🔧 Enhanced test lifecycle hooks (beforeEach/afterEach)
|
|
- 🎯 Fixed parallel test execution and grouping
|
|
- ⏳ Improved timeout and retry mechanisms
|
|
- 🛠️ Added test fixtures for reusable test data
|
|
- 📊 Enhanced TAP parser for better test reporting
|
|
- 🐛 Fixed glob pattern handling in shell scripts
|
|
|
|
## Contribution
|
|
|
|
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
|
|
|
|
## License
|
|
|
|
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
|
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
|
|
|
[](https://maintainedby.lossless.com) |