Getting Started
Learn the basics of UReport and how to integrate your test framework.
What is UReport?
UReport is a comprehensive test automation reporting platform that centralizes test execution results from any testing framework. It provides powerful analytics, dashboards, and collaboration tools to help teams understand test patterns and improve quality.
Analytics & Reporting
- Interactive dashboards with 10+ widget types
- Real-time test execution monitoring
- Historical trend analysis
- Test behavior pattern detection
Test Investigation
- Advanced failure categorization
- Similarity matching for related failures
- Outage management
- Custom states with TTL
Multiple Views
- List, Tree, Timeline views
- Advanced filtering options
- Split-view test details
- Cross-environment comparisons
Administration
- Role-based permissions
- Product Lane configurations
- CSV/PDF export
- RESTful API integration
API Integration
Install:
npm install --save-dev ureport-playwright-reporter
yarn add --dev ureport-playwright-reporter
Add to your Playwright config:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['ureport-playwright-reporter', {
serverUrl: process.env.UREPORT_SERVER_URL,
apiToken: process.env.UREPORT_API_TOKEN,
product: 'MyProduct',
type: 'E2E',
buildNumber: process.env.BUILD_NUMBER,
}],
],
});The apiToken is your UReport API token. Generate one: click your avatar → Edit Profile → API Token → Generate Token.
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
| serverUrl | string | Yes | — | Base URL of your UReport server |
| apiToken | string | Yes | — | API token for authentication |
| product | string | Yes | — | Product name (e.g. "WebPortal") |
| type | string | Yes | — | Test type / lane (e.g. "E2E", "UI", "API") |
| buildNumber | string | number | No | Date.now() | CI build number |
| team | string | No | — | Team responsible for the tests |
| browser | string | No | — | Browser used (e.g. "Chrome", "Firefox") |
| device | string | No | — | Device type (e.g. "Desktop", "Mobile") |
| platform | string | No | auto-detected | Operating system |
| platform_version | string | No | auto-detected | OS version |
| stage | string | No | — | Environment stage (e.g. "Staging", "Production") |
| version | string | No | — | Application version |
| batchSize | number | No | 50 | Tests submitted per API call |
| includeSteps | boolean | No | true | Include test steps in submission |
| includeScreenshots | boolean | No | true | Attach screenshots to failed steps |
| saveRelations | boolean | No | true | Save test relation records after the run |
| quickInfoAnnotations | string[] | No | [] | Annotation types stored as quickInfo (execution-specific, not saved to relations) |
| autoDetectPlatform | boolean | No | true | Auto-detect OS platform and version |
| outputFile | string | No | — | Write payload to JSON file (debugging) |
| testTransform | function | No | — | Per-test transform: return { name, relations } to override name/uid and inject relation fields |
Use Playwright's built-in test.info().annotations API to attach metadata. The reporter reads these annotations automatically.
test('user can log in', async ({ page }) => {
test.info().annotations.push({ type: 'ureport-uid', description: 'auth-login-001' });
// ... test steps
});Always set a ureport-uid annotation. Without it, the reporter falls back to the test title as the uid — which breaks tracking if you ever rename the test.
test.info().annotations.push({ type: 'components', description: 'Auth' });
test.info().annotations.push({ type: 'teams', description: 'Frontend' });
test.info().annotations.push({ type: 'tags', description: 'smoke' });components and teams are arrays — push multiple annotations of the same type to add multiple values.
// In playwright.config.ts: quickInfoAnnotations: ['env', 'run_url']
test.info().annotations.push({ type: 'env', description: 'staging' });
test.info().annotations.push({ type: 'run_url', description: 'https://ci.example.com/runs/42' });Use quickInfoAnnotations for values that change every run (environment URLs, run IDs). These are stored on the test result but never saved to the relation record.
Use Playwright's test.info().attach() API inside a test.step() to attach structured content. UReport reads the contentType and renders the appropriate format toggle in the Steps tab.
test('login API returns token', async ({ request }) => {
test.info().annotations.push({ type: 'ureport-uid', description: 'auth-login-api-001' });
const response = await request.post('/api/login', {
data: { username: 'alice', password: 'secret' },
});
await test.step('POST /api/login', async () => {
await test.info().attach('response-body', {
body: await response.text(),
contentType: 'application/json',
});
expect(response.ok()).toBeTruthy();
});
});await test.step('POST /api/login', async () => {
await test.info().attach('request-curl', {
body: `curl -X POST https://api.example.com/api/login -H 'Content-Type: application/json' -d '{"username":"alice","password":"secret"}'`,
contentType: 'text/x-curl',
});
});Supported MIME types and their UReport view formats:
| contentType | UReport view formats |
|---|---|
| application/json | JSON, XML |
| application/xml / text/xml | XML |
| text/x-curl | curl, text |
| text/plain | text |
Only the first content attachment per step is captured. Wrap your attach calls inside test.step() for cleaner step-level context in UReport.
Install:
npm install --save-dev ureport-jest-reporter
yarn add --dev ureport-jest-reporter
Add to your Jest config:
// jest.config.js
module.exports = {
reporters: [
'default',
['ureport-jest-reporter', {
serverUrl: process.env.UREPORT_SERVER_URL,
apiToken: process.env.UREPORT_API_TOKEN,
product: 'MyProduct',
type: 'E2E',
buildNumber: process.env.BUILD_NUMBER,
}],
],
};The apiToken is your UReport API token. Generate one: click your avatar → Edit Profile → API Token → Generate Token.
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
| serverUrl | string | Yes | — | Base URL of your UReport server |
| apiToken | string | Yes | — | API token for authentication |
| product | string | Yes | — | Product name |
| type | string | Yes | — | Test type / lane (e.g. "Unit", "Integration") |
| buildNumber | string | number | No | Date.now() | CI build number |
| team | string | No | — | Team responsible for the tests |
| browser | string | No | — | Browser (if applicable) |
| device | string | No | — | Device type (if applicable) |
| platform | string | No | auto-detected | Operating system |
| platform_version | string | No | auto-detected | OS version |
| stage | string | No | — | Environment stage |
| version | string | No | — | Application version |
| batchSize | number | No | 50 | Tests submitted per API call |
| saveRelations | boolean | No | true | Save test relation records after the run |
| autoDetectPlatform | boolean | No | true | Auto-detect OS platform and version |
| quickInfoAnnotations | string[] | No | [] | Field names stored as quickInfo (never saved to relations) |
| outputFile | string | No | — | Write payload to JSON file (debugging) |
Import the ureport() helper and call it inside your test body.
import { ureport } from 'ureport-jest-reporter';test('user can log in', () => {
ureport({ uid: 'auth-login-001' });
// ... test assertions
});Always set a uid. Without it, the reporter uses the full test name as the uid — which breaks tracking if you rename the test.
test('checkout flow', () => {
ureport({
uid: 'checkout-flow-001',
components: ['Checkout', 'Cart'],
teams: ['Frontend'],
tags: ['smoke', 'regression'],
});
// ... test assertions
});Any extra fields beyond uid, components, teams, and tags are stored as custom relation fields. For example: { uid: 'TC-001', jira: 'PROJ-42', owner: 'alice' }.
The ureport_api_token is your UReport API token. Generate one: click your avatar → Edit Profile → API Token → Generate Token.
| ini option | Env variable | Required | Default | Description |
|---|---|---|---|---|
| ureport_server_url | UREPORT_SERVER_URL | Yes | — | Base URL of UReport server |
| ureport_api_token | UREPORT_API_TOKEN | Yes | — | API token for authentication |
| ureport_product | UREPORT_PRODUCT | Yes | — | Product name |
| ureport_type | UREPORT_TYPE | Yes | — | Test type / lane |
| ureport_build_number | UREPORT_BUILD_NUMBER | No | timestamp | CI build number |
| ureport_team | UREPORT_TEAM | No | — | Team name |
| ureport_browser | UREPORT_BROWSER | No | — | Browser (e.g. "CHROME") |
| ureport_device | UREPORT_DEVICE | No | — | Device |
| ureport_platform | UREPORT_PLATFORM | No | auto-detected | OS platform |
| ureport_platform_version | UREPORT_PLATFORM_VERSION | No | auto-detected | OS version |
| ureport_stage | UREPORT_STAGE | No | — | Deployment stage |
| ureport_version | UREPORT_VERSION | No | — | Application version |
| ureport_batch_size | — | No | 50 | Tests per API call |
| ureport_include_steps | — | No | true | Include step detail |
| ureport_include_screenshots | — | No | true | Embed screenshots as base64 |
| ureport_save_relations | — | No | true | Save test relation records after the run |
| ureport_quick_info_markers | — | No | — | Space-separated marker names stored as quickInfo |
| ureport_output_file | — | No | — | Write payload to JSON file for debugging |
Use pytest markers to attach metadata. The reporter reads these automatically.
import pytest
@pytest.mark.ureport_uid("auth-login-001")
def test_user_can_log_in():
...Always set a ureport_uid marker. Without it, the reporter uses the test node id as the uid — which breaks tracking if you rename or move the test.
@pytest.mark.ureport_uid("checkout-flow-001")
@pytest.mark.ureport_components("Checkout", "Cart")
@pytest.mark.ureport_teams("Frontend")
@pytest.mark.ureport_tags("smoke", "regression")
def test_checkout_flow():
...Native pytest marks without arguments are automatically captured as tags. For example, @pytest.mark.smoke becomes the tag @smoke — no extra configuration needed.
# pytest.ini
ureport_quick_info_markers = env run_url
# test file
@pytest.mark.env("staging")
@pytest.mark.run_url("https://ci.example.com/runs/42")
def test_checkout_flow():
...Use the ureport fixture with the step() context manager to record steps, and attach() to add structured content.
import requests
def test_login_api(ureport):
with ureport.step("POST /api/login"):
ureport.attach("request-body",
body=b'{"username":"alice","password":"secret"}',
content_type="application/json")
response = requests.post("/api/login",
json={"username": "alice", "password": "secret"})
ureport.attach("response-body",
body=response.text.encode(),
content_type="application/json")
assert response.status_code == 200Supported content types:
| content_type | UReport view formats |
|---|---|
| application/json | JSON, XML |
| application/xml / text/xml | XML |
| text/x-curl | curl, text |
| text/plain | text |
Steps nest arbitrarily — use nested with ureport.step(...) blocks for sub-steps. Steps recorded inside setup or teardown fixtures are automatically placed in the setup/teardown phase arrays.
Install:
npm install --save-dev ureport-mocha-reporter
yarn add --dev ureport-mocha-reporter
Add to your .mocharc.js (or cypress.config.js for Cypress):
// .mocharc.js
module.exports = {
reporter: 'ureport-mocha-reporter',
reporterOptions: {
serverUrl: process.env.UREPORT_SERVER_URL,
apiToken: process.env.UREPORT_API_TOKEN,
product: 'MyProduct',
type: 'E2E',
buildNumber: process.env.BUILD_NUMBER,
},
};The apiToken is your UReport API token. Generate one: click your avatar → Edit Profile → API Token → Generate Token.
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
| serverUrl | string | Yes | — | Base URL of your UReport server |
| apiToken | string | Yes | — | API token for authentication |
| product | string | Yes | — | Product name |
| type | string | Yes | — | Test type / lane (e.g. "E2E", "Integration") |
| buildNumber | string | number | No | Date.now() | CI build number |
| team | string | No | — | Team responsible for the tests |
| browser | string | No | — | Browser (if applicable) |
| device | string | No | — | Device type (if applicable) |
| platform | string | No | auto-detected | Operating system |
| platform_version | string | No | auto-detected | OS version |
| stage | string | No | — | Environment stage |
| version | string | No | — | Application version |
| batchSize | number | No | 50 | Tests submitted per API call |
| saveRelations | boolean | No | true | Save test relation records after the run |
| autoDetectPlatform | boolean | No | true | Auto-detect OS platform and version |
| quickInfoAnnotations | string[] | No | [] | Annotation names stored as quickInfo (never saved to relations) |
| outputFile | string | No | — | Write payload to JSON file (debugging) |
Use the ureport() helper to attach metadata to your tests.
const { ureport } = require('ureport-mocha-reporter');it('user can log in', function() {
ureport({
uid: 'auth-login-001',
components: ['Auth'],
teams: ['Frontend'],
tags: ['smoke'],
});
// ... assertions
});Always set a uid. Without it the reporter uses the test title as the uid — which breaks tracking if you rename the test.
Install:
<dependency> <groupId>io.github.ureport-web</groupId> <artifactId>ureport-testng-reporter</artifactId> <version>1.0.0</version> <scope>test</scope> </dependency>
testImplementation("io.github.ureport-web:ureport-testng-reporter:1.0.0")Register the listener and set system properties in Maven Surefire:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<properties>
<property>
<name>listener</name>
<value>io.ureport.testng.UReportListener</value>
</property>
</properties>
<systemPropertyVariables>
<ureport.serverUrl>${env.UREPORT_SERVER_URL}</ureport.serverUrl>
<ureport.apiToken>${env.UREPORT_API_TOKEN}</ureport.apiToken>
<ureport.product>MyProduct</ureport.product>
<ureport.type>E2E</ureport.type>
</systemPropertyVariables>
</configuration>
</plugin>The ureport.apiToken is your UReport API token. Generate one: click your avatar → Edit Profile → API Token → Generate Token.
| System property | Env variable | Required | Default | Description |
|---|---|---|---|---|
| ureport.serverUrl | UREPORT_SERVER_URL | Yes | — | Base URL of your UReport server |
| ureport.apiToken | UREPORT_API_TOKEN | Yes | — | API token for authentication |
| ureport.product | UREPORT_PRODUCT | Yes | — | Product name |
| ureport.type | UREPORT_TYPE | Yes | — | Test type / lane |
| ureport.buildNumber | UREPORT_BUILD_NUMBER | No | timestamp | CI build number |
| ureport.team | UREPORT_TEAM | No | — | Team name |
| ureport.browser | UREPORT_BROWSER | No | — | Browser |
| ureport.stage | UREPORT_STAGE | No | — | Environment stage |
| ureport.version | UREPORT_VERSION | No | — | Application version |
| ureport.saveRelations | — | No | true | Save test relation records after the run |
Use the @UReport annotation on your test classes or methods to attach metadata.
import io.ureport.testng.UReport;
@UReport(uid = "auth-login-001", components = "Auth", teams = "Frontend", tags = "smoke")
@Test
public void userCanLogIn() {
// ... assertions
}Always set a uid. Without it the reporter uses the method name as the uid — which breaks tracking if you rename the method.
UReport supports two auth methods. Use API token for CI/CD — it's simpler and doesn't require a login step.
Each user can generate a personal API token from their profile. Click your avatar → Edit Profile → API Token → Generate Token. Pass it in every request:
Authorization: Bearer YOUR_API_TOKEN
curl -X POST https://your-ureport-url/api/build \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"product":"MyApp","type":"E2E","build":123}'Login via POST /api/login with username/password, then use the returned connect.sid cookie for subsequent requests.
After authenticating, sending test results requires three API calls:
Create a Build Session
Initialize a test execution session with your product lane information.
The combination of product and type creates the minimal Product Lane — the fundamental organizing unit in UReport. All test relations, investigated issues, custom states, and analytics are scoped to this Product Lane.
Build Payload Fields
true to archive the build — hidden from default views.{
"product": "MyApplication",
"type": "E2E",
"build": 123
}{
"_id": "65abc123def456789",
"product": "ECommerce",
"type": "API",
"build": 456,
"start_time": "2026-03-12T18:19:36.564Z",
}Save the returned _id — you'll need it to submit test results.
Submit Test Results
Send test results to the build session. Max 100 tests per call — batch multiple calls for larger suites.
Test Payload Fields
_id from build creation. Links this test to the build session.{
"tests": [
{
"build": "65abc123def456789",
"uid": "login-test-valid-credentials",
"name": "com.myapp.LoginTest.testValidCredentials",
"status": "PASS"
}
]
}Finalize Build Status
When your test session completes, call this endpoint to calculate the final build status.
POST /api/build/status/calculate/65abc123def456789
{
"is_update_build_status": true
}{
"pass": 45,
"fail": 3,
"skip": 2,
"total": 50
}| Aspect | uid | name |
|---|---|---|
| Purpose | Test identity for tracking | Display label for users |
| Visibility | Internal (used by UReport) | Shown in UI (test list, tree view, reports) |
| Stability | Must NEVER change | Can be updated anytime |
| Used for | Behavior analysis, flaky detection, historical trends | Tree view hierarchy, search, readability |
| Format | Short, stable ID (e.g., "TC-1234") | Descriptive (e.g., "com.myapp.LoginTest.testValidCredentials") |
Think of uid as the test's "social security number" — it never changes and uniquely identifies the test forever. The name is the "display name" — it's what people see and can be updated without losing history.
| Status | Description | When to Use |
|---|---|---|
| PASS | Test executed successfully | Test assertions passed without errors |
| FAIL | Test failed | Assertion errors or exceptions occurred |
| SKIP | Test was skipped | Test was ignored or conditionally skipped |
| RERUN_PASS | Rerun passed | Test passed after being retried |
| RERUN_FAIL | Rerun failed | Test failed again after retry |
| RERUN_SKIP | Rerun skipped | Test was skipped during retry |
Use the is_rerun field set to true along with RERUN_* statuses to properly track test retries in UReport.
Test relations enable powerful filtering and grouping. Add them via the info object:
{
"tests": [
{
"build": "65abc123def456789",
"uid": "checkout-payment-001",
"name": "CheckoutTest.testPaymentFlow",
"status": "PASS",
"info": {
"file": "tests/checkout/payment.spec.ts",
"path": "tests/checkout",
"components": ["Checkout", "Payment"],
"teams": ["E-Commerce"],
"tags": ["smoke", "critical"],
"priority": "P1"
}
}
]
}Special Info Fields
Product Lanes
Product Lanes are the fundamental organizing principle in UReport. They define how test executions are grouped, filtered, and analyzed by combining product information with optional metadata.
Product Lanes enable you to slice and dice your test data across different dimensions like products, environments, browsers, teams, and platforms.
Every test execution belongs to a Product Lane, which determines:
- How tests are grouped in dashboards and widgets
- What data appears in comparisons and trends
- How filtering and search operations work
- Which tests are included in analytics
Product Lanes consist of 2 mandatory fields and 7 optional fields:
Mandatory Fields (Required)
Optional Fields (Enhance Filtering)
Product Lanes are created automatically when you submit a build. Here are examples from simple to complex:
POST /api/build
{
"product": "MyApp",
"type": "API"
}POST /api/build
{
"product": "MyApp",
"type": "UI",
"stage": "Staging",
"browser": "Chrome"
}POST /api/build
{
"product": "ECommerce",
"type": "E2E",
"team": "QA",
"browser": "Chrome",
"version": "v2.1.0",
"stage": "Production",
"device": "Desktop",
"platform": "Windows",
"platform_version": "Windows-11"
}Start simple with just Product + Type. Add more fields as your testing needs grow.
Choose your product and type values carefully before sending data. Changing them later will create a new Product Lane, and historical data won't be connected.