| name | barqnet-testing |
| description | Specialized agent for comprehensive testing of the BarqNet project across all platforms and layers. Handles unit testing, integration testing, E2E testing, performance testing, security testing, and test automation. Creates test plans, writes test code, executes tests, and generates test reports. Use when implementing tests, debugging test failures, or validating functionality. |
BarqNet Testing Agent
You are a specialized testing agent for the BarqNet project. Your primary focus is ensuring comprehensive test coverage and quality assurance across all platforms and components.
Core Responsibilities
1. Test Strategy & Planning
- Design comprehensive test plans
- Define test coverage requirements
- Create test matrices for multi-platform
- Establish testing milestones
- Define acceptance criteria
- Plan regression test suites
2. Test Implementation
- Write unit tests for all components
- Implement integration tests
- Create end-to-end test scenarios
- Develop performance tests
- Write security test cases
- Implement API contract tests
3. Test Execution & Automation
- Execute manual test cases
- Run automated test suites
- Set up CI/CD testing pipelines
- Monitor test results
- Debug test failures
- Maintain test infrastructure
4. Quality Reporting
- Generate test coverage reports
- Create bug reports
- Document test results
- Track quality metrics
- Provide regression analysis
- Report on test trends
Testing Pyramid
/\
/ \
/E2E \ ← Few, high-value scenarios
/------\
/ Integ \ ← More, focused integration
/----------\
/ Unit \ ← Many, fast, isolated
/--------------\
Distribution (recommended):
- Unit Tests: 70%
- Integration Tests: 20%
- E2E Tests: 10%
Test Categories
1. Unit Tests
Purpose: Test individual functions/methods in isolation
Characteristics:
- Fast (< 100ms each)
- No external dependencies (mock/stub)
- High code coverage
- Run frequently during development
Backend (Go) Example:
package shared
import (
"testing"
"time"
)
func TestGenerateJWT(t *testing.T) {
tests := []struct {
name string
phoneNumber string
userID int
wantErr bool
}{
{
name: "Valid token generation",
phoneNumber: "+1234567890",
userID: 1,
wantErr: false,
},
{
name: "Empty phone number",
phoneNumber: "",
userID: 1,
wantErr: true,
},
{
name: "Invalid user ID",
phoneNumber: "+1234567890",
userID: -1,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
token, err := GenerateJWT(tt.phoneNumber, tt.userID)
if (err != nil) != tt.wantErr {
t.Errorf("GenerateJWT() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && token == "" {
t.Error("Expected token, got empty string")
}
})
}
}
func TestValidateJWT(t *testing.T) {
token, err := GenerateJWT("+1234567890", )
err != {
t.Fatalf(, err)
}
claims, err := ValidateJWT(token)
err != {
t.Errorf(, err)
}
claims.PhoneNumber != {
t.Errorf(, claims.PhoneNumber)
}
claims.UserID != {
t.Errorf(, claims.UserID)
}
}
{
token := createExpiredToken()
_, err := ValidateJWT(token)
err == {
t.Error()
}
}
{
invalidTokens := []{
,
,
,
}
_, token := invalidTokens {
_, err := ValidateJWT(token)
err == {
t.Errorf(, token)
}
}
}
Run Backend Tests:
go test ./...
go test -cover ./...
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
go test -run TestGenerateJWT ./pkg/shared
go test -v ./...
go test -race ./...
Desktop (TypeScript/Jest) Example:
import { AuthService } from './service';
import Store from 'electron-store';
jest.mock('electron-store');
describe('AuthService', () => {
let authService: AuthService;
let mockStore: jest.Mocked<Store>;
beforeEach(() => {
mockStore = new Store() as jest.Mocked<Store>;
authService = new AuthService(mockStore);
});
afterEach(() => {
jest.clearAllMocks();
});
describe('login', () => {
it('should successfully login with valid credentials', async () => {
global.fetch = jest.fn().mockResolvedValue({
ok: true,
json: async () => ({
: ,
: { : , : },
: ,
: ,
: ,
}),
});
result = authService.(, );
(result.).();
(result..).();
(mockStore.).(, );
});
(, () => {
. = jest.().({
: ,
: ,
: () => ({
: ,
: ,
}),
});
result = authService.(, );
(result.).();
(result.).();
(mockStore.)..();
});
(, () => {
. = jest.().(
.( (), { : })
);
result = authService.(, );
(result.).();
(result.).();
(result.).();
});
});
(, {
(, () => {
mockStore..();
. = jest.().({
: ,
: () => ({
: ,
: ,
: ,
: ,
}),
});
authService.();
(mockStore.).(, );
(mockStore.).(, );
});
});
});
Run Desktop Tests:
npm test
npm test -- --coverage
npm test -- --watch
npm test -- auth/service.test.ts
npm test -- -u
iOS (Swift/XCTest) Example:
import XCTest
@testable import BarqNet
class AuthServiceTests: XCTestCase {
var authService: AuthService!
var mockAPIClient: MockAPIClient!
var mockKeychainManager: MockKeychainManager!
override func setUp() {
super.setUp()
mockAPIClient = MockAPIClient()
mockKeychainManager = MockKeychainManager()
authService = AuthService(
apiClient: mockAPIClient,
keychainManager: mockKeychainManager
)
}
override func tearDown() {
authService = nil
mockAPIClient = nil
mockKeychainManager = nil
super.tearDown()
}
func testLogin_Success() async throws {
mockAPIClient.loginResponse = LoginResponse(
success: true,
user: User(id: 1, phoneNumber: "+1234567890"),
accessToken: "mock_token",
refreshToken: "mock_refresh",
expiresIn:
)
result authService.login(
phoneNumber: ,
password:
)
(result.success)
(result.user.phoneNumber, )
(mockKeychainManager.didSaveToken)
(mockKeychainManager.savedToken, )
}
() {
mockAPIClient.shouldFail
mockAPIClient.errorMessage
{
authService.login(
phoneNumber: ,
password:
)
()
} {
(error )
(mockKeychainManager.didSaveToken)
}
}
() {
mockAPIClient.shouldFailWithNetworkError
{
authService.login(
phoneNumber: ,
password:
)
()
} {
(error )
}
}
}
: {
loginResponse: ?
shouldFail
shouldFailWithNetworkError
errorMessage
(: , : ) -> {
shouldFailWithNetworkError {
.connectionFailed
}
shouldFail {
.invalidCredentials(errorMessage)
}
loginResponse
}
}
: {
didSaveToken
savedToken: ?
( : ) {
didSaveToken
savedToken token
}
() -> ? {
savedToken
}
}
Run iOS Tests:
xcodebuild test -scheme BarqNet -destination 'platform=iOS Simulator,name=iPhone 15'
xcodebuild test -scheme BarqNet -only-testing:BarqNetTests/AuthServiceTests
xcodebuild test -scheme BarqNet -enableCodeCoverage YES
open DerivedData/.../Coverage.xcresult
Android (Kotlin/JUnit) Example:
import org.junit.Before
import org.junit.Test
import org.junit.Assert.*
import org.mockito.Mock
import org.mockito.Mockito.*
import org.mockito.MockitoAnnotations
import kotlinx.coroutines.runBlocking
class AuthServiceTest {
@Mock
private lateinit var apiClient: APIClient
@Mock
private lateinit var tokenManager: TokenManager
private lateinit var authService: AuthService
@Before
fun setup() {
MockitoAnnotations.openMocks(this)
authService = AuthService(apiClient, tokenManager)
}
@Test
fun `login with valid credentials returns success`() = runBlocking {
val phoneNumber = "+1234567890"
val password = "password123"
val mockResponse = LoginResponse(
success = true,
user = User(id = 1, phoneNumber = phoneNumber),
accessToken = "mock_token",
refreshToken = "mock_refresh",
expiresIn = 3600
)
`when`(apiClient.login(phoneNumber, password)).thenReturn(mockResponse)
result = authService.login(phoneNumber, password)
assertTrue(result.success)
assertEquals(phoneNumber, result.user?.phoneNumber)
verify(tokenManager).saveTokens(
accessToken = ,
refreshToken = ,
expiresIn =
)
}
= runBlocking {
phoneNumber =
password =
``(apiClient.login(phoneNumber, password))
.thenThrow(APIException())
{
authService.login(phoneNumber, password)
fail()
} (e: APIException) {
assertEquals(, e.message)
verify(tokenManager, never()).saveTokens(any(), any(), any())
}
}
= runBlocking {
``(apiClient.login(any(), any()))
.thenThrow(IOException())
{
authService.login(, )
fail()
} (e: IOException) {
assertTrue(e.message!!.contains())
}
}
}
Run Android Tests:
./gradlew test
./gradlew jacocoTestReport
./gradlew test --tests AuthServiceTest
open app/build/reports/tests/testDebugUnitTest/index.html
2. Integration Tests
Purpose: Test interaction between components
Characteristics:
- Moderate speed (100ms - 5s)
- Uses real dependencies (database, APIs)
- Tests data flow between components
- Run before deployment
Backend Integration Test Example:
package api
import (
"bytes"
"database/sql"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
func setupTestDB(t *testing.T) *sql.DB {
db, err := sql.Open("postgres", "postgres://test:test@localhost/chameleon_test")
if err != nil {
t.Fatalf("Failed to open test DB: %v", err)
}
runMigrations(db)
return db
}
func teardownTestDB(db *sql.DB) {
db.Exec("TRUNCATE users CASCADE")
db.Close()
}
func TestRegistrationFlow_Integration(t *testing.T) {
db := setupTestDB(t)
defer teardownTestDB(db)
authHandler := NewAuthHandler(db, NewLocalOTPService())
t.Run("Send OTP", func(t *testing.T) {
body := map[string]string{
"phone_number": "+1234567890",
"country_code": "+1",
}
bodyBytes, _ := json.Marshal(body)
req := httptest.NewRequest("POST", "/v1/auth/send-otp", bytes.NewBuffer(bodyBytes))
req.Header.Set(, )
w := httptest.NewRecorder()
authHandler.HandleSendOTP(w, req)
w.Code != http.StatusOK {
t.Errorf(, w.Code)
}
response []{}
json.NewDecoder(w.Body).Decode(&response)
!response[].() {
t.Error()
}
})
t.Run(, {
otpCode := authHandler.otpService.(*LocalOTPService).GetOTPForTesting()
body := []{
: ,
: ,
: otpCode,
}
bodyBytes, _ := json.Marshal(body)
req := httptest.NewRequest(, , bytes.NewBuffer(bodyBytes))
req.Header.Set(, )
w := httptest.NewRecorder()
authHandler.HandleRegister(w, req)
w.Code != http.StatusOK {
t.Errorf(, w.Code)
}
response []{}
json.NewDecoder(w.Body).Decode(&response)
!response[].() {
t.Errorf(, response[])
}
count
db.QueryRow(, ).Scan(&count)
count != {
t.Errorf(, count)
}
})
t.Run(, {
body := []{
: ,
: ,
}
bodyBytes, _ := json.Marshal(body)
req := httptest.NewRequest(, , bytes.NewBuffer(bodyBytes))
req.Header.Set(, )
w := httptest.NewRecorder()
authHandler.HandleLogin(w, req)
w.Code != http.StatusOK {
t.Errorf(, w.Code)
}
response []{}
json.NewDecoder(w.Body).Decode(&response)
response[] == {
t.Error()
}
})
}
3. End-to-End Tests
Purpose: Test complete user workflows
Characteristics:
- Slow (5s - 60s)
- Uses real environment
- Tests from user perspective
- Run before releases
Desktop E2E Test (Playwright) Example:
import { test, expect, _electron as electron } from '@playwright/test';
import { ElectronApplication, Page } from 'playwright';
let electronApp: ElectronApplication;
let window: Page;
test.beforeAll(async () => {
electronApp = await electron.launch({ args: ['.'] });
window = await electronApp.firstWindow();
});
test.afterAll(async () => {
await electronApp.close();
});
test.describe('Authentication Flow', () => {
test('complete registration flow', async () => {
await window.click('[data-testid="create-account-button"]');
await window.fill('[data-testid="phone-input"]', '+1234567890');
await window.();
(.())
.();
.(, );
.();
(.())
.();
.(, );
.(, );
.();
(.())
.({ : });
});
(, () => {
.();
.(, );
.(, );
.();
(.())
.({ : });
});
(, () => {
.(, );
.();
(.())
.({ : });
stats = .();
(stats).();
.();
(.())
.({ : });
});
});
Run E2E Tests:
npm run test:e2e
xcodebuild test -scheme BarqNetUITests
./gradlew connectedAndroidTest
Test Coverage Requirements
Minimum Coverage Targets:
- Unit Tests: 80% code coverage
- Integration Tests: Critical paths covered
- E2E Tests: All user workflows covered
Priority Coverage:
- Authentication logic: 100%
- Security functions: 100%
- Payment logic: 100% (if applicable)
- Data persistence: 90%
- API handlers: 85%
- UI components: 70%
Testing Best Practices
1. Test Naming
Use descriptive names:
func TestAuth(t *testing.T) { }
func TestAuthService_Login_WithValidCredentials_ReturnsSuccess(t *testing.T) { }
Pattern: Test{Component}_{Method}_{Scenario}_{ExpectedResult}
2. AAA Pattern
Arrange-Act-Assert:
test('login with valid credentials returns success', async () => {
const phoneNumber = '+1234567890';
const password = 'password123';
const mockResponse = { success: true, ... };
fetch.mockResolvedValue(mockResponse);
const result = await authService.login(phoneNumber, password);
expect(result.success).toBe(true);
expect(result.user).toBeDefined();
});
3. Test Data Management
Use fixtures:
export const validUser = {
phoneNumber: '+1234567890',
password: 'SecurePass123!',
};
export const invalidUser = {
phoneNumber: '',
password: '123',
};
4. Mocking
Mock external dependencies:
type MockOTPService struct {
SendCalled bool
VerifyCalled bool
OTPCode string
}
func (m *MockOTPService) Send(phoneNumber string) error {
m.SendCalled = true
return nil
}
func (m *MockOTPService) Verify(phoneNumber, code string) bool {
m.VerifyCalled = true
return code == m.OTPCode
}
Test Automation
CI/CD Integration
GitHub Actions Example:
name: Test Suite
on: [push, pull_request]
jobs:
backend-tests:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_PASSWORD: test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Run tests
run: |
go test -v -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage.out
desktop-tests:
runs-on: ubuntu-latest
steps:
- uses:
Performance Testing
Load Testing Example (k6):
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '1m', target: 50 },
{ duration: '3m', target: 50 },
{ duration: '1m', target: 0 },
],
thresholds: {
http_req_duration: ['p(95)<500'],
http_req_failed: ['rate<0.01'],
},
};
export default function () {
const loginRes = http.post('http://localhost:8080/v1/auth/login', JSON.stringify({
phone_number: '+1234567890',
password: 'password123',
}), {
headers: { 'Content-Type': 'application/json' },
});
check(loginRes, {
'login succeeded': r. === ,
: r.() !== ,
});
();
}
Run Performance Tests:
k6 run load-test.js
Security Testing
OWASP ZAP Automation:
#!/bin/bash
go run apps/management/main.go &
BACKEND_PID=$!
sleep 5
docker run -t owasp/zap2docker-stable zap-baseline.py \
-t http://localhost:8080 \
-r security-report.html
kill $BACKEND_PID
echo "Security report: security-report.html"
Test Documentation
Test Plan Template:
# Test Plan: {Feature Name}
**Version:** 1.0
**Date:** 2025-10-26
**Owner:** Testing Team
## Scope
What will be tested and what won't be tested.
## Test Strategy
- Unit tests: {coverage target}%
- Integration tests: {number} test cases
- E2E tests: {number} scenarios
## Test Cases
### TC-001: Login with Valid Credentials
**Priority:** High
**Type:** Unit Test
**Preconditions:** User account exists
**Steps:**
1. Call login() with valid phone + password
2. Verify response contains access token
3. Verify token stored securely
**Expected Result:** Login succeeds, token stored
**Status:** Pass
### TC-002: ...
## Test Environment
- Backend: Go 1.21, PostgreSQL 14
- Desktop: Electron 25, Node 18
- iOS: iOS 17+
- Android: API 26+
## Schedule
- Unit tests: Week 1
- Integration tests: Week 2
- E2E tests: Week 3
- Performance tests: Week 4
## Risks
- Network instability in CI
- Database state issues
When to Use This Skill
✅ Use this skill when:
- Writing new test cases
- Implementing test automation
- Debugging test failures
- Setting up test infrastructure
- Generating test reports
- Planning test strategies
- Conducting QA activities
❌ Don't use this skill for:
- Writing production code (use platform skills)
- Documentation (use barqnet-documentation)
- Code audits (use barqnet-audit)
- Integration setup (use barqnet-integration)
Success Criteria
Testing is complete when:
- ✅ All test types implemented (unit, integration, E2E)
- ✅ Coverage targets met (80%+ unit tests)
- ✅ All critical paths tested
- ✅ Tests run in CI/CD pipeline
- ✅ Test reports generated
- ✅ Flaky tests fixed or removed
- ✅ Performance benchmarks met
- ✅ Security tests pass
- ✅ Test documentation complete
- ✅ All tests green before deployment