Learn PLCs free
Evidence-led guide3,753 words

PLC Program Architecture, Testing and Code Quality: Practical Guide

Design PLC software for deterministic tests, apply review and static-analysis gates, automate unit and integration regression, and connect results to emulator, HIL, FAT and SAT evidence.

PPI
PLC Programming IO Editorial Team
Sourced guidance with documented review and correction standards

Review status: Editorially reviewed against current IEC 61131-3:2025 scope, PLCopen Coding Guidelines and Software Quality Metrics, current CODESYS Test Manager 5.1 documentation, Beckhoff TE1200 TwinCAT PLC Static Analysis 2.10.2 material, current Siemens TIA Portal Test Suite V21 and S7-PLCSIM Advanced V8 surfaces, current Rockwell FactoryTalk Logix Echo product material, ISA-88/ISA-95 context and current functional-safety lifecycle references; exact tool, compiler, library, emulator, target, task, I/O, motion, network, safety and physical process test behavior require project-specific verification

Direct answer

Good PLC program testing begins with architecture, not a test tool. Separate physical I/O mapping, signal qualification, reusable equipment behavior, sequence coordination and final output arbitration. Pass time, inputs and dependencies through explicit interfaces where the platform supports it. Then test small deterministic units quickly, multi-object behavior in integration, controller execution in simulation/emulation, real I/O and devices in HIL/FAT, and the installed process in SAT.

A compile is not a test; a simulator animation is not field validation; code coverage is not requirement coverage; and FAT does not replace unit regression. Use each gate for the faults it can reveal:

  • review and static analysis for ownership, unsafe constructs, rule violations and maintainability;
  • unit tests for functions, calculations, state transitions, priorities and boundaries;
  • integration tests for object interactions, task order, handshakes, HMI and protocols;
  • emulation for target/runtime behavior supported by the exact emulator;
  • hardware tests for I/O, timing, networks, drives and real device diagnostics; and
  • FAT/SAT for machine, process, operator, recovery and site requirements.

Every changed requirement should map to at least one positive, negative, boundary and recovery test as applicable. Record exact project hash, compiler/tool/library/firmware versions, initial state, stimuli, expected result, actual result, timing and first failure. Safety application validation remains a separate controlled lifecycle on the exact approved target.

Download the 24-case PLC test plan, 24-point code-review checklist and deterministic motor-object Structured Text example.

Testable PLC software architecture from field I O through input adapter equipment objects sequence and single output arbiter with diagnostics and HMI
Test seams follow ownership boundaries. One final arbiter writes physical outputs; equipment objects expose command, state, feedback and fault evidence.

Turn requirements into testable contracts

Replace vague behavior with observable state

“Start the motor normally” cannot produce a decisive assertion. A testable contract states:

When StartReq rises while Auto is selected, permissives are healthy, no fault is active and stopped feedback is proven, the motor object enters Starting, requests the run output, waits no longer than 30 task ticks for qualified running feedback, then enters Running; otherwise it removes the command, latches the first applicable fault and requires an authorized healthy reset.

That sentence names initial state, trigger, guards, command, feedback, timeout, fault response and reset. Split it into requirement IDs and tests.

Contract surface Example Test oracle
input/request one rising StartReq with request ID if remote exactly one acceptance/rejection
permissive Auto, overload healthy, no trip, process ready start cannot leave Stopped when any required guard is false
state Stopped → Starting → Running only allowed transitions occur
command RunCommand true in Starting/Running only output intent follows state and one owner
feedback independent qualified RunFeedback command never substitutes for proof
timeout 30 executions in deterministic harness; field time in target design exact just-before/at/after boundary
fault first-out code and latched Failed state earliest cause retained; later symptoms do not overwrite
reset fault clear, feedback stopped, conditions healthy, authorized edge reset cannot restart automatically

Create a trace matrix: requirement → design object → source revision → static rule/review → automated tests → integrated/FAT/SAT cases → release evidence. A single acceptance test may cover several requirements, but each requirement must still identify its decisive observation.

Include abnormal and simultaneous cases

At minimum consider:

  • minimum, maximum, zero, invalid and overflow values;
  • input transition just before/at/after a timer or count boundary;
  • simultaneous Start/Stop, Set/Reset, fault/reset and mode changes;
  • held versus pulsed requests;
  • power, warm restart, download, task disable and re-enable;
  • communication stale, bad quality, duplicated or reordered command;
  • feedback that arrives late, disappears while running or contradicts command;
  • array maximum, empty set and unexpected enumeration/state;
  • first fault followed by secondary faults; and
  • recovery that fails halfway and needs rollback.

Test priority deliberately. Accidentally passing one execution order is not a priority specification.

Architecture for testability

Separate hardware adapters from control objects

Use five practical layers:

Layer Owns Inject/test without field hardware Must still be proven later
I/O adapter raw address, polarity, scaling, quality and source age substitute typed input contract real wiring/module/filter/update behavior
equipment object requests, permissives, state, command, feedback timeout and fault deterministic input/time seam exact target task and device feedback
sequence coordination among equipment and process steps test objects/fakes with state contracts actual devices, timing and process interactions
output arbiter final ordinary-control writer, mode/manual priority and diagnostics assert one command owner physical output and safe-state design
platform adapter vendor blocks, communications, retentive/restart integration mocked interface where practical exact runtime, firmware, network and libraries

Do not hide physical addresses, HMI writes, timer instances, output coils and fault reset inside one 2,000-line routine. Tight coupling makes every test an expensive system test and permits multiple writers.

Make state and time controllable

A stateful function block should expose enough state and fault evidence to test, while protecting internal implementation details that consumers do not need. Avoid using wall-clock delay in unit tests. Provide a deterministic clock/tick seam or call the block with a test scheduler so the suite advances time predictably.

The downloadable example uses TimeoutTicks and one call as one deterministic tick. That makes boundaries reproducible, but production engineering must translate ticks into an exact periodic task and verify worst-case timing. The pattern is not a universal replacement for target timers.

Keep one physical-output writer

Equipment objects should generally produce requests/commands into one final mapping or arbitration layer. When Auto, Manual, HMI, maintenance and safety-related interfaces all write the physical output tag in separate routines, unit tests cannot establish a single priority and online diagnosis becomes execution-order archaeology.

Safety outputs remain owned by the certified safety application/architecture. Standard logic can request or observe permitted state but cannot establish safety integrity through an ordinary arbiter.

Use a PLC testing pyramid

Many fast deterministic tests, fewer expensive system tests

Level Test object Typical speed Best defects Cannot establish alone
pure/unit functions, methods, FB state transitions seconds/minutes for suite calculations, boundaries, priority, state and reset target execution or device behavior
integration several objects, sequences, HMI/protocol adapter minutes interface, ownership, task/order and handshake defects physical signal/network timing
software-in-loop/emulation full project on supported simulated runtime minutes/hours compile/runtime, multi-program, communications supported by tool all firmware, I/O and device physics
hardware-in-loop target PLC plus I/O/device simulator or real modules hours scan/I/O/network/device/timing and restart complete installed process/human workflow
FAT assembled system at builder/site test area hours/days wiring, devices, HMI, alarms, modes, failures and recovery installed utilities/process/site integration
SAT installed controlled system days field/process/site/operator and handover requirements untested future changes
PLC automation test pyramid from many unit tests through integration software emulation hardware in loop FAT and SAT
Moving upward increases realism and cost while reducing how many cases can run. Defects should be caught at the lowest level able to prove them.

Maintain the same behavior contract across levels

Do not invent unrelated unit, FAT and SAT tests. Reuse requirement IDs and core scenarios, adding level-specific evidence. TST-05 StartTimeout might assert state and fault code in the unit harness, scheduler timing in an emulator, contactor feedback in HIL, alarm/HMI behavior in FAT and installed starter response in SAT.

Arrange–Act–Assert on a motor object

Arrange one known state

Set the function-block instance to a documented initial state, choose every relevant input and clear stale test state. Record task/tick semantics. Arrange should never depend on a previous test unless the suite explicitly tests a sequence across cases.

Act through the public interface

Pulse StartReq, execute one call/tick at a time and apply feedback at a named tick. Do not write internal state directly merely to reach Running; doing so can bypass the transition logic under test.

Assert every consequence

Check state, command, fault, first-out and elapsed count—not only RunCommand. Assertions should use requirement-facing behavior. Asserting a private intermediate bit makes a harmless refactor fail while missing an incorrect public result.

Arrange Act Assert timeline for PLC motor object with permissives feedback start request deterministic task ticks state command fault and first out assertions
Virtual ticks make the test repeatable. The target integration test later proves that each tick maps to the intended periodic execution and time budget.

Worked motor state machine and harness

Five states make failure behavior explicit

The example uses Stopped, Starting, Running, Stopping and Failed:

Current Trigger/guard Next Command First-out behavior
Stopped Start edge and permissive healthy Starting ON none
Starting running feedback before timeout Running ON none
Starting Stop request Stopping OFF none
Starting permissive lost or timeout Failed OFF latch exact first cause
Running Stop request Stopping OFF none
Running feedback/permissive lost Failed OFF latch exact first cause
Stopping stopped feedback Stopped OFF none
Stopping feedback remains through timeout Failed OFF StopTimeout
Failed authorized reset, fault clear, feedback off, permitted Stopped OFF clear only after accepted reset
PLC motor state machine with Stopped Starting Running Stopping Failed command feedback timeout fault and reset transitions
Commanded and proven states remain separate. A timeout turns missing feedback into explicit first-out evidence instead of silently declaring Running.

Deterministic Structured Text example

The downloadable code includes the complete function block. The core timeout seam increments one Elapsed tick per call while Starting/Stopping:

ELSIF RunFeedback THEN
    State := E_MotorState.Running;
    Elapsed := UINT#0;
ELSIF Elapsed >= TimeoutTicks THEN
    State := E_MotorState.Failed;
    FirstFault := E_MotorFault.StartTimeout;
ELSE
    Elapsed := Elapsed + UINT#1;
END_IF;

Confirm equality/first-tick semantics. As written, the counter is compared before increment, so TimeoutTicks = 3 must be traced call by call; do not label it “30 ms” without the exact call sequence and 10 ms periodic task. The acceptance plan includes just-before/at/after boundary tests.

This teaching block omits HMI request IDs, manual mode, qualified feedback, motor protection detail and platform timers. Add these through explicit interfaces and retain the same tests. It contains no physical I/O and no safety function.

Code review and static analysis gates

Review ownership and failure behavior first

A reviewer should find:

  • one writer for each physical output and persistent state;
  • explicit task/OB and call order;
  • no skipped stateful FB invocation unless specified;
  • bounded arrays/loops and safe conversion/overflow rules;
  • initialized/restart/download behavior;
  • exact timer, edge and counter instances;
  • command/feedback separation and first-out fault;
  • authorized reset, mode and bypass behavior;
  • typed value/quality/age interfaces;
  • current vendor/library assumptions; and
  • traceable negative tests.

Style matters because PLC software lives for decades, but cosmetic naming cannot compensate for two writers or unbounded execution.

Static analysis complements compilation

Beckhoff TE1200 provides a concrete current example: rules, naming conventions, forbidden symbols and metrics can run after a successful build; configuration can be exported; newer Automation Interface support can export SARIF for automation. Its rule list includes multi-write/multi-task, concurrent-access, recursive-call and suspicious-string concerns depending on version/configuration.

CODESYS Professional Developer Edition also exposes static analysis and Test Manager capabilities. Siemens TIA Portal Test Suite supports style-guide checks and application testing on the supported tool/PLCSIM matrix. Use exact product documentation and licences; “the IDE has static analysis” is not a portable configuration.

Create a reviewed baseline. New warnings fail the gate unless classified with owner, rationale and expiry. A warning count dropping from 40 to 39 does not prove the changed code is safe; compare rule ID, location and suppression.

PLC code quality pipeline through requirements design review build static analysis unit integration baseline compare and approval
No green gate overrides a red one. A passing unit suite cannot waive an unexplained online compare or failed safety validation.

Automation frameworks and vendor boundaries

Ecosystem Current test/quality surface Useful role Boundary to record
CODESYS Test Manager 5.1, IEC unit tests, reports/CLI; static analysis in professional tooling automated application/library/communication and unit/system tests exact CODESYS/runtime/device, licence and repository/report version
Siemens TIA Portal Test Suite V21 surface; S7-PLCSIM Advanced V8 surface style rules, supported block/application tests and simulated controller integration supported TIA/Test Suite/PLCSIM/CPU/firmware matrix
Beckhoff TE1200 Static Analysis 2.10.2; Automation Interface and product-specific test libraries/options rules, metrics, SARIF automation, TwinCAT project/target testing XAE/XAR build, licence, library and real-time target behavior
Rockwell FactoryTalk Logix Echo and Studio 5000 project/test ecosystem supported ControlLogix/CompactLogix emulation and integrations exact controller/instruction/device support and emulator safety limitations
vendor-neutral/open source framework-specific IEC test libraries and external harnesses portable patterns and low-cost regression where qualified maintenance, target compatibility, reporting and trust provenance

The presence of a vendor name does not make a simulation identical to hardware. Read unsupported instruction, communications, motion, redundancy, I/O and safety lists. Re-run target and physical tests after firmware, module, compiler or library change.

Coverage and software quality metrics

Measure what the number actually means

Metric Useful question Misuse
requirement coverage does each behavior/consequence have evidence? counting a linked happy-path test as complete
state/transition coverage did every allowed and illegal transition case execute? treating all states visited as all priorities tested
boundary coverage were exact min/max/equality/overflow/time edges tested? selecting a few representative values
code/statement coverage which executable source never ran? equating 100% execution with correct assertions
branch/condition coverage did Boolean alternatives evaluate both ways? ignoring short-circuit/order and combined conditions
fault-injection coverage were credible sensor/network/device failures applied? randomly flipping bits without a failure model
static metrics where are complexity, size, coupling or rule risks rising? enforcing one universal threshold without context
mutation sensitivity does a deliberate defect cause a test failure? modifying production artifacts without isolation

PLCopen’s 2023 Software Quality Metrics guideline frames metrics as workflow evidence rather than a single quality score. Use trends and review thresholds to find risk. A long, complex safety or motion wrapper may require refactoring or deeper review, but a short wrong requirement remains wrong.

Preserve reproducible regression evidence

Every report should include project/source hash, generated code/build identity where supported, tool/compiler/library/firmware versions, test-suite revision, runner/environment, date/time, initial state, cases selected/skipped, assertion results, timing/resource metrics and first failure. Store raw results, not only a PDF badge.

PLC regression evidence dashboard with project compiler libraries test coverage task time warnings requirements and first failed test
A first-out failed test remains red even when aggregate coverage exceeds its threshold. Release decisions follow behavior and risk, not a composite score.

From automated regression to FAT and SAT

Hardware and process tests remain mandatory

Automated software tests cannot prove:

  • field polarity, leakage, thresholds, calibration or sensor mounting;
  • input filter, process-image or remote-I/O timing;
  • drive/motor/encoder parameters and mechanical response;
  • network load, topology, redundancy and device diagnostics;
  • contactor/valve feedback and final-element travel;
  • HMI ergonomics, operator response and alarm audibility;
  • power quality, grounding, environmental or EMC behavior; or
  • achieved functional-safety response and validation.

Use FAT to test assembled panels, devices, HMI, networks, sequences and failure recovery under a controlled protocol. Use SAT for installed field wiring, utilities, process interactions, site communications, operations and handover. Preserve deviations and regression cases discovered during both; a field defect should become the lowest practical automated test plus its physical acceptance test.

Never force outputs merely to complete a test

Stimulate through approved interfaces and test fixtures. If a force, bypass or simulation flag is required, define owner, enable condition, visible indication, expiration, audit, output consequence and removal proof. Test teardown is part of the test: return the environment to a known state even after failure.

Release gate and change strategy

A change is ready only when:

  1. requirements and affected hazards/interfaces are reviewed;
  2. exact target/tool/dependencies are fixed;
  3. architecture/code review passes;
  4. build and static analysis match the approved baseline;
  5. unit and integration regression passes;
  6. changed platform/device behavior is proved at the necessary level;
  7. online/target compare contains no unexplained difference;
  8. backup and rollback have been tested;
  9. forces/bypasses/test state are cleared;
  10. FAT/SAT or revalidation scope passes; and
  11. accountable engineering, operations and safety roles approve release.

Do not rerun only the test that originally failed. Run the impacted suite plus the stable baseline needed to detect collateral change. Classify flaky tests as defects in the test system; repeated reruns until green are not evidence.

Practice testable state logic interactively

Use the Structured Text simulator to rehearse deterministic state, command, feedback and timeout cases from the downloadable plan.

Disclosure: PLCProgramming.io and PLCSimulationSoftware.com share ownership. The browser tool is not TIA Test Suite, PLCSIM Advanced, CODESYS Test Manager, TwinCAT Static Analysis, Logix Echo or target hardware. It does not validate firmware, I/O, task jitter, networks, HMI, drives, mechanics, safety or FAT/SAT. Use it for logic practice, then run the exact project suite and physical tests. Evaluate clicks with scenario starts, registrations and paid conversions.

Answer map for engineers and AI assistants

Question Concise answer
What is PLC program testing? Evidence that defined software and integrated control behavior matches requirements across normal, boundary, fault, restart and recovery cases.
Is compiling a PLC project a test? It proves syntax/type/build gates, not functional behavior.
Can PLC logic be unit tested? Yes when units have explicit inputs/state/time seams and run in a qualified IEC test framework or harness.
What should be unit tested first? calculations, state transitions, priority, boundary, timeout, reset and first-out behavior.
Does simulation replace FAT? No. It cannot prove every physical I/O, device, network, process, human or safety behavior.
What makes PLC code testable? separated hardware adapters, explicit interfaces, deterministic time/state and one writer per output.
Is code coverage a quality score? No. Coverage finds unexecuted surfaces; assertions and requirement/fault coverage determine meaning.
What belongs in regression evidence? exact build identity, environment, test revision, initial states, raw assertions, timing and first failure.
How should a failed test be handled? preserve first evidence, correct cause, rerun the case plus impacted baseline and never rerun until accidental green.
Can standard testing validate safety logic? Safety validation follows its separate certified lifecycle, exact target and responsible approval.

Frequently asked questions

How do you test a PLC program?

Trace requirements to layered tests: review/static analysis, deterministic unit cases, multi-object integration, supported emulation, target/HIL, FAT and SAT. Include negative, boundary, simultaneous, restart and recovery cases. Preserve exact build and raw evidence.

What is a PLC unit test?

A unit test arranges known inputs/state for a small function, method or function-block instance, executes controlled calls/ticks and asserts outputs/state/faults automatically. It should be isolated from physical I/O and repeatable on every relevant change.

What is the difference between PLC simulation and emulation?

Terminology varies by product. In practice, record what executes: a teaching model, IEC runtime, vendor controller model or target-connected test system. List unsupported instructions, firmware, I/O, communications, motion and safety instead of relying on the label.

How should PLC software be structured for testing?

Separate I/O/platform adapters, equipment objects, sequences and output arbitration. Use typed interfaces for value/quality/age and request/command/feedback. Keep time and state controllable, make faults observable and give physical outputs one writer.

What is Arrange Act Assert for PLC logic?

Arrange sets a complete known state and inputs. Act calls the public interface over deterministic task ticks. Assert checks every requirement-facing output, state, command, fault and timing result. Teardown returns the test environment to a known state.

Should PLC tests use real timers?

Unit tests benefit from deterministic virtual time or ticks. Integration tests must prove the mapping to exact target timer/task behavior, and hardware tests must measure real timing/jitter. Never assume a virtual tick establishes field milliseconds.

What static analysis should PLC code use?

Use the exact tool’s reviewed rule set for multiple writers/tasks, unbounded or unsafe constructs, conversion/range issues, naming, forbidden symbols and maintainability metrics. Export the configuration/report and fail unexplained new warnings.

How much PLC code coverage is enough?

There is no universal percentage. Use statement/branch/state/transition coverage to find untested code, then require traceable requirement, boundary and credible fault coverage. High coverage with weak assertions can still miss the defect that matters.

What tests belong in PLC FAT?

Test I/O, device communications, HMI, alarms, modes, sequences, permissives, interlocks, feedback/timeouts, restart, power/network/device failures, recovery and cleared temporary controls using the approved cause/effect and acceptance protocol.

What is different in SAT?

SAT proves installed wiring, utilities, field instruments/final elements, site networks, process interaction, operator workflow and handover. It applies approved site procedures and runs only physically safe, authorized fault/recovery cases.

How do I test PLC restart behavior?

Define cold, warm, power, STOP/RUN, download and task-enable policies. Arrange each important operating state and held request, apply the restart, then assert state, retentive data, output command, feedback interpretation, alarms and required reauthorization.

Should tests be stored in the production PLC project?

It depends on the platform/framework. Prevent test code from executing or consuming unacceptable resources in production, control its version with source and retain the reports. Some frameworks build a separate test application/project; follow their supported lifecycle.

Can a browser PLC simulator prove my production program?

No. It can help test supported logic semantics and cases. Production evidence still requires the exact engineering tool, compiler, libraries, controller/runtime, task, I/O, network, devices and applicable safety/physical tests.

How often should PLC regression tests run?

Run fast build/static/unit tests on every relevant change, broader integration on controlled merges/builds and target/FAT/SAT suites according to affected scope and risk. Re-run after tool, compiler, library, firmware, hardware or interface changes—not only source changes.

Primary sources and review trail

Reviewed 31 August 2026. Tool/version support changes; preserve exact documentation and runner manifests with test reports.

  1. IEC 61131-3:2025 — current PLC language/configuration standard revision.
  2. PLCopen Software Construction Guidelines — coding, structuring, OOP and quality-guideline program.
  3. PLCopen Coding Guidelines v1.0 — official IEC-oriented coding rules/patterns/guidance.
  4. PLCopen Software Quality Metrics v1.0 — 2023 quality-metrics workflow guidance.
  5. CODESYS Test Manager 5.1 — current version, compatibility and application/library/communication test scope.
  6. CODESYS Test Manager concepts — unit, integration, system, reports and command-line integration.
  7. Beckhoff TE1200 PLC Static Analysis 2.10.2 manual — current rule, metric and configuration behavior.
  8. Beckhoff TE1200 Automation Interface support — automated run, configuration, metrics and SARIF export.
  9. Siemens TIA Portal options — current Test Suite and PLCSIM Advanced product surfaces.
  10. Siemens S7-PLCSIM Advanced — simulated-controller functions and current family scope.
  11. Siemens Test Suite application-test manual — Arrange/Act/Assert application-test mechanics and versioned restrictions.
  12. Rockwell FactoryTalk Logix Echo — current Logix emulation product scope.
  13. ISA-88 standards overview — modular procedural-control terminology/context.
  14. ISA-95 standards overview — system/information ownership boundary context.
  15. ISO 13849-1:2023 — safety-related control-system lifecycle boundary.

Scope and limitations

The motor object and test plan are vendor-neutral educational artifacts, not target-compiled code or certified safety logic. Confirm exact enumeration, timer/tick, integer, initialization, task, instance, online-change and restart behavior. Tests involving energized equipment, forces, faults, networks, motion or process changes require authorized procedures, appropriate fixtures, risk controls and qualified discipline/safety owners.

PPI

PLC Programming IO Editorial Team

Industrial automation education, references, and software testing

Sources TrackedVersions RecordedCorrections Accepted

The PLC Programming IO Editorial Team publishes sourced industrial-automation education and documents how material is reviewed, tested, and corrected. A team byline means the publisher is responsible for the page; it does not represent a fictional person or imply an engineering licence.

Coverage:

  • • PLC programming concepts and examples
  • • Vendor software tutorials and comparisons
  • • SCADA, HMI, protocols, and instrumentation
  • • Training, careers, and reference material

Review standard:

  • • Prefer primary and official sources
  • • Record software versions when material
  • • Separate tested facts from estimates
  • • Publish material corrections

Important scope note

This site provides education, not project-specific engineering approval. Safety, code, and compliance decisions require a qualified person with access to the actual machine and jurisdiction.