Developer Guide - sebiboga/testlink-upgraded GitHub Wiki
TestLink v1.9.20 Developer Guide
Overview
This guide provides developers with the knowledge needed to understand, extend, and maintain TestLink codebase.
Table of Contents
- Architecture Overview
- Development Setup
- Code Organization
- Key Components
- Common Tasks
- Best Practices
- Debugging Tips
Architecture Overview
High-Level Structure
testlink/
├── lib/ # Core library code
│ ├── functions/ # Helper functions and classes
│ ├── api/ # REST and XMLRPC APIs
│ ├── execute/ # Test execution logic
│ ├── testcases/ # Test case management
│ ├── plan/ # Test plan management
│ └── ...
├── gui/ # User interface
│ ├── templates/ # Smarty templates (tl-classic, dashio themes)
│ └── javascript/ # JavaScript code
├── install/ # Installation utilities
│ └── util/ # sysinfo.php, config tools
├── docs/ # Documentation
├── config.inc.php # Main configuration
└── common.php # Entry point
Key Architectural Patterns
- Class-Based Design: Most functionality is encapsulated in classes (e.g.,
testcase.class.php,testproject.class.php) - Database Abstraction: Database operations go through a
databaseclass - Template Engine: Smarty templates for UI rendering
- API Layer: REST and XMLRPC APIs for programmatic access
- Configuration-Driven: Features controlled by config.inc.php settings
Development Setup
Requirements
- PHP 7.4+
- MySQL 5.7.24+ or MariaDB
- Apache or nginx with mod_rewrite
- Git for version control
Initial Setup
# 1. Clone the repository
git clone https://github.com/sebiboga/testlink-upgraded.git
cd testlink-upgraded
# 2. Copy sample config
cp config.inc.php.sample config.inc.php
# 3. Edit config for your environment
# - Set database connection details
# - Set base href
# - Configure features you need
# 4. Set up database
# - Run install/sql/mysql/testlink_create_tables.sql
# - Or use web installer at /install
# 5. Create a development branch
git checkout -b feature/your-feature-name
# 6. Start development!
Code Organization
Directory Structure Explained
lib/ - Core Library
-
functions/: Helper classes and functionstestcase.class.php- Test case operationstestproject.class.php- Project operationsdatabase.class.php- Database abstractioncommon.php- Common functions and initializationtlSmarty.inc.php- Smarty template configuration
-
api/: API endpointsrest/v3/- REST API v3 (recommended)xmlrpc/v1/- XMLRPC API v1 (legacy)
-
execute/: Test executionexecSetResults.php- Record execution resultsexecHistory.php- View execution historybugAdd.php- Link bugs to execution
-
testcases/: Test case managementtcEdit.php- Edit test casestcImport.php- Import test casestcSearch.php- Search test cases
-
plan/: Test plan managementplanEdit.php- Edit test plansplanAddTC.php- Add test cases to planplanImport.php- Import test plans
gui/ - User Interface
-
templates/: Smarty templatestl-classic/- Classic themedashio/- Modern dashboard theme
-
javascript/: Client-side codetestlink_library.js- Common JavaScript functionstest_automation.js- Automation scripts
Key Components
Database Layer
All database operations go through the database class:
// Example: Selecting data
$sql = "SELECT * FROM users WHERE id = " . intval($user_id);
$result = $db->get_recordset($sql);
// Example: Inserting data
$sql = "INSERT INTO users (name, email) VALUES ('" .
$db->prepare_string($name) . "', '" .
$db->prepare_string($email) . "')";
$result = $db->exec_query($sql);
// Never use raw MySQL functions!
Key Methods:
get_recordset($sql)- SELECT returning arrayexec_query($sql)- INSERT/UPDATE/DELETEprepare_string($var)- Escape string valuesprepare_int($var)- Ensure integer values
Class-Based Operations
Test Cases
// Create a test case class instance
$tcase_mgr = new testcase($db);
// Create a test case
$result = $tcase_mgr->create([
'name' => 'Login Test',
'suite_id' => 5,
'project_id' => 1,
'description' => 'Test user login'
]);
// Update a test case
$tcase_mgr->update($testcase_id, [
'name' => 'Updated Name'
]);
// Get test case
$tc = $tcase_mgr->get_by_id($testcase_id);
// Delete test case
$tcase_mgr->delete($testcase_id);
Test Projects
// Create a test project class instance
$tproject_mgr = new testproject($db);
// Get all projects
$projects = $tproject_mgr->get_all();
// Get specific project
$project = $tproject_mgr->get_by_id($project_id);
// Create project
$project_id = $tproject_mgr->create([
'name' => 'New Project',
'description' => 'Project description'
]);
API Usage
REST API v3
// Create a test case via API
$curl = curl_init('https://testlink/api/rest/v3/testcases');
curl_setopt($curl, CURLOPT_HTTPHEADER, [
'Authorization: Bearer YOUR_TOKEN',
'Content-Type: application/json'
]);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode([
'name' => 'Login Test',
'project_id' => 1,
'suite_id' => 5
]));
$response = curl_exec($curl);
$result = json_decode($response, true);
XMLRPC API v1
Every method takes a single struct argument (not positional parameters) - see API-Documentation for the full request/response format, working curl examples, and how to get a devKey.
// Create a test case via XMLRPC - xmlrpc extension, one struct argument
$request = xmlrpc_encode_request('tl.createTestCase', [[
'devKey' => 'YOUR_KEY',
'testsuiteid' => 54,
'testprojectid'=> 13,
'testcasename' => 'TestCaseName',
'authorlogin' => 'admin',
'summary' => 'What this test case verifies.',
'steps' => [[
'step_number' => 1,
'actions' => 'Do the thing.',
'expected_results' => 'The thing happens.',
'execution_type' => 1,
]],
]]);
$ch = curl_init('https://testlink/lib/api/xmlrpc/v1/xmlrpc.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: text/xml']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = xmlrpc_decode(curl_exec($ch));
Template Engine (Smarty)
{* Get labels for current language *}
{lang_get var="labels" s="btn_save,btn_cancel"}
{* Conditional display *}
{if $user->is_admin}
<p>You are an admin</p>
{/if}
{* Loop through array *}
{foreach item=project from=$projects}
<p>{$project.name}</p>
{/foreach}
{* Include another template *}
{include file="inc_header.tpl"}
{* Escape output *}
<p>{$variable|escape}</p>
Common Tasks
Task: Add a New Feature
-
Create a branch:
git checkout -b feature/my-feature -
Identify affected components:
- Will it affect test cases? → Edit
lib/functions/testcase.class.php - Will it affect UI? → Edit templates in
gui/templates/ - Will it affect API? → Edit
lib/api/ - Will it affect database? → Create migration in
install/sql/
- Will it affect test cases? → Edit
-
Implement the feature:
- Write code following existing patterns
- Add locale strings if needed (
locale/en_US/strings.txt) - Update database schema if needed
-
Test thoroughly:
- Test through UI
- Test via API if applicable
- Check for errors in browser console and PHP logs
-
Create a pull request:
git push origin feature/my-feature gh pr create --title "Feature: My Feature" --body "Description"
Task: Add a New Database Column
-
Create migration file:
-- install/sql/migrations/20240816_add_new_column.sql ALTER TABLE tcsteps ADD COLUMN my_new_column INT DEFAULT 0; -
Update related class:
- If for test cases: Edit
lib/functions/testcase.class.php - Update
get_*()methods to include new column - Update
create()method to handle new column - Update
update()method to handle new column
- If for test cases: Edit
-
Update UI if needed:
- Add form field to relevant template
- Handle in corresponding PHP controller
-
Update API:
- Add field to REST API response
- Update API documentation
Task: Fix a Bug
-
Locate the bug:
- Check error logs:
tail -f /var/log/php-error.log - Use sysinfo.php diagnostic tool
- Check browser console for JavaScript errors
- Check error logs:
-
Write a test:
- If test exists: update it
- If test missing: create new test
-
Fix the bug:
- Identify root cause
- Apply minimal fix (don't refactor)
- Verify fix doesn't break other tests
-
Verify fix:
- Test the specific scenario
- Run related tests
- Check for regressions
Best Practices
Code Style
-
Use consistent naming:
- Classes: PascalCase (
TestProject,TestCase) - Functions: snake_case (
get_test_cases()) - Variables: snake_case (
$test_case_id)
- Classes: PascalCase (
-
Database queries:
- Always use
prepare_string()andprepare_int() - Never concatenate user input directly
- Use comments to explain complex queries
- Always use
-
Error handling:
- Check for null/false returns
- Log errors for debugging
- Provide user-friendly error messages
Security
-
Input validation:
- Always validate user input
- Use
prepare_string()for database strings - Use
prepare_int()for integer values
-
Database access:
- Use parameterized queries (via prepare methods)
- Never trust user input
- Limit query results when possible
-
Authentication:
- Check user permissions before operations
- Use role-based access control (RBAC)
- Log security-relevant actions
Performance
-
Database queries:
- Limit result sets with WHERE clauses
- Use indexes for frequently queried fields
- Cache static data when possible
-
Code:
- Avoid N+1 queries
- Cache computed values
- Use appropriate data structures
-
Caching:
- Cache template compilation
- Cache database query results
- Use browser cache for static assets
Debugging Tips
Enable Debug Mode
// In config.inc.php
define('DEBUG', 1);
define('TLCFG_DEBUG_LVL', DEBUG);
Use Error Logging
// Log messages
tLog('Message here', 'WARNING');
tLog('Debug info', 'DEBUG');
// Check logs at: ?
// Defined by TLCFG_LOG_PATH in config.inc.php
Browser Developer Tools
- Console tab: Check for JavaScript errors
- Network tab: Check API requests/responses
- Storage tab: Check localStorage/sessionStorage
Common Issues
| Issue | Solution |
|---|---|
| Blank page | Check PHP error log, enable DEBUG mode |
| Database connection error | Verify config.inc.php settings |
| API not working | Check authentication token, review logs |
| UI rendering broken | Check template syntax, verify Smarty cache |
| Test execution failing | Check database, review error logs |
Useful Resources
- GitHub: https://github.com/sebiboga/testlink-upgraded
- Wiki Documentation: See Wiki for user and admin docs
- API Documentation: See Wiki API Documentation page
- Database Schema:
install/sql/mysql/testlink_create_tables.sql - Configuration Reference:
config.inc.phpcomments
Getting Help
- Check existing issues: Search GitHub issues
- Review similar code: Find similar features and learn from them
- Read tests: Understanding test files helps understand code intent
- Ask in discussions: Use GitHub Discussions for questions
Last Updated: August 2026
Version: 1.9.20