Test-framework agnostic JavaScript testing runner that supports TDD workflows and CI integration across multiple browsers and environments.
—
Testem's flexible configuration system supports multiple file formats and extensive customization options for test execution, browser launching, and reporting.
Testem supports multiple configuration file formats with automatic discovery.
// testem.json - JSON format
{
"framework": "jasmine",
"src_files": ["src/**/*.js", "spec/**/*.js"],
"launch_in_ci": ["Chrome", "Firefox"]
}
// testem.yml - YAML format
framework: jasmine
src_files:
- "src/**/*.js"
- "spec/**/*.js"
launch_in_ci:
- Chrome
- Firefox
// testem.js - JavaScript/CommonJS format
module.exports = {
framework: 'jasmine',
src_files: ['src/**/*.js', 'spec/**/*.js'],
launch_in_ci: ['Chrome', 'Firefox']
};Essential configuration options for test execution and file management.
interface CoreConfig {
// Test Framework
framework?: string; // jasmine, qunit, mocha, or custom
// File Management
src_files?: string[]; // Source files to include (glob patterns)
src_files_ignore?: string[]; // Files to exclude (glob patterns)
serve_files?: string[]; // Files to serve (defaults to src_files)
watch_files?: string[]; // Files to watch (defaults to src_files)
css_files?: string[]; // CSS files to include
// Test Pages
test_page?: string | string[]; // Custom test page(s)
// Directory Settings
cwd?: string; // Working directory
config_dir?: string; // Config resolution directory
}Usage Examples:
// Basic file configuration
{
"src_files": [
"src/**/*.js",
"test/**/*.js"
],
"src_files_ignore": [
"src/vendor/*.js",
"**/*.min.js"
]
}
// Custom test page
{
"test_page": "custom-test.html",
"serve_files": ["dist/bundle.js"]
}
// Multiple test pages
{
"test_page": [
"unit-tests.html",
"integration-tests.html"
]
}Configure testem's built-in server and networking options.
interface ServerConfig {
// Server Settings
port?: number; // Server port (default: 7357)
host?: string; // Server host (default: localhost)
// Routing
routes?: Record<string, string | string[]>; // Custom route mappings
proxies?: Record<string, ProxyConfig>; // Proxy configuration
middleware?: Function[]; // Express middleware functions
// Security
unsafe_file_serving?: boolean; // Allow serving outside CWD
}
interface ProxyConfig {
target: string; // Proxy target URL
secure?: boolean; // Verify SSL certificates
ws?: boolean; // WebSocket proxy
onlyContentTypes?: string[]; // Content type filter
}Usage Examples:
// Basic server config
{
"port": 8080,
"host": "0.0.0.0"
}
// Custom routes
{
"routes": {
"/api": "mock-api",
"/assets": ["static", "fallback"]
}
}
// Proxy configuration
{
"proxies": {
"/api": {
"target": "http://localhost:3000",
"secure": false
},
"/ws": {
"target": "ws://localhost:3001",
"ws": true
}
}
}Configure browser and process launchers for different execution environments.
interface LauncherConfig {
// Built-in Launcher Control
launch_in_dev?: string[]; // Launchers for development mode
launch_in_ci?: string[]; // Launchers for CI mode
// Browser Customization
browser_args?: Record<string, string[] | string | BrowserArgsByMode>;
browser_paths?: Record<string, string>; // Custom browser paths
browser_exes?: Record<string, string>; // Custom browser executables
// Custom Launchers
launchers?: Record<string, LauncherDefinition>;
}
interface BrowserArgsByMode {
dev?: string[]; // Args for development mode
ci?: string[]; // Args for CI mode
}
interface LauncherDefinition {
command?: string; // Command to execute
exe?: string; // Executable path
args?: string[]; // Command arguments
protocol?: string; // browser, tap, or process
}Usage Examples:
// Basic launcher config
{
"launch_in_dev": ["Chrome"],
"launch_in_ci": ["Chrome", "Firefox", "Safari"]
}
// Browser customization
{
"browser_args": {
"Chrome": ["--no-sandbox", "--disable-gpu"],
"Firefox": ["--headless"]
},
"browser_paths": {
"Chrome": "/path/to/custom/chrome"
}
}
// Custom launcher
{
"launchers": {
"Node": {
"command": "node test/runner.js",
"protocol": "tap"
},
"CustomBrowser": {
"exe": "/path/to/browser",
"args": ["--test-mode"],
"protocol": "browser"
}
}
}Configure test execution behavior, timeouts, and parallel processing.
interface ExecutionConfig {
// Timeouts
timeout?: number; // Browser timeout in seconds
// Parallel Execution
parallel?: number; // Max parallel runners (CI mode)
// Test Behavior
fail_on_zero_tests?: boolean; // Exit with error if no tests
bail_on_uncaught_error?: boolean; // Exit on uncaught errors
single_run?: boolean; // Run once and exit
disable_watching?: boolean; // Disable file watching
// Reporter Settings
reporter?: string; // Test reporter (tap, xunit, dot, teamcity)
report_file?: string; // Output file for reports
}Usage Examples:
// CI execution config
{
"timeout": 120,
"parallel": 5,
"fail_on_zero_tests": true,
"bail_on_uncaught_error": true
}
// Custom reporter
{
"reporter": "xunit",
"report_file": "test-results.xml"
}Configure hooks that run at different points in the test lifecycle.
interface HookConfig {
on_start?: string | Function; // Run on suite startup
before_tests?: string | Function; // Run before each test run
after_tests?: string | Function; // Run after each test run
on_exit?: string | Function; // Run before suite exits
}Usage Examples:
// Command hooks
{
"on_start": "npm run setup",
"before_tests": "npm run build",
"after_tests": "npm run cleanup",
"on_exit": "npm run teardown"
}
// JavaScript function hooks (testem.js only)
module.exports = {
before_tests: function(config, data, callback) {
console.log('Running tests...');
callback();
},
after_tests: function(config, data, callback) {
console.log('Tests completed');
callback();
}
};Advanced options for specialized use cases and integrations.
interface AdvancedConfig {
// URL and Query Parameters
url?: string; // Custom URL for tests
query_params?: Record<string, any> | string; // Query parameters
// TAP Reporter Options
tap_failed_tests_only?: boolean; // Only output failed tests
tap_quiet_logs?: boolean; // Only log failures
tap_strict_spec_compliance?: boolean; // Strict TAP compliance
tap_log_processor?: Function; // Custom log processor
// Development Features
growl?: boolean; // Native notifications
socket_heartbeat_timeout?: number; // Socket timeout
}Usage Examples:
// Query parameters
{
"query_params": {
"env": "test",
"debug": true
}
}
// TAP customization
{
"tap_failed_tests_only": true,
"tap_quiet_logs": true
}// testem.json
{
"framework": "jasmine",
"src_files": [
"src/**/*.js",
"spec/**/*.js"
],
"launch_in_dev": ["Chrome"],
"launch_in_ci": ["Chrome", "Firefox"]
}// testem.js
module.exports = {
framework: 'mocha',
src_files: [
'dist/bundle.js',
'test/**/*.js'
],
test_page: 'test/index.html',
launch_in_dev: ['Chrome'],
launch_in_ci: ['Chrome', 'Firefox', 'Safari'],
browser_args: {
Chrome: ['--no-sandbox'],
Firefox: ['--headless']
},
proxies: {
'/api': {
target: 'http://localhost:3000'
}
},
before_tests: 'npm run build',
timeout: 60,
parallel: 3,
reporter: 'tap'
};Install with Tessl CLI
npx tessl i tessl/npm-testem