Skip to main content

Testing Strategies

Effective testing ensures your SuiteScript applications work correctly and reliably.


Testing Levels

┌─────────────────────────────────────────────────────────────────────────────┐
│ TESTING PYRAMID │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────┐
│ E2E │ ← Fewer, slower, more coverage
│ Tests │
├─────────────┤
│ Integration │
│ Tests │
├─────────────┤
│ Unit │ ← More, faster, specific
│ Tests │
└─────────────┘


UNIT TESTS:
• Test individual functions
• Mock NetSuite APIs
• Fast execution
• Run locally

INTEGRATION TESTS:
• Test script interactions
• Use sandbox environment
• Test with real records

E2E TESTS:
• Full workflow testing
• User scenario simulation
• Complete business processes

Manual Testing Checklist

Script Type Testing

Script TypeWhat to Test
SuiteletGET/POST handling, form display, data processing
User EventbeforeLoad, beforeSubmit, afterSubmit triggers
Client ScriptField changes, validation, save behavior
ScheduledExecution, governance, rescheduling
Map/ReduceAll stages, error handling, summarize
RESTletAll HTTP methods, authentication, responses
Workflow ActionTrigger conditions, return values

Testing User Event Scripts

/**
* Manual Test Plan for User Event Script
*/

// TEST: beforeLoad
// 1. Navigate to record in View mode
// 2. Verify custom fields appear
// 3. Verify buttons added correctly
// 4. Check page layout changes

// TEST: beforeSubmit
// 1. Create new record with valid data → Should save
// 2. Create record with invalid data → Should show error
// 3. Edit record and modify key fields → Should validate
// 4. Try to violate business rules → Should block

// TEST: afterSubmit
// 1. Create record → Check if related records created
// 2. Update record → Verify external systems notified
// 3. Check execution logs for errors

Testing Script

/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
* @description Include test logging
*/
define(['N/log'], (log) => {

const beforeSubmit = (context) => {
log.debug('TEST', '=== beforeSubmit START ===');
log.debug('Context Type', context.type);
log.debug('Record ID', context.newRecord.id);
log.debug('Record Type', context.newRecord.type);

// Log field values for debugging
const fields = ['entity', 'total', 'custbody_status'];
fields.forEach(field => {
log.debug(`Field: ${field}`, context.newRecord.getValue({ fieldId: field }));
});

// Your logic here

log.debug('TEST', '=== beforeSubmit END ===');
};

return { beforeSubmit };
});

Testing Client Scripts

/**
* Client Script Testing Checklist
*/

// TEST: pageInit
// 1. Load record in CREATE mode → Check defaults set
// 2. Load record in EDIT mode → Check existing values
// 3. Load record in COPY mode → Check copied values

// TEST: fieldChanged
// 1. Change field A → Verify field B updates
// 2. Change field to invalid value → Check validation
// 3. Change field on sublist → Verify line updates

// TEST: validateLine
// 1. Enter valid line data → Should commit
// 2. Enter invalid line data → Should block with message

// TEST: saveRecord
// 1. Save valid record → Should succeed
// 2. Save with missing required data → Should block
// 3. Save with business rule violation → Should block

// BROWSER CONSOLE TESTING
// Open browser console (F12)
// Look for console.log messages
// Check for JavaScript errors

Debug in Browser

// Add to client script for browser debugging
const pageInit = (context) => {
console.log('=== pageInit ===');
console.log('Mode:', context.mode);
console.log('Record:', context.currentRecord);

// Expose for browser console
window.testRecord = context.currentRecord;
};

// In browser console:
// > testRecord.getValue({ fieldId: 'entity' })
// > testRecord.setText({ fieldId: 'salesrep', text: 'John Smith' })

Testing Scheduled Scripts

┌─────────────────────────────────────────────────────────────────────────────┐
│ SCHEDULED SCRIPT TESTING │
└─────────────────────────────────────────────────────────────────────────────┘

1. SET DEPLOYMENT TO "TESTING"
├── Go to: Customization → Scripting → Script Deployments
└── Set Status: Testing (only you can run)

2. RUN MANUALLY
├── Click "Save & Execute" button
└── Monitor execution in real-time

3. CHECK LOGS
├── Customization → Scripting → Script Execution Logs
└── Filter by your script

4. VERIFY RESULTS
├── Check records were updated
├── Verify emails sent
└── Confirm expected behavior

5. TEST GOVERNANCE
├── Run with small dataset first
├── Check getRemainingUsage() logs
└── Verify rescheduling works

Governance Testing

const execute = (context) => {
const script = runtime.getCurrentScript();

// Log governance throughout
log.debug('Initial Units', script.getRemainingUsage());

mySearch.run().each((result, index) => {
if (index % 100 === 0) {
log.debug('Governance Check', {
processed: index,
remaining: script.getRemainingUsage()
});
}

processRecord(result);
return true;
});

log.debug('Final Units', script.getRemainingUsage());
};

Testing RESTlets

Using Postman

  1. Create Request

    • Set URL: https://{accountid}.restlets.api.netsuite.com/...
    • Add OAuth 1.0 authentication
    • Set Content-Type: application/json
  2. GET Request Test

GET ?script=customscript_api&deploy=1&id=123
  1. POST Request Test
{
"action": "create",
"data": {
"name": "Test Customer",
"email": "test@example.com"
}
}

Using cURL

# GET request
curl -X GET \
'https://1234567.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=customscript_api&deploy=1&id=123' \
-H 'Authorization: OAuth oauth_consumer_key="...",oauth_token="...",oauth_signature="..."' \
-H 'Content-Type: application/json'

# POST request
curl -X POST \
'https://1234567.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=customscript_api&deploy=1' \
-H 'Authorization: OAuth ...' \
-H 'Content-Type: application/json' \
-d '{"action":"create","data":{"name":"Test"}}'

Testing Map/Reduce Scripts

┌─────────────────────────────────────────────────────────────────────────────┐
│ MAP/REDUCE TESTING STRATEGY │
└─────────────────────────────────────────────────────────────────────────────┘

1. TEST getInputData FIRST
├── Return small dataset (5-10 records)
├── Verify data format
└── Check filters working

2. TEST map FUNCTION
├── Check context.value parsing
├── Verify context.write() calls
└── Check error handling

3. TEST reduce FUNCTION
├── Verify key grouping
├── Check context.values iteration
└── Test record creation/updates

4. TEST summarize
├── Check error iteration
├── Verify output processing
└── Test notification sending

5. FULL TEST
├── Run with full dataset
├── Monitor M/R status page
└── Check all stages complete

Monitor Map/Reduce Status

Customization → Scripting → Script Execution → Map/Reduce Script Status

Shows:

  • Current stage
  • Records processed
  • Errors per stage
  • Time elapsed

Test Data Management

Create Test Data

/**
* Suitelet to create test data
*/
const createTestData = () => {
const testCustomer = record.create({
type: record.Type.CUSTOMER
});

testCustomer.setValue({ fieldId: 'companyname', value: 'TEST - Automation Customer' });
testCustomer.setValue({ fieldId: 'email', value: 'test@automation.local' });

const customerId = testCustomer.save();

log.debug('Test Data', `Created customer: ${customerId}`);
return customerId;
};

Clean Test Data

/**
* Clean up test records
*/
const cleanTestData = () => {
const testRecords = search.create({
type: search.Type.CUSTOMER,
filters: [
['companyname', 'startswith', 'TEST -']
]
});

testRecords.run().each((result) => {
record.delete({
type: record.Type.CUSTOMER,
id: result.id
});
return true;
});
};

Logging Best Practices

// Use appropriate log levels
log.debug('Debug', 'Detailed debugging info'); // Development only
log.audit('Audit', 'Important milestones'); // Always log
log.error('Error', 'Error information'); // Always log

// Log structured data
log.debug('Record Data', JSON.stringify({
id: record.id,
type: record.type,
status: record.getValue({ fieldId: 'status' })
}, null, 2));

// Log timing
const startTime = Date.now();
// ... processing ...
log.audit('Performance', `Completed in ${Date.now() - startTime}ms`);

// Mark test entries clearly
log.debug('=== TEST START ===');
// ... test code ...
log.debug('=== TEST END ===');

Test Documentation Template

# Test Plan: Invoice Approval Script

## Test Environment
- Account: TSTDRV1234567
- Date: 2024-01-15
- Tester: John Smith

## Test Cases

### TC001: Invoice Under Threshold
- **Input**: Create invoice for $500
- **Expected**: No approval required
- **Result**: ✓ PASS

### TC002: Invoice Over Threshold
- **Input**: Create invoice for $5,000
- **Expected**: Routes to manager for approval
- **Result**: ✓ PASS

### TC003: Approval Action
- **Input**: Manager clicks Approve button
- **Expected**: Status updates, notification sent
- **Result**: ✗ FAIL - Email not sent

## Issues Found
1. Issue #1: Email notification fails when...

Next Steps