testing · O-RAN · 5G core · course

Testing a 5G network, end to end

A working course for engineers who test RAN and core. Levels, types, techniques and tools, all mapped onto one system: a UE talking through an O-RU, O-DU and O-CU into a 5G core.

16 September 2026About 70 minutes16 modulesInteractive: architecture, pipeline, quiz
A data centre corridor between rows of closed server cabinets

Foundations

1. The system under test

Run a procedure, then click any interface to see which tests own it.

THE SYSTEM UNDER TEST
O-CU5G coreSMOO1 · O2 · M-PlaneNon-RT RICrApps · A1Near-RT RICxApps · E2UENAS · RRCO-RULow-PHY · RFO-DUHi-PHY · MAC · RLCCU-CPRRC · PDCP-CCU-UPPDCP-U · SDAPAMFSMFUPFDNUuOpen FHM-PlaneF1-C / UE1N2N3SBIN4N6E2O1PTP / SyncETiming: grandmaster to O-DU to O-RU, ±1.5 µs budget for TDDN9 between UPFs and Xn between gNBs omitted
Pick a procedure or click an interfaceThe seams are where distributed-system bugs live: every one is an integration boundary with its own spec, its own timing domain, and its own capture point.

Architecture map. Left to right on the main row: UE, O-RU, O-DU, O-CU split into CU-CP and CU-UP, then the 5G core with AMF, SMF, UPF and the data network. Above them: SMO, Non-RT RIC and Near-RT RIC with management links down to the O-RU, O-DU and CU-CP. The interfaces Uu, Open Fronthaul, M-Plane, F1, E1, N2, N3, SBI, N4, N6, E2, O1 and PTP are labelled. While nothing is selected, a packet travels the user plane from the UE through the O-RU, O-DU, CU-UP and UPF to the data network and back, and each interface it crosses lights. Selecting an interface stops the packet there and lists the test levels that own it. Four buttons run Registration, PDU session, User data and O-RU bring-up, moving a marker one node per step with a line of explanation.

  • the path: the user plane, or the procedure's seams
  • a user-plane packet, out and back
  • a procedure's packet, one node per step
  • a seam; dashed, a management interface
UE, O-RU, O-DU and O-CU with the 5G core to the right and the SMO and RICs above. A user-plane packet travels from the UE to the data network and back, and each seam it crosses lights. Each interface label is a button: selecting one stops the packet on that seam and lists the tests that own it. A procedure button sends a packet through the seams that procedure crosses.

Foundations

2. What a test framework is

A test framework is the reusable machinery that lets you write, organise, run, and report tests without rebuilding the plumbing each time. Tests are the content; the framework is the structure they plug into. In telecom, the framework plus the lab, simulators, and topology is the harness, and that is where most of the engineering goes.

Six pieces, mapped to this system:

Discovery and structure

How tests are found, grouped, tagged, selected.

Markers like @f1, @sim, @real_rf, @otic_subset so CI can run "all F1 tests on simulator" without touching hardware.

e.g. pytest markers, Robot Framework tags

Fixtures and lifecycle

Setup and teardown at the right scope.

Session-scoped: bring up Open5GS in containers. Module-scoped: start a gNB. Function-scoped: register a fresh UE and deregister after.

e.g. pytest fixtures, testcontainers, docker-compose, containerlab

Assertions and oracles

How pass/fail is decided.

eventually(ue.state == "REGISTERED", 10s); a tshark filter proving InitialContextSetup carried the right S-NSSAI; N3 throughput within a statistical window, never an exact number.

e.g. custom async matchers, tshark/pyshark, Prometheus queries

Drivers and abstraction

How tests talk to the thing under test.

One UE interface with two backends: UERANSIM and a real phone via ADB. One RU interface with a NETCONF backend for M-Plane and a simulated one. A test written against the interface runs on either.

e.g. ncclient, UERANSIM CLI, ADB, gRPC/REST clients, serial console

Execution and orchestration

Parallelism, ordering, timeouts, provisioning, lab reservation.

Per commit: containers. Nightly: a reserved lab slot with one O-RU. Weekly: the scale rig. A queue for scarce hardware, or people route around the tests.

e.g. GitLab CI, Jenkins, Kubernetes with Multus/SR-IOV, a reservation service

Reporting and artifacts

Results, history, evidence on every failure.

Every failed system test attaches pcaps from N2, F1, and fronthaul, NF logs, the PTP offset trace, and any core dump. Without them nobody can debug a "PDU session failed" red.

e.g. Allure, ReportPortal, JUnit XML, Grafana snapshots

Designing one: the order that works

  1. Driver abstraction first. Tests express intent ("attach 50 UEs", "push an A1 policy", "cut the fronthaul fibre"), never raw protocol. Each driver has a simulated and a real backend behind the same interface.
  2. Topology as code. One declarative spec for the network under test drives docker-compose, Kubernetes, and lab reservation.
  3. Deterministic identity. Every run gets an ID; every SUPI range, tenant, and PDU session created carries it. Reruns are idempotent; teardown is one predicate.
  4. Async oracles. eventually, always, observed. Telecom assertions are never synchronous; forbid sleep().
  5. Fault injection as an API. Fibre pull, PTP loss, pod kill, partition, latency. If chaos is manual it never runs.
  6. Evidence on failure by default. Capture at the seam that failed, plus one seam either side.

Foundations

3. Levels on a RAN and core

A level answers how much of the system is under test. On this stack the levels are unusually literal: each step up crosses one more interface from the diagram.

The pyramid rule: put a test at the lowest level that can falsify the behaviour. A NAS state machine bug does not need a radio. A PTP phase bug cannot be found without one.

THE TEST PYRAMID
The test pyramidTest pyramid for telecom: unit at the base, then component / API (one NF), integration (one seam), system (sim, RF, scale), and field / acceptance at the top. The base is many, fast and cheap; the top is few, slow and costly.UnitComponent / API (one NF)Integration (one seam)System (sim, RF, scale)Field / acceptancemany · fast · cheapfew · slow · costly

Test pyramid for telecom: unit at the base, then component / API (one NF), integration (one seam), system (sim, RF, scale), and field / acceptance at the top. The base is many, fast and cheap; the top is few, slow and costly. Each tier carries a row of dots, illustrative only, that halves from 24 at the base to one at the top.

  • unit, the base: many, fast, cheap
  • each tier up: fewer, slower, costlier
Five levels; each step up crosses one more interface from the map. Put a test at the lowest level that can falsify the behaviour. The dots in each tier are illustrative: many tests at the base, few at the top.
LevelWhat is under testExample on this systemTools
UnitOne function or module, peers mockedNAS 5GMM state transitions; RLC AM segmentation; PFCP IE encoder; a YANG validator for M-Plane; the scheduler's PRB allocation routineGoogleTest/Catch2 (OAI, srsRAN), pytest for Python NFs, Go testing for free5GC, gMock, ASan on every run
Component / APIOne NF or node, real infra, driven through its public interfaceAMF alone with a scripted gNB: NGSetup, Registration, check SBI calls to AUSF/UDM match the OpenAPI. O-RU alone: NETCONF get-config, edit-config, notifications per the O-RAN M-Plane YANGPacketRusher, scripted NGAP/SCTP client, Schemathesis on the 3GPP OpenAPI, ncclient, WireMock for peer NFs
IntegrationTwo real elements across one interfacegNB and AMF over N2 (NGAP). O-DU and O-CU over F1AP. O-DU and O-RU over Open Fronthaul CUS-plane plus M-Plane. SMF and UPF over N4. Where IE mismatches, version skew, and encoding bugs surfaceWireshark/tshark at the seam, containerlab, netem, a bench O-RU for fronthaul
SystemWhole path UE to RAN to core to DN, black box, against requirementsRegistration, PDU session, data, mobility, release. Three rungs, always labelled: sim (UERANSIM + Open5GS), real RF (SDR or vendor O-RU + real UE in a shielded box), scale (Landslide / LoadCore / TM500). Includes load, failover, soak, securityUERANSIM, srsRAN/OAI, Open5GS/free5GC, TM500, Landslide, TRex on N3/N6, Robot Framework or pytest
Field / acceptanceReal spectrum, real users, the customer's KPIsDrive/walk test for RSRP/SINR/throughput/handover; pre-production soak; PoC exit criteria signed by the operator or enterprise. FAT/SAT for hardwareTEMS, Nemo, QualiPoc, R&S TSME scanner; operator KPI dashboards

The three rungs of system test are not interchangeable. A simulator throughput number is not a real-RF number and neither is a carrier-scale number. Fading, real UE behaviour, and timing exist only over the air; session-rate cliffs exist only at scale. Label every result by rung. A test plan that does not say which rung a KPI is measured on is a wish list.

On coverage

80% line coverage is the usual target for stack code, 60% a floor, and neither is a quality score. An ASN.1 decoder can be 100% covered by tests that never assert on a single IE value. Branch coverage is more honest; mutation testing (module 9) is the real answer.

Foundations

4. Types by purpose

A type answers what property is being checked. Types run at every level; a type is not a level. Functional tests exist at unit (does the encoder encode), integration (does F1 Setup carry the cell config), and system (does the UE get an IP). Keeping the two axes separate is the most common vocabulary fix a test team needs.

Functional

Functional

Does it do what the spec or requirement says.

UE registers with the correct slice; PDU session gets the QoS flow the SMF selected; O-RU applies a carrier config over M-Plane and reports it back.

Any level. Same tools as the level
Functional

Regression

Re-running existing tests after a change. A reason to run tests, not a kind.

Every merge to the DU repo re-runs the F1 and fronthaul integration suite on simulator; nightly re-runs on the bench O-RU.

e.g. CI on merge, nightly lab runs
Functional

Smoke

Fast, shallow, first. Is this build worth testing further?

Deploy core and gNB, one UE registers, one PDU session, one ping across N6, no NF crashed. Three minutes. Fail blocks everything downstream.

e.g. 10 to 20 tagged tests post-deploy
Functional

Sanity

Narrow and deep on one change before the full regression.

Fix to PFCP session modification: run only the N4 tests plus one PDU session, not the whole suite.

e.g. targeted subset by ticket
Functional

Exploratory

Skilled, unscripted, manual. Finds what no script anticipated.

Lab bring-up of a new O-RU: pull the fibre mid-session, power-cycle during a NETCONF edit-config, attach two UEs with the same SUPI. The interesting bugs on a new radio are found this way first.

e.g. session charters, a notebook, Wireshark open
Functional

Installation, upgrade, recovery

Fresh deploy, upgrade N-1 to N, rolling upgrade of one NF at a time, rollback, restore config from backup.

Upgrade the O-DU while the O-CU stays on the previous release: F1AP version negotiation, IE compatibility, cell recovery time.

e.g. Helm rollouts, versioned lab snapshots
Non-functional

Performance: load, stress, soak, spike

Load: KPI budgets at expected traffic. Stress: past capacity, where and how it fails. Soak: days or weeks. Spike: surge.

TRex on N3 for UPF Gbps/Mpps and latency; Landslide for registrations per second and concurrent sessions; a 7-day soak watching AMF RSS and PTP offset.

e.g. TRex, iperf3, PacketRusher, Landslide, LoadCore, TM500
Non-functional

Security

Scans, fuzzing on protocol parsers, auth on SBI and NETCONF, pentest pre-release.

Fuzz the NGAP/NAS decoder with malformed PDUs; verify SBI mTLS and OAuth2 between NFs; M-Plane over TLS/SSH with proper certificates; no default credentials on the O-RU.

e.g. Trivy, Semgrep, boofuzz, AFL++, nmap, ZAP on the SMO
Non-functional

Resilience and chaos

Inject failure on purpose, verify the design's recovery claim.

Kill the AMF pod mid-registration; partition CU-CP from CU-UP; add 50 ms on F1-U; skew the O-DU clock; drop and restore PTP. Does the cell hold, re-establish, or fail closed as specified?

e.g. Chaos Mesh, Litmus, tc netem, Toxiproxy, an optical attenuator
Non-functional

Conformance and interoperability

Follows the standard; works with other vendors.

3GPP conformance for UE/gNB; O-RAN WG4 fronthaul conformance for the O-RU; M-Plane conformance against the YANG; IOT with another vendor's O-DU at an OTIC or plugfest. Separate suite, owner, cadence.

e.g. Keysight, VIAVI, R&S CMX, OTIC labs, O-RAN test specs
Non-functional

Timing and sync

Unique to RAN and first in bring-up order.

PTP/SyncE from grandmaster through O-DU to O-RU inside the ±1.5 µs phase budget; holdover when GNSS drops; T1a/T2a fronthaul delay windows.

e.g. Calnex Paragon/Sentinel, ptp4l/phc2sys logs, GNSS simulator

Foundations

5. How tests get executed

Manual

A human executes. Scripted manual (follow the test case) is what you automate. Exploratory is what you cannot automate and is where a good system tester earns their pay: every new radio, every new vendor pairing, every new release gets an exploratory session before the automation is trusted.

Automation

Tests executed by code. Not only "automated manual tests": TRex load runs, 7-day soaks, chaos injections, fuzzing, and per-commit simulator suites were never manual. Automation pays only when the suite is reliable enough that red means something. A flaky E2E suite gets ignored within a month.

Black, white, grey box

Black box: through the external interface only (system, field). White box: with code knowledge (unit). Grey box: external stimulus, internal observation. A system tester who reads the AMF's Prometheus counters and the DU's log while driving a UE through registration is testing grey box, and that is the right default for distributed systems.

Static

Examine code without running it. Non-negotiable for C/C++ stack code.

Tools: clang-tidy, cppcheck, CodeQL, Semgrep, golangci-lint, mypy, MISRA checkers on embedded targets; ASan/UBSan builds in CI count as nearly static.

Practices: TDD, BDD, shift-left

TDD for protocol encoders and state machines works well: the spec gives you the test before the code. BDD (Given/When/Then) is common in operator test plans because acceptance criteria are already written that way. Shift-left in telecom means: simulator in CI before the lab, static analysis before the simulator, and conformance subsets before the OTIC visit.

Practice

6. Test design from the spec

Telecom is spec-driven, which is an advantage: the test cases are latent in 3GPP and O-RAN documents. The techniques below are how you extract them without producing ten thousand redundant cases.

Procedures become scenarios

Every 3GPP procedure (TS 23.502 for the core, TS 38.331 for RRC, TS 38.413 for NGAP, TS 38.473 for F1AP) is a sequence diagram with a success path and enumerated failure paths. Each success path is one E2E scenario. Each failure path, with its cause code, is a negative scenario. Registration alone yields the accept path plus rejects for illegal UE, PLMN not allowed, roaming not allowed, no suitable cells, congestion, and the abnormal cases (T3510 expiry, lower-layer failure, collision with deregistration).

State machines become transition tables

5GMM (deregistered, registered-initiated, registered, deregistered-initiated, service-request-initiated), 5GSM, RRC (idle, inactive, connected), SCTP associations. Test every valid transition, then every event arriving in a state that must ignore or reject it. The invalid transitions are where implementations diverge.

IE tables become boundary cases

Every message has an IE table with presence (mandatory, optional, conditional), criticality (reject, ignore, notify), range, and multiplicity. Each row is a set of cases: absent when mandatory, present when conditional condition is false, at minimum, at maximum, one over maximum, unknown IE with criticality reject versus ignore. This is equivalence partitioning and boundary value analysis applied to ASN.1, and it finds most interop bugs before the plugfest.

Timers become negative cases

T3510, T3580, T3346, RRC inactivity, PFCP heartbeat, SCTP heartbeat, NGAP guard timers. For each: expiry once, expiry at the retry limit, response arriving one tick after expiry, and clock skew between peers.

Configuration space becomes a pairwise set

Band, bandwidth, subcarrier spacing, TDD pattern, MIMO layers, slice count, security algorithms, PDU session type: exhaustive is thousands of combinations; pairwise is dozens. Generate the set, then add the specific combinations the operator will deploy.

Mobility and multi-UE become scenario grids

Intra-DU, inter-DU intra-CU (F1), inter-CU (Xn), inter-AMF (N2) handover; RRC re-establishment; RRC inactive to connected; two UEs with the same SUPI; a UE that never answers the security-mode command. Each cell in the grid is a case; each failing cell is usually a retainability KPI in the field.

Risk-based depth

Not every case gets every rung. Rank by likelihood (new code, new vendor pairing, historic defect density) times impact (service-affecting, security, regulatory) and give the top of the list all three system rungs and a soak; give the bottom the simulator and move on.

Practice

7. Strategy by rung

A telecom test strategy is organised around the three rungs of system test, because they are the resource constraint. Everything cheap runs on every commit; everything that needs hardware is scheduled.

RungWhat it provesWhat it cannot proveCadenceGate
Static, unit, integrationEncoders, state machines, one-seam behaviourAnything about timing, RF, or scaleEvery commitMerge
System, simProcedures end to end, failover, chaos, regression breadthPTP, fading, real UE behaviour, capacity cliffsEvery merge and nightlyNightly green
System, real RFTiming, fronthaul, real UE, RF quality, exploratory on new radiosScale, field propagationNightly subset, weekly fullRelease candidate
System, scaleCapacity, session rate, soak stability, throughput budgetsField conditionsWeekly, pre-releaseRelease
Conformance and IOTStandard compliance, multi-vendorProduct-specific behaviourPer release, OTIC per certificationCommercial
FieldCustomer KPIs under real conditionsNothing further; it is the last rungPer deploymentAcceptance

Entry and exit criteria that mean something

Entry to the RF rung: sim suite green, PTP locked, spectrum clear in the shielded box, lab reserved. Exit from the scale rung: KPI thresholds met with the method named, no NF crash in the soak, no open severity-1. Exit criteria written as "all tests pass" get waived on release day; criteria written as specific KPIs with thresholds do not.

PoC exit criteria

For a proof of concept with an operator or enterprise, write the exit criteria before the hardware ships: which procedures, on which rung, at which KPI threshold, with which test method, witnessed by whom. A PoC without written exit criteria ends in a disagreement about whether it passed.

Estimation

Simulator cases cost minutes each to run and hours to write. RF cases cost a lab slot plus setup; budget a day per new radio for bring-up before any case runs. Scale cases cost the rig for a day and analysis for another. Soak is calendar time: budget two weeks of continuous rig for a release. Write the assumptions next to the numbers.

Practice

8. Lab and environment

Most telecom test programmes fail in the lab, not in the test design. A lab nobody can reproduce, a radio three teams fight over, a grandmaster with drifting config: these produce more false failures than any number of bad assertions.

Environment tiers

TierContentsOwnsIsolation
DeveloperOpen5GS or free5GC, UERANSIM, srsRAN or OAI gNB in containersUnit, integration, one-seamPer machine
CI, ephemeralSame stack, Kubernetes namespace per run, Multus for the N2/N3 planes, netem for impairmentSmoke, sim system suite, chaosPer pipeline
Bench RFO-DU server with SR-IOV NIC, one or two O-RUs, PTP grandmaster, shielded box with real UEs, spectrum analyser, optical attenuatorsFronthaul integration, timing, RF system rung, exploratoryReserved per slot
ScaleLandslide or LoadCore, TM500, TRex hosts, production-sized coreLoad, soak, stressReserved per run
ConformanceCommercial test system or OTIC bookingCertification evidenceScheduled
Field / pre-productionLicensed or shared spectrum, real siteAcceptancePer deployment

Rules that keep the lab trustworthy

  • Provision from code, including the grandmaster config, switch VLANs, and NIC settings. If it cannot be rebuilt from a repo, it will drift.
  • Reserve every piece of hardware through a queue. A radio taken by a chat message is a radio with unknown state.
  • Pin versions of simulators and test tools as strictly as product versions. A UERANSIM upgrade that silently changes NAS behaviour looks like a product regression.
  • Timing first: verify PTP lock and offset before any RF test run, automatically, as an entry check.
  • Shielded box for real UEs: legal, repeatable, and it keeps the neighbours' networks out of your pcaps.
  • Reset after every destructive test, and snapshot config before every exploratory session.

Test data

Subscriber provisioning (SUPI ranges, K/OPc, slices, DNNs) generated per run and loaded into UDM/UDR by the harness. Every UE a test creates carries the run ID in its SUPI range so cleanup is one query and parallel runs never collide. Real SIM cards for the RF rung are inventory: tracked, provisioned to match, never hand-edited.

Practice

9. Telecom techniques

pcap-as-assertion

Capture at the seam, assert on the dissected protocol. The most powerful oracle in telecom test.

tshark -r n2.pcap -Y "ngap.procedureCode == 14" to prove InitialContextSetup carried the S-NSSAI. pyshark to assert F1 Setup Response listed the expected cells.

e.g. tshark, pyshark, scapy for crafting

Property-based testing

State a law, generate thousands of inputs, shrink the failures.

decode(encode(pdu)) == pdu for every NAS and NGAP message; PFCP IE round-trips; RLC reassembly under any segmentation. Finds encoder bugs weeks before a plugfest would.

e.g. Hypothesis, QuickCheck, rapid

Fuzzing

Malformed and random input at every parser that touches the network.

AFL++/libFuzzer on the ASN.1 decoders (RRC, NGAP, F1AP, E2AP); boofuzz over SCTP at the AMF; malformed YANG payloads at the O-RU NETCONF server.

e.g. AFL++, libFuzzer, boofuzz

Mutation testing

Break the code on purpose; see if tests notice.

Flip a comparison in the QoS flow mapper; if no test fails, the 85% coverage on that module is fake.

e.g. mutmut, Stryker, PIT

Contract testing

Consumer and provider agree on the interface without running both.

SBI is OpenAPI-defined by 3GPP, so AMF-as-consumer and AUSF-as-provider can be contract-tested from the spec. Schemathesis fuzzes straight off the YAML.

e.g. Schemathesis, Pact, Dredd

Impairment and topology emulation

Make the transport behave like the field without the field.

netem on F1-U for midhaul latency and jitter; optical attenuator on the fronthaul fibre; containerlab topologies with a real RU on one leg; Multus/SR-IOV for CNF test beds.

e.g. tc netem, containerlab, Toxiproxy

Statistical oracles

Pass/fail as a distribution, not an equality.

Throughput asserted as p50 and p95 over a window against a threshold, with enough runs to separate drift from noise. A test that asserts throughput == 812 is worthless on real RF.

e.g. Prometheus range queries, numpy in the harness

KPI-driven soak

Long runs judged by KPI trend, not by pass at the end.

7 days at moderate load, sampling registration success, session drop rate, RSS per NF, and PTP offset hourly; fail on trend, not on final value.

e.g. Grafana alert rules as assertions

Practice

10. Defects and RCA

Lifecycle

NewTriagedAssignedFixedReady for retestVerified on the rung it was foundClosed

Verification happens on the rung where the defect was found, at minimum. A fronthaul bug found on the bench is not verified on the simulator.

Severity in telecom terms

Severity
Definition
Example
Release effect
Critical
Service-affecting for all users, or data/security exposure
AMF crash on malformed NAS; cell down on PTP holdover; keys logged in clear
Stop
Major
Service-affecting for a subset, or a KPI outside threshold
Handover failure on inter-DU; session drop rate above target; slice not honoured
Fix before release
Minor
Not service-affecting
Wrong counter name in PM file; M-Plane notification late but correct
Schedule

Priority is set separately by the customer impact and timeline. A minor-severity defect blocking an OTIC certification is high priority.

What a telecom defect report contains

  • Rung and environment: sim, bench RF (which radio, which firmware), scale, field. Build IDs for every element in the path.
  • Capture-point discipline: which seam the pcap is from, which plane, which timing domain. A fronthaul eCPRI capture and an SBI HTTP/2 capture are different worlds.
  • The procedure and the step it failed at, with the cause code if one was sent.
  • Minimal reproduction: one UE, one PDU session, exact config.
  • Evidence: pcaps from the failing seam and one either side, NF logs, PTP offset, core dump if any, config snapshot.
  • Frequency across runs, and whether it reproduces on a lower rung.
  • KPI impact: which KPI, by how much, for which users.

Root cause analysis

For every escaped defect and every critical, ask which level should have caught it. A fronthaul IE mismatch that reached the field should have been a one-seam integration test; a session leak found by a customer should have been a soak. The answer is a new test at that level, and the escape count by level is the metric that tells you where the strategy is thin.

Practice

11. KPIs and reporting

Telecom has a settled KPI vocabulary. Use it in test plans so the operator's acceptance team and your system test team are measuring the same things.

FamilyKPIMethodRung
AccessibilityRRC setup success rate, registration success rate, PDU session setup success rate, setup timeCounters at CU-CP and AMF/SMF, correlated with pcapsSim, RF, scale
RetainabilitySession drop rate, abnormal release rate, RRC re-establishment rateCounters plus release cause distributionRF, scale, field
IntegrityDL/UL throughput peak and cell-edge, latency, jitter, BLERiperf3/TRex on N3 and N6; UE-side for cell-edgeRF, scale, field
MobilityHandover success rate, ping-pong rate, interruption timeScripted mobility on TM500 or attenuator-driven on the benchRF, scale, field
CapacityConcurrent UEs and sessions, control-plane events per second, soak stabilityLandslide/LoadCore; 7-day soak with hourly samplingScale
RFRSRP/RSRQ/SINR distributions, EVM, ACLR, coverage %Spectrum and vector signal analyser; drive testRF, field
TimingPTP offset, holdover duration, fronthaul delay marginSync analyser; ptp4l logsRF
O-RANInterface conformance pass %, interop certificate, fronthaul conformanceTest spec execution; OTICConformance

Test-programme metrics

Requirement coverage by procedure and by rung; pass rate trend per rung; open defects by severity and by seam; escapes by level (the RCA metric); flaky rate on the sim suite; lab utilisation and queue wait; time from commit to first sim red.

The release report

One page per rung. What ran, on which hardware and firmware, KPI results against thresholds with the method named, open defects with severity and seam, known limitations, and a recommendation: ready, ready with conditions, not ready. Conformance evidence is attached as its own artifact set because it will be asked for by a certification body or an operator's procurement, not by engineering.

Tooling

12. Tools and stack

LayerOpen-source and generalTelecom-specific
UnitGoogleTest/Catch2 (C/C++), pytest, Go testing, JUnit; gMock/unittest.mock; gcov/lcov, coverage.py; ASan/UBSan/TSan buildsStack-native suites in OAI, srsRAN, Open5GS, free5GC, Magma; asn1c-generated decoder tests
Component / APISchemathesis, Postman/Newman, REST Assured, WireMock, testcontainersPacketRusher (gNB/UE toward core), ncclient for NETCONF/YANG (M-Plane, O1), scripted NGAP/PFCP clients, 3GPP OpenAPI YAMLs as the contract
Integration (one seam)containerlab, docker-compose, tc netem, ToxiproxyWireshark/tshark with NGAP, NAS-5GS, F1AP, E1AP, E2AP, PFCP, GTP-U, HTTP/2, eCPRI dissectors; a bench O-RU for fronthaul; FlexRIC for E2
System, sim rungKubernetes with Multus/SR-IOV, GitLab CI/Jenkins, Robot Framework, pytestUERANSIM, Open5GS/free5GC, srsRAN/OAI gNB, FlexRIC + xApp; RU emulators for fronthaul
System, real-RF rungADB for real UEs, shielded boxSDR (USRP) + srsRAN/OAI, vendor O-RU, real UE, spectrum analyser, attenuators, sync tester
System, scale rungk6/Locust for SMO and SBI RESTTRex and iperf3 on N3/N6, Spirent Landslide, Keysight LoadCore/UeSIM/RIC Test, VIAVI TM500/TeraVM, PacketRusher for control-plane rate
Chaos / resilienceChaos Mesh, Litmus, Gremlin, tc netemOptical attenuator, PTP/GNSS disruption, fibre pull, pod kill on AMF/SMF/UPF/CU-CP
Timingptp4l, phc2sys, chrony logsCalnex Paragon/Sentinel, GNSS simulator, 1588 analysers
Conformance / IOTR&S CMX/CMW, Anritsu MT8000A, Keysight and VIAVI O-RAN test systems, O-RAN WG4 fronthaul and M-Plane conformance specs, OTIC labs, plugfests
FieldTEMS, Nemo, QualiPoc, R&S TSME scanner; Atoll/iBwave for planning
SecurityTrivy, Semgrep, CodeQL, Snyk, ZAP, nmapAFL++/libFuzzer on ASN.1 decoders, boofuzz over SCTP, SBI mTLS/OAuth2 checks, NETCONF-over-TLS/SSH checks
Debug and triagegdb + core dumps, valgrind/ASan on reduced-scale repros, strace, perf, tcpdump, journalctl, serial console (minicom/screen) to radios, Prometheus/Grafana on NF metrics, centralised logs
Test management and reportingJira with Zephyr or Xray, TestRail; Allure, ReportPortal, JUnit XML; pcaps, logs, and cores attached to every failure

Browser automation (Selenium, Playwright) belongs to the SMO and portal UI only. Nothing in the RAN or core is browser-driven; a telecom test role that leads with Selenium is a portal QA role.

Tooling

13. Run a pipeline

A CI gate for this stack, cheap first, expensive last. Run it clean, then inject a bug at each level and watch where it gets caught and what the failure message can tell you.

THE CI GATE
Staticclang-tidy, ASan build, secretspassUnitstack + NF modules, 90spassIntegrationN2, F1, N4, FH seamspassSmokesim: 1 UE, 1 PDU, 1 pingpassSystem (sim)procedures + chaospassSystem (RF)bench O-RU, real UEpassScaleTRex N3, LandslidepassConformanceO-RAN subset, weeklypasscheap first, expensive last
Staticclang-tidy, ASan build, secretspassUnitstack + NF modules, 90spassIntegrationN2, F1, N4, FH seamspassSmokesim: 1 UE, 1 PDU, 1 pingpassSystem (sim)procedures + chaospassSystem (RF)bench O-RU, real UEpassScaleTRex N3, LandslidepassConformanceO-RAN subset, weeklypasscheap first, expensive last
Staticclang-tidy, ASan build, secretspassUnitstack + NF modules, 90spassIntegrationN2, F1, N4, FH seamspassSmokesim: 1 UE, 1 PDU, 1 pingpassSystem (sim)procedures + chaospassSystem (RF)bench O-RU, real UEpassScaleTRex N3, LandslidepassConformanceO-RAN subset, weeklypasscheap first, expensive last
> Run clean build
pass Static
pass Unit
pass Integration
pass Smoke
pass System (sim)
pass System (RF)
pass Scale
pass Conformance
All eight stages green.
Nothing injected, nothing caught. The build is a release candidate; the conformance subset ran because it was the weekly slot.

A pipeline of eight stages in order: Static, Unit, Integration, Smoke, System on the simulator, System on real RF, Scale and Conformance. The clean run plays once when the figure comes into view. Five buttons run a clean build or inject a NAS encoder bug, an F1 IE mismatch, PTP drift or an AMF failover bug. Stages turn to running, pass or FAIL in turn; after a failure the later stages are greyed as not run. A log below prints each result with the failure message and the level that found it.

  • the run: the stage running now
  • passed
  • the stage that caught the bug
  • not reached; dashed, not run after a failure
Eight stages, cheap first, expensive last. The clean run plays once when the figure comes into view: a cheap stage finishes fast, an expensive one takes longer. Run it clean or inject one bug and watch which stage catches it; the log prints the failure message and where it was found.

The cost curve: the NAS bug named the function in 90 seconds. The F1 mismatch needed a pcap. The PTP drift passed every software stage and only failed on real hardware. The failover bug survived to the chaos step and produced a message that names no component at all, which is where the next module begins.

Tooling

14. The debug ladder

When a system test on this stack goes red, the failure rarely names the culprit. Work the ladder top to bottom; do not skip a rung because the symptom "looks like" a later one.

  1. TimingPTP locked at O-DU and O-RU? Offset inside budget? Holdover? On TDD, bad sync mimics every other failure. Check ptp4l/phc2sys logs and the O-RU sync state over M-Plane first.
  2. TransportFibre, VLANs, MTU, routes. Can the DU reach the RU's M-Plane address? Is fronthaul on the right VLAN with the right priority? ping, ip, ethtool, switch counters.
  3. AssociationsSCTP up on N2 and F1-C? NGSetup and F1 Setup succeeded? E1 between CU-CP and CU-UP? E2 to the RIC if in play? ss -S, Wireshark on sctp, ngap, f1ap.
  4. Subscriber and authSUPI provisioned in UDM/UDR? Keys match the SIM? Slice allowed? The NAS reject cause on Uu tells you; nas-5gs filter.
  5. SessionPDU session establishment: SMF selected, N4 session created on UPF, QoS flows mapped, IP allocated. pfcp and ngap filters, SMF/UPF logs.
  6. Data pathGTP-U on N3, F1-U tunnels, N6 routing and NAT. tcpdump on N3 and N6; TEIDs match both ends.
  7. PerformanceOnly once everything above is clean: throughput, latency, CPU pinning, hugepages, NUMA, IRQ affinity. perf, DPDK stats, TRex.

Product, harness, or environment

Before opening a defect: did the simulator version change, did the lab config drift, did someone else have the radio. In a young suite a third of system reds are not product bugs. The harness must make this cheap to answer: pinned versions, provisioning from code, reservation logs.

Where gdb and valgrind enter

A crash anywhere in the ladder ends with a core dump. gdb on the core: bt, thread apply all bt, frame, info locals, why the symbols are missing (stripped binary, no debuginfo, cross-compiled target needing set sysroot). Know how cores are produced in a container: ulimit -c, core_pattern, systemd-coredump, and why a pod has none.

valgrind appears in one telecom scenario: a soak run shows RSS growing on the AMF or DU. Memcheck localises it, but at 10 to 50x slowdown it cannot run under real traffic or real-time threads, so reproduce at reduced scale on a debug build, or use ASan/LSan compiled in. A leak and unbounded growth are not the same thing: glibc arena behaviour, caches, and fragmentation all look like leaks.

The output of a debug session is not a fix. It is a defect report with the pcap from the right seam, the core, the logs, the config, the rung it was seen on, and a reproduction that takes the developer straight to the frame.

Wrap up

15. Check yourself

Question 1 of 8

A test starts a real O-DU and a real O-CU in containers, drives F1 Setup, and asserts with tshark that the Setup Response lists two cells. What level?

Question 2 of 8

UERANSIM registration passes on every commit. On the bench O-RU the same test fails intermittently. What do you check first?

Question 3 of 8

A TRex run pushing 20 Gbps through the UPF over N3 is:

Question 4 of 8

The 7-day soak shows the DU's RSS climbing 30 MB a day under real traffic. Right next step?

Question 5 of 8

Which belongs in the O-RAN conformance track rather than the functional suite?

Question 6 of 8

A test plan lists "DL throughput ≥ 800 Mbps". What is missing?

Question 7 of 8

Registration Reject with cause "PLMN not allowed" arrives during a test that expected success. Which technique produced the case that should have existed for it?

Question 8 of 8

A fronthaul IE mismatch between two vendors reached a customer site. In RCA, which level should have caught it?

Wrap up

16. Interface glossary

Uu
Air interface between UE and gNB. RRC and NAS ride on it. 3GPP TS 38.300 series.
Open Fronthaul (CUS-plane)
O-RAN 7.2x split between O-DU and O-RU: control, user, synchronisation planes over eCPRI. Microsecond timing domain.
M-Plane
Management plane for the O-RU: NETCONF/YANG from the O-DU or SMO. Configuration, software, notifications, sync state.
F1-C / F1-U
O-DU to O-CU: F1AP control (TS 38.473) and GTP-U user plane.
E1
CU-CP to CU-UP: E1AP bearer context management (TS 38.463).
N2
gNB to AMF: NGAP over SCTP (TS 38.413). Registration, context setup, PDU session resources.
N3
gNB to UPF: GTP-U user plane.
N4
SMF to UPF: PFCP session control (TS 29.244).
N6
UPF to data network.
SBI
Service-based interface between core NFs: HTTP/2 with 3GPP-published OpenAPI (TS 29.5xx series).
Xn
gNB to gNB: handover and dual connectivity (TS 38.423).
E2
Near-RT RIC to E2 nodes (DU and CU): E2AP with service models such as KPM and RC.
A1
Non-RT RIC to Near-RT RIC: policy management.
O1
SMO to O-RAN managed elements: NETCONF/YANG configuration, VES telemetry, PM files.
O2
SMO to O-Cloud: infrastructure and deployment management.
PTP / SyncE
IEEE 1588 phase and SyncE frequency distribution from grandmaster through O-DU to O-RU. ±1.5 µs end-to-end phase budget is the usual TDD target.
OTIC
O-RAN Open Test and Integration Centre: accredited labs that run conformance and interoperability specs and issue certificates.
Rung
One of the three system-test environments: simulator, real RF, scale. Results are always labelled by rung.

Written by telecogeco, a ugeco brand. The levels, types and techniques are general test practice for a RAN and core; the architecture map, the pipeline and the quiz are illustrations with synthetic results, not a record of any test run.