Skip to main content
Frappe Helpdesk uses comprehensive testing to ensure reliability and prevent regressions. This guide covers how to write and run tests for both backend and frontend code.

Overview

The project uses:
  • Backend: Frappe’s testing framework based on Python’s unittest
  • Frontend: Vite development server for manual testing
  • CI/CD: GitHub Actions for automated testing on pull requests

Backend Testing

Test Structure

Backend tests are located alongside the code they test:
helpdesk/
├── helpdesk/
│   ├── doctype/
│   │   ├── hd_ticket/
│   │   │   ├── hd_ticket.py
│   │   │   └── test_hd_ticket.py
│   │   ├── hd_agent/
│   │   │   ├── hd_agent.py
│   │   │   └── test_hd_agent.py
│   └── report/
│       └── ticket_analytics/
│           └── test_ticket_analytics.py
└── test_utils.py

Writing Tests

Tests inherit from frappe.tests.IntegrationTestCase:
from frappe.tests import IntegrationTestCase
import frappe

class TestHDTicket(IntegrationTestCase):
    def setUp(self):
        """Run before each test method"""
        frappe.db.delete("HD Ticket")
        # Create test data

    def test_ticket_creation(self):
        """Test that tickets can be created"""
        ticket = frappe.get_doc({
            "doctype": "HD Ticket",
            "subject": "Test Ticket",
            "description": "Test Description"
        })
        ticket.insert()
        self.assertTrue(ticket.name)

    def tearDown(self):
        """Run after each test method"""
        # Clean up test data

Test Utilities

The project provides helper functions in helpdesk/test_utils.py:
from helpdesk.test_utils import (
    make_ticket,
    create_agent,
    add_comment,
    make_status,
)

# Create a test ticket
ticket = make_ticket(
    subject="Test Ticket",
    description="Description",
    priority="High"
)

# Create a test agent
agent = create_agent(
    email="[email protected]",
    first_name="Test",
    last_name="Agent"
)

# Add a comment to a ticket
comment = add_comment(
    ticket=ticket.name,
    content="Test comment",
    comment_by="[email protected]"
)

Time-Based Testing

For testing SLA and time-dependent features, use self.freeze_time():
from frappe.utils import add_to_date, get_datetime
from helpdesk.test_utils import get_current_week_monday

def test_response_resolution_working_day(self):
    ticket_creation = get_current_week_monday()
    
    with self.freeze_time(ticket_creation):
        ticket = make_ticket(
            priority="High",
            service_level_agreement_creation=ticket_creation
        )
        
    expected_response_by = add_to_date(ticket_creation, hours=1)
    self.assertEqual(expected_response_by, ticket.response_by)

Running Backend Tests

Run All Tests

bench --site your-site.test run-tests --app helpdesk

Run Specific Test File

bench --site your-site.test run-tests --app helpdesk --module helpdesk.helpdesk.doctype.hd_ticket.test_hd_ticket

Run Specific Test Method

bench --site your-site.test run-tests --app helpdesk --module helpdesk.helpdesk.doctype.hd_ticket.test_hd_ticket --test test_ticket_creation

Run Tests with Coverage

bench --site your-site.test run-tests --app helpdesk --coverage
Coverage reports are generated at ~/frappe-bench/sites/coverage.xml.

Enable Verbose Output

bench --site your-site.test run-tests --app helpdesk --verbose

Test Setup and Teardown

The test_utils.py file includes a before_tests() function that runs before all tests:
def before_tests():
    """Initialize test environment"""
    frappe.db.set_single_value("HD Settings", "skip_email_workflow", 0)
    make_holiday_list()
    make_new_sla()
    make_test_objects("Email Domain", reset=True)
    create_email_account()
    frappe.db.commit()
This ensures consistent test data across all test runs.

Frontend Testing

Development Server

For frontend testing, use the Vite development server:
cd ~/frappe-bench/apps/helpdesk/desk
yarn dev
Access the application at:
  • http://localhost:8080 (default Vite port)
  • http://helpdesk.test:8080 (with host mapping)

Frontend Testing Practices

  1. Manual Testing: Test UI changes in the browser
  2. Component Testing: Verify components work in isolation
  3. Integration Testing: Test complete user flows
  4. Browser Testing: Test across different browsers
  5. Responsive Testing: Test on different screen sizes

Development Build

Build the frontend for production testing:
cd ~/frappe-bench/apps/helpdesk/desk
yarn build
Then build assets with bench:
bench build --app helpdesk

CI/CD Testing

GitHub Actions Workflow

Tests run automatically on pull requests to main, main-hotfix, and develop branches. The workflow:
  1. Sets up Python 3.14 and Node.js 24
  2. Installs MariaDB 10.6
  3. Installs Frappe Framework and dependencies
  4. Runs all backend tests with coverage
  5. Uploads coverage reports to Codecov
View test results in the GitHub Actions tab of your pull request.

Test Coverage

The project uses Codecov for coverage tracking:
  • Coverage badge: codecov
  • Target: Maintain or improve coverage with each PR
  • Coverage reports are generated automatically in CI

Writing Good Tests

Best Practices

  1. Test One Thing: Each test should verify a single behavior
  2. Use Descriptive Names: test_ticket_creation_with_high_priority()
  3. Arrange-Act-Assert: Structure tests clearly:
    def test_example(self):
        # Arrange: Set up test data
        ticket = make_ticket(priority="High")
        
        # Act: Perform the action
        ticket.status = "Resolved"
        ticket.save()
        
        # Assert: Verify the result
        self.assertEqual(ticket.agreement_status, "Fulfilled")
    
  4. Clean Up: Always clean up test data in tearDown()
  5. Avoid Dependencies: Tests should not depend on each other
  6. Test Edge Cases: Include tests for error conditions and boundary values

Common Test Patterns

Testing DocType Creation

def test_ticket_creation(self):
    ticket = frappe.get_doc({
        "doctype": "HD Ticket",
        "subject": "Test",
        "description": "Description"
    })
    ticket.insert()
    self.assertTrue(ticket.name)

Testing Field Validation

def test_required_field(self):
    ticket = frappe.get_doc({
        "doctype": "HD Ticket",
        "description": "No subject"
    })
    with self.assertRaises(frappe.MandatoryError):
        ticket.insert()

Testing API Endpoints

def test_assign_agent_api(self):
    from helpdesk.helpdesk.doctype.hd_ticket.api import assign_agent
    
    ticket = make_ticket()
    agent = create_agent("[email protected]")
    
    result = assign_agent(ticket.name, agent.user)
    self.assertTrue(result)

Testing Workflows

def test_ticket_resolution_workflow(self):
    ticket = make_ticket(priority="Urgent")
    
    # Agent responds
    ticket.status = "Replied"
    ticket.save()
    self.assertEqual(ticket.agreement_status, "Paused")
    
    # Customer responds
    ticket.status = "Open"
    ticket.save()
    self.assertEqual(ticket.agreement_status, "Resolution Due")
    
    # Agent resolves
    ticket.status = "Resolved"
    ticket.save()
    self.assertEqual(ticket.agreement_status, "Fulfilled")

Debugging Tests

def test_example(self):
    ticket = make_ticket()
    print(f"Ticket: {ticket.name}")
    print(f"Status: {ticket.status}")
    print(f"Response By: {ticket.response_by}")

Using the Debugger

import pdb

def test_example(self):
    ticket = make_ticket()
    pdb.set_trace()  # Debugger breakpoint
    ticket.status = "Resolved"

Checking Database State

def test_example(self):
    ticket = make_ticket()
    
    # Check database directly
    db_status = frappe.db.get_value("HD Ticket", ticket.name, "status")
    print(f"DB Status: {db_status}")

Testing Checklist

Before submitting a pull request:
  • All existing tests pass
  • New functionality includes tests
  • Edge cases are tested
  • Tests are documented with clear names
  • No test data leaks between tests
  • Tests run in isolation
  • Coverage is maintained or improved
  • Frontend changes are manually tested

Resources

Getting Help

If you need help with testing:
  • Review existing test files for examples
  • Ask in the Telegram group
  • Post on the Discuss forum
  • Check the Frappe Framework testing documentation

Build docs developers (and LLMs) love