Core Concepts
You've set up hundreds of automated CI/CD tests in xUnit and NUnit.
The question
You've set up hundreds of automated CI/CD tests in xUnit and NUnit. Your ServiceNow team mentions 'ATF' — Automated Test Framework. How does it compare to your .NET testing experience, and what kind of testing does ServiceNow handle that's fundamentally different from unit testing code?
Reading Between the Lines
ATF (Automated Test Framework) is ServiceNow's built-in testing platform. But unlike xUnit/NUnit which test code in isolation, ATF tests platform behavior — form loads, workflow executions, security rules, and UI interactions. It's closer to Selenium + integration testing than pure unit testing.
The Comparison
// .NET Testing Pyramid (what you know) // Unit Tests (xUnit) → Test individual methods/classes // Integration Tests → Test API endpoints, DB operations // E2E Tests (Selenium) → Test full UI workflows // // ServiceNow ATF Maps To: // Server-side steps → Integration tests (BR fires correctly) // Form-based steps → E2E tests (form loads, fields populate) // Flow/Workflow steps → Integration tests (automation works) // Security steps → Auth tests (ACLs enforce correctly) // No pure unit testing → Script Includes tested via server steps
What ATF Handles That's Different
- Configuration testing: Did the UI Policy hide the right field? Does the Business Rule auto-populate the correct value? These aren't code tests — they're platform behavior tests. No equivalent in .NET because you write the behavior; in ServiceNow, you configure it.
- Impersonation: ATF can run tests as different users to verify role-based access — like having test fixtures that swap identity mid-test.
Run as User: helpdesk.agent→ verify they can create incidents but can't delete them. - Parameterized test suites: Group ATF tests into suites that run against specific Update Sets before deployment — like a gate in your Azure DevOps pipeline. This is how mature ServiceNow teams prevent regressions.
// ATF Test Step Example — Server-side Script step
// (like writing an xUnit [Fact] method)
(function(outputs, steps, params, stepResult, assertEqual) {
// Arrange: Create a test incident
var gr = new GlideRecord('incident');
gr.initialize();
gr.short_description = 'ATF Test Incident';
gr.impact = 1;
gr.urgency = 1;
gr.insert();
// Act: Re-query to check Business Rule fired
gr.get(gr.sys_id);
// Assert: Priority should be auto-calculated to 1 (Critical)
assertEqual({
name: 'Priority auto-calculated',
shouldbe: '1',
value: gr.getValue('priority')
});
// Cleanup
gr.deleteRecord();
})(outputs, steps, params, stepResult, assertEqual);Limitations vs .NET Testing
- No mocking framework: You can't mock GlideRecord calls like you'd mock
IRepositorywith Moq. Tests hit real tables. - No TDD workflow: ATF tests are created in the UI, not in an IDE. The feedback loop is slower than
dotnet test --watch. - Test data management: ATF creates real records during tests. Cleanup is manual unless you build it into your test steps.
💡 .NET Developer Pro Tip
Think of ATF as your integration test suite with Selenium-like capabilities built in. Use it for regression testing before deployments — especially for Business Rules, ACLs, and Flows. For Script Include logic, write ATF server-side steps that exercise the methods directly, similar to calling service methods in integration tests.