Skip to content

feat: increase hybrid prefab test coverage - #4172

Open
NoelStephensUnity wants to merge 5 commits into
develop-3.x.xfrom
feat/hybrid-prefab-test-coverage
Open

NoelStephensUnity wants to merge 5 commits into
develop-3.x.xfrom
feat/hybrid-prefab-test-coverage

Conversation

@NoelStephensUnity

@NoelStephensUnity NoelStephensUnity commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

Purpose of this PR

This PR gets 232 test cases, from 26 of the 117 NGO runtime SDK integration test fixtures (Tests/Runtime), running in hybrid prefab mode (UnifiedHost / UnifiedServer).

PR Scope:

This PR's focuses on covering NGO features that work with the unified API today (i.e. the connection sequence, RPCs, NetworkVariables, spawning and ownership).

Out of this PR's scope:

  • Tests that required major adjustments or were outside of the current supported feature sets (NGO & N4E).
  • As an example:
    • All time travel-based tests (the time travel approach does not work with unified and providing the same tests coverage could require new, hybrid specific, tests), AttachableBehaviour (parenting consolidation is separate work), owner-authoritative NetworkTransform, and the NetworkRigidbody tests.
    • NetworkTransform tests have no relevance when using hybrid prefabs.
    • etc.

Test helper changes

  • All hybrid test cases run over the unified transport.
  • N4E worlds and UnifiedNetcodeTransport only start when at least one hybrid prefab is registered.
    • The test base class does not create hybrid player prefabs, so a UnifiedHost test case that only spawned players runs in "normal" NGO mode.
      • CreateServerAndClients now registers a UnifiedSessionPrefab if a hybrid test case does not register at least one of its own.

Tests included (hybrid fixtures + UseUnifiedTests() => true):

Area Fixtures
RPCs RpcTypeSerializationTests (132 cases), RpcTests, RpcDuringOnNetworkSpawn
NetworkVariables NetworkVariableGeneralTests, NetworkListTests, NetworkVariableCollectionsTests, NetworkVariableCollectionsChangingTests, NetworkVariableTraitsTests, NetworkVariablePermissionTests, NetworkVariableInheritanceTests, NetworkVarBufferCopyTest, OwnerModifiedTests, NetworkBehaviourUpdaterTests
Connection sequence ConnectionApprovalTests, ConnectionApprovalTimeoutTests, ClientApprovalDenied, NetworkManagerPlayerPrefab
Spawning / ownership NetworkObjectOnNetworkDespawnTests, NetworkObjectOwnershipTests, NetworkBehaviourPrePostSpawnTests, NetworkObjectSynchronizationTests (late join), PlayerSpawnObjectVisibilityTests, ComponentControllerTests, MessageReceiveAllocationTests
Parenting NetworkTransformAutoParenting (NGO parenting of hybrid objects)

Adjustments needed

  • Ghosts spawn from a snapshot, later than NGO's spawn message. Tests that read SpawnedObjects immediately after a spawn or a late join now use WaitForSpawnedOnAllOrTimeOut (NetworkVariablePermissionTests, NetworkVariableInheritanceTests, NetworkObjectSynchronizationTests). ComponentControllerTests predicates were missing a continue and threw instead of waiting.
  • RpcTests, RpcTypeSerializationTests and ClientApprovalDenied now have explicit Host / Server fixture arguments. NUnit drops a bare [TestFixture] when the class also has parameterized fixtures. This renames their test IDs (e.g. RpcTests.TestRpcs → RpcTests(Host).TestRpcs).
  • NetworkObjectDeserializationFailure is ignored for hybrid prefabs. Removing a prefab from one client's NetworkConfig does not unregister its ghost prefab, because all worlds in the test process share that registration.

Tests that were refactored:

Test-specific values that only configure a prefab now use arrays generated inside the test instead of expanded into [TestFixture]s:

  • NetworkBehaviourUpdaterTests: 36 fixtures → 5. Client count grows during the test, so the 1 and 2 client cases now include a late-joined client instead of a fresh session per case.
  • NetworkVariableCollectionsChangingTests: 10 fixtures → 5. Each test runs List then Dictionary.
Before After
NetworkBehaviourUpdaterTests unified 15 fixtures, 16.02 s 2 fixtures, 8.61 s
NetworkBehaviourUpdaterTests non-unified 21 fixtures, 10.65 s 3 fixtures, 6.59 s
NetworkVariableCollectionsChangingTests unified 4 fixtures, 33.88 s 2 fixtures, 29.98 s
NetworkVariableCollectionsChangingTests non-unified 6 fixtures, 39.15 s 3 fixtures, 38.60 s

Issues found and will require one (or more) follow-up PR(s)

  1. NetworkManager shutdown calls World.DisposeAllWorlds(), so one client shutting down disposes the server's and every other client's world in the same process. Disposing only the NetworkManager's own NetcodeWorld (local experiment, not in this PR) took NetworkObjectDontDestroyWithOwnerTests from 0/6 to 5/6 and the NetworkSpawnManagerTests connect/disconnect cases from 2/4 to 4/4.
  2. A client-initiated disconnect does not raise the client's own disconnect event, and peers receive 1 of 2 expected notifications (DisconnectTests, PeerDisconnectCallbackTests ClientDisconnectsFromServer). This still fails with (1) fixed.
  3. Instantiating a hybrid prefab and destroying it without spawning logs N4E's "not a valid ghost (ghostId == 0)" error (NetworkBehaviourReferenceTests, NetworkTransformOrderOfOperations, PlayerObjectTests).
  4. The expected prefab handler instantiate exception does not appear for hybrid spawns (NetworkPrefabHandlerSynchronizationTests).
  5. NGO's connection-approval player spawn, NetworkSpawnManager.InstantiateNetworkPrefab does not select the NetworkManager world before instantiating a hybrid prefab. So, hybrid player prefabs fail when several worlds share a process. (This should be resolved with GhostObject.DelaySpawning / Spawn() as a separate PR).

All tests impacted by the above issues were not included in this PR.

Jira ticket

MTT-16201

Documentation

  • No documentation changes or additions were necessary.

Testing & QA (How your changes can be verified during release Playtest)

The unified result is from the Yamato unified job on this PR (6000.7.0b3, N4E 7.0.0). The non-unified results are headless PlayMode runs on 6000.7.0b1 (bundles N4E 7.0.0) with the unified job's scripting defines, filtered to the touched fixtures. Each result is from one run.

Run Passed Failed Skipped
Unified job, UNIFIED_TESTS=true 233 0 6409 (tests not opted in excluded)
UNIFIED_TESTS unset, this branch 271 0 —
UNIFIED_TESTS unset, develop-3.x.x 316 0 —
  • The unified job's 233 is the 232 hybrid cases plus one testproject documentation test (DocumentationCodeSamples.CommandLineOptionsDocsTests). The 4 hybrid NetworkObjectDeserializationFailure cases are ignored by design and counted as skipped.
  • Non-unified coverage is unchanged. The 45 fewer cases on this branch come from the two consolidated fixtures, whose values now run inside the test (NetworkBehaviourUpdaterTests 42 → 3, NetworkVariableCollectionsChangingTests 12 → 6).

Functional Testing

Manual testing :

  • Manual testing done

Automated tests:

  • Covered by existing automated tests
  • Covered by new automated tests

Does the change require QA team to:

  • Review automated tests?
  • Execute manual tests?
  • Provide feedback about the PR?

Up-port

Not needed. Hybrid prefab mode only exists on develop-3.x.x.

Backports

Not needed.

N4E worlds and UnifiedNetcodeTransport only start when at least one hybrid
prefab is registered. Player prefabs are never hybrid, so a UnifiedHost or
UnifiedServer test case that spawns nothing but players silently ran as plain
NGO. CreateServerAndClients now registers a UnifiedSessionPrefab when a hybrid
test case registered no hybrid prefab of its own.
Adds UnifiedHost/UnifiedServer fixtures and the UseUnifiedTests opt-in to 25
fixtures covering RPCs, NetworkVariables and collections, connection approval,
spawn/despawn, ownership, late-join synchronization and NGO parenting of
hybrid objects.

Ghosts spawn from a snapshot, later than NGO's spawn message, so tests that
read SpawnedObjects immediately after a spawn or a late join now wait with
WaitForSpawnedOnAllOrTimeOut. ComponentControllerTests' predicates were
missing a continue and threw instead of waiting.

RpcTests, RpcTypeSerializationTests and ClientApprovalDenied gain explicit
Host/Server fixture arguments: NUnit drops a bare [TestFixture] when the class
also has parameterized fixtures.

NetworkObjectDeserializationFailure is ignored for hybrid prefabs: removing a
prefab from one client's NetworkConfig does not unregister its ghost prefab,
which all worlds in the process share.
The fixture was expanded into 36 [TestFixture]s (mode x client count x NetVar
combination), each starting its own session for both of its two test cases.
It now has one fixture per HostOrServer mode, and a single test that walks
the NetVar combinations and spawn counts in arrays, adding a client between
passes and despawning each case's objects before the next. Failure messages
name the case.

The 1 and 2 client passes now include a late-joined client, where every
case previously ran against a freshly started session.
…n types

The collection type only selects which helper component the prefab carries,
so it no longer needs its own fixture. Both prefabs are registered up front
and each test runs List then Dictionary in one session, despawning the
instance from its current authority between them. Failure messages name the
collection type. 10 fixtures become 5.
@NoelStephensUnity NoelStephensUnity changed the title Feat/hybrid prefab test coverage feat: increase hybrid prefab test coverage Sep 27, 2026
@NoelStephensUnity
NoelStephensUnity marked this pull request as ready for review September 27, 2026 23:57
@NoelStephensUnity
NoelStephensUnity requested a review from a team as a code owner September 27, 2026 23:57
@u-pr

u-pr Bot commented Sep 27, 2026

Copy link
Copy Markdown

⚠️ Some settings were ignored in '.pr_agent.toml (repository root)' repo settings

Check the configuration's TOML syntax, permitted settings, and size limit. See the error below.


Error message:
Ignored prohibited settings: github_app.handle_pr_actions. Permitted settings were applied.

Configuration content:
# This is the configuration for the u-pr bot
# https://github.cds.internal.unity3d.com/unity/u-pr
# For configuration of this file:
# https://developer.portal.internal.unity.com/catalog/default/component/u-pr/docs/configuration/automatic_runs/

[github_app]
handle_pr_actions = ['opened', 'ready_for_review']  # PR events that auto-run pr_commands
pr_commands       = ["/harness-review"]             # what runs on those events
reviewer_commands = ["/harness-review"]             # what runs when @u-pr is added as reviewer

@u-pr u-pr Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Harness Review

Ship it

The change expands unified hybrid test coverage and consolidates two test suites; I examined fixture selection, hybrid startup, synchronization waits, and spawn and despawn behavior without finding an actionable issue.

Reviewed commit 5f4c87a

🤖 Helpful? 👍/👎

@codecov-github-com

codecov-github-com Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

@@              Coverage Diff               @@
##           develop-3.x.x    #4172   +/-   ##
==============================================
  Coverage          78.19%   78.19%           
==============================================
  Files                153      153           
  Lines              26272    26272           
==============================================
  Hits               20544    20544           
  Misses              5728     5728           
Flag Coverage Δ
NGOv2_project_testproject_ubuntu 76.64% <ø> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
com.unity.netcode.gameobjects 78.19% <ø> (ø)

ℹ️ Need help interpreting these results?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants