From 108dd5c461ac12e0bc28b51af8cc32287a97e64b Mon Sep 17 00:00:00 2001 From: richard elms Date: Mon, 10 Nov 2025 14:02:00 +0100 Subject: [PATCH 1/6] add tests to confirm --- features/app_start_spans.feature | 42 +++++++ .../mazerunner/Assets/Scenes/MainScene.unity | 108 ++++++++++++------ .../Scenarios/AppStart/AppStartWithMetrics.cs | 30 +++++ .../AppStart/AppStartWithMetrics.cs.meta | 11 ++ .../SceneLoad/SceneLoadWithMetrics.cs | 29 +++++ .../SceneLoad/SceneLoadWithMetrics.cs.meta | 11 ++ features/scene_load_spans.feature | 39 +++++++ features/steps/unity_steps.rb | 78 +++++++++++++ 8 files changed, 315 insertions(+), 33 deletions(-) create mode 100644 features/fixtures/mazerunner/Assets/Scripts/Scenarios/AppStart/AppStartWithMetrics.cs create mode 100644 features/fixtures/mazerunner/Assets/Scripts/Scenarios/AppStart/AppStartWithMetrics.cs.meta create mode 100644 features/fixtures/mazerunner/Assets/Scripts/Scenarios/SceneLoad/SceneLoadWithMetrics.cs create mode 100644 features/fixtures/mazerunner/Assets/Scripts/Scenarios/SceneLoad/SceneLoadWithMetrics.cs.meta diff --git a/features/app_start_spans.feature b/features/app_start_spans.feature index bdf9208e..f536ffc8 100644 --- a/features/app_start_spans.feature +++ b/features/app_start_spans.feature @@ -73,3 +73,45 @@ Scenario: App Start Clear Customisation * the trace "Bugsnag-Span-Sampling" header equals "1:4" * the trace payload field "resourceSpans.0.scopeSpans.0.spans.3.name" equals "[AppStart/UnityRuntime]" +Scenario: App Start with metrics + When I run the game in the "AppStartWithMetrics" state + And I wait to receive at least 4 spans + + # basic structure – same as the other app start tests + * the span named "[AppStartPhase/LoadAssemblies]" exists + * the span named "[AppStartPhase/SplashScreen]" exists + * the span named "[AppStartPhase/LoadFirstScene]" exists + * the span named "[AppStart/UnityRuntime]" exists + + # root app-start metadata + * the span named "[AppStart/UnityRuntime]" has string attribute "bugsnag.span.category" equal to "app_start" + * the span named "[AppStart/UnityRuntime]" has string attribute "bugsnag.app_start.type" equal to "UnityRuntime" + * the span named "[AppStart/UnityRuntime]" has boolean attribute "bugsnag.span.first_class" equal to true + + # rendering metrics on the app-start span + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.total_frames" greater than 0 + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_average" greater than 0 + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 + + # memory metrics on the app-start span (arrayed samples) + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.timestamps" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.system.memory.spaces.art.size" greater than 0 + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.spaces.art.used" with at least 5 elements + + # CPU metrics on the app-start span + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_total" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages + * the span named "[AppStart/UnityRuntime]" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage + * the span named "[AppStart/UnityRuntime]" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage + + # phase spans should also carry the memory metrics + * the span named "[AppStartPhase/LoadAssemblies]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/SplashScreen]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/LoadFirstScene]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 diff --git a/features/fixtures/mazerunner/Assets/Scenes/MainScene.unity b/features/fixtures/mazerunner/Assets/Scenes/MainScene.unity index 9e543a1d..3c192d15 100644 --- a/features/fixtures/mazerunner/Assets/Scenes/MainScene.unity +++ b/features/fixtures/mazerunner/Assets/Scenes/MainScene.unity @@ -103,7 +103,7 @@ NavMeshSettings: serializedVersion: 2 m_ObjectHideFlags: 0 m_BuildSettings: - serializedVersion: 2 + serializedVersion: 3 agentTypeID: 0 agentRadius: 0.5 agentHeight: 2 @@ -116,7 +116,7 @@ NavMeshSettings: cellSize: 0.16666667 manualTileSize: 0 tileSize: 256 - accuratePlacement: 0 + buildHeightMesh: 0 maxJobWorkers: 0 preserveTilesOutsideBounds: 0 debug: @@ -153,7 +153,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1513513353} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -283,13 +282,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 259057444} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &259057446 MonoBehaviour: @@ -356,13 +355,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 260121133} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 9 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &260121135 MonoBehaviour: @@ -431,13 +430,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 320782971} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &320782973 MonoBehaviour: @@ -531,13 +530,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 323187830} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 10 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &323187832 MonoBehaviour: @@ -651,13 +650,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 368414949} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &381874221 GameObject: @@ -699,9 +698,17 @@ Camera: m_projectionMatrixMode: 1 m_GateFitMode: 2 m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 m_SensorSize: {x: 36, y: 24} m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 m_NormalizedViewPortRect: serializedVersion: 2 x: 0 @@ -735,13 +742,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 381874221} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &480052157 GameObject: @@ -756,6 +763,7 @@ GameObject: - component: {fileID: 480052159} - component: {fileID: 480052161} - component: {fileID: 480052162} + - component: {fileID: 480052163} m_Layer: 0 m_Name: SceneLoad m_TagString: Untagged @@ -770,13 +778,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 480052157} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &480052159 MonoBehaviour: @@ -830,6 +838,18 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: ShouldStartNotifier: 0 +--- !u!114 &480052163 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 480052157} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: aee8c4c9da1c248b295c914510473aef, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &805103369 GameObject: m_ObjectHideFlags: 0 @@ -857,13 +877,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 805103369} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 7 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &805103371 MonoBehaviour: @@ -941,13 +961,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 895329258} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &895329260 MonoBehaviour: @@ -986,13 +1006,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 923005099} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 11 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &923005101 MonoBehaviour: @@ -1031,13 +1051,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1054039541} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 13 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1054039543 MonoBehaviour: @@ -1051,6 +1071,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c54429fd439634bc3a9bebabb900b119, type: 3} m_Name: m_EditorClassIdentifier: + ShouldStartNotifier: 0 --- !u!1 &1124192952 GameObject: m_ObjectHideFlags: 0 @@ -1080,13 +1101,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1124192952} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 12 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1124192954 MonoBehaviour: @@ -1189,27 +1210,27 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1294582013} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - - {fileID: 259057445} - - {fileID: 1452957866} - - {fileID: 320782972} - - {fileID: 895329259} - - {fileID: 2146169737} - - {fileID: 480052158} - - {fileID: 1609554505} - - {fileID: 805103370} - {fileID: 2053587486} - - {fileID: 260121134} - {fileID: 323187831} + - {fileID: 1452957866} + - {fileID: 260121134} - {fileID: 923005100} - - {fileID: 1124192953} - {fileID: 1054039542} + - {fileID: 259057445} + - {fileID: 1124192953} + - {fileID: 1609554505} + - {fileID: 2146169737} + - {fileID: 320782972} + - {fileID: 480052158} + - {fileID: 805103370} + - {fileID: 895329259} m_Father: {fileID: 2126837007} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1452957865 GameObject: @@ -1243,13 +1264,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1452957865} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1452957867 MonoBehaviour: @@ -1446,6 +1467,7 @@ Canvas: m_SortingBucketNormalizedSize: 0 m_VertexColorAlwaysGammaSpace: 0 m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 m_SortingLayerID: 0 m_SortingOrder: 0 m_TargetDisplay: 0 @@ -1463,7 +1485,6 @@ RectTransform: m_Children: - {fileID: 41935981} m_Father: {fileID: 0} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1499,13 +1520,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1609554504} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1609554506 MonoBehaviour: @@ -1599,6 +1620,7 @@ GameObject: - component: {fileID: 2053587488} - component: {fileID: 2053587490} - component: {fileID: 2053587491} + - component: {fileID: 2053587492} m_Layer: 0 m_Name: AppStart m_TagString: Untagged @@ -1613,13 +1635,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2053587485} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 8 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2053587487 MonoBehaviour: @@ -1686,6 +1708,18 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: ShouldStartNotifier: 0 +--- !u!114 &2053587492 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2053587485} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 91b41cdbefc5543c6b4c68a2d0cb6005, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &2126837005 GameObject: m_ObjectHideFlags: 0 @@ -1725,6 +1759,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2126837005} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -1732,7 +1767,6 @@ Transform: m_Children: - {fileID: 1294582014} m_Father: {fileID: 0} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2126837008 MonoBehaviour: @@ -1778,13 +1812,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2146169736} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1294582014} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2146169738 MonoBehaviour: @@ -1903,3 +1937,11 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: ShouldStartNotifier: 0 +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 381874224} + - {fileID: 2126837007} + - {fileID: 1513513353} + - {fileID: 368414952} diff --git a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/AppStart/AppStartWithMetrics.cs b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/AppStart/AppStartWithMetrics.cs new file mode 100644 index 00000000..9d7fdc3d --- /dev/null +++ b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/AppStart/AppStartWithMetrics.cs @@ -0,0 +1,30 @@ +using System.Collections; +using System.Collections.Generic; +using BugsnagUnityPerformance; +using UnityEngine; + +public class AppStartWithMetrics : Scenario +{ + public override void PreparePerformanceConfig(string apiKey, string host) + { + base.PreparePerformanceConfig(apiKey, host); + SetMaxBatchSize(4); + Configuration.EnabledMetrics = new EnabledMetrics + { + CPU = true, + Memory = true, + Rendering = true + }; + Configuration.AutoInstrumentAppStart = AutoInstrumentAppStartSetting.START_ONLY; + } + + public override void Run() + { + Invoke("ReportAppStarted", 5.0f); + } + + private void ReportAppStarted() + { + BugsnagPerformance.ReportAppStarted(); + } +} diff --git a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/AppStart/AppStartWithMetrics.cs.meta b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/AppStart/AppStartWithMetrics.cs.meta new file mode 100644 index 00000000..89ece694 --- /dev/null +++ b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/AppStart/AppStartWithMetrics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 91b41cdbefc5543c6b4c68a2d0cb6005 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/SceneLoad/SceneLoadWithMetrics.cs b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/SceneLoad/SceneLoadWithMetrics.cs new file mode 100644 index 00000000..805bf19a --- /dev/null +++ b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/SceneLoad/SceneLoadWithMetrics.cs @@ -0,0 +1,29 @@ +using System.Collections; +using System.Collections.Generic; +using BugsnagUnityPerformance; +using UnityEngine; + +public class SceneLoadWithMetrics : Scenario +{ + public override void PreparePerformanceConfig(string apiKey, string host) + { + base.PreparePerformanceConfig(apiKey, host); + SetMaxBatchSize(1); + Configuration.EnabledMetrics = new EnabledMetrics + { + CPU = true, + Memory = true, + Rendering = true + }; + } + + public override void Run() + { + Invoke("DoSceneLoad", 2.0f); + } + + private void DoSceneLoad() + { + BugsnagSceneManager.LoadScene("Scene1"); + } +} diff --git a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/SceneLoad/SceneLoadWithMetrics.cs.meta b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/SceneLoad/SceneLoadWithMetrics.cs.meta new file mode 100644 index 00000000..15740d21 --- /dev/null +++ b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/SceneLoad/SceneLoadWithMetrics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aee8c4c9da1c248b295c914510473aef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/features/scene_load_spans.feature b/features/scene_load_spans.feature index 04ec85f3..413653d0 100644 --- a/features/scene_load_spans.feature +++ b/features/scene_load_spans.feature @@ -79,3 +79,42 @@ Feature: Scene Load Spans * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" string attribute "bugsnag.view.name" equals "ManualSceneSpan" * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" bool attribute "bugsnag.span.first_class" is true + Scenario: Scene load with metrics + When I run the game in the "SceneLoadWithMetrics" state + And I wait to receive at least 1 span + Then the trace Bugsnag-Integrity header is valid + And the trace "Bugsnag-Api-Key" header equals "a35a2a72bd230ac0aa0f52715bbdc6aa" + * the trace "Bugsnag-Sent-At" header matches the regex "^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$" + * the trace "Bugsnag-Span-Sampling" header equals "1:1" + + # identity + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.name" equals "[ViewLoad/UnityScene]Scene1" + * the span named "[ViewLoad/UnityScene]Scene1" is first class + * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.span.category" equal to "view_load" + * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.view.type" equal to "UnityScene" + * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.view.name" equal to "Scene1" + * the span named "[ViewLoad/UnityScene]Scene1" has boolean attribute "bugsnag.span.first_class" equal to true + + # rendering metrics + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.total_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_average" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.slow_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 + + # memory metrics + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.art.size" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.art.used" with at least 2 elements + + # CPU metrics + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_total" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage + * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage \ No newline at end of file diff --git a/features/steps/unity_steps.rb b/features/steps/unity_steps.rb index d0a3012f..d302e44f 100644 --- a/features/steps/unity_steps.rb +++ b/features/steps/unity_steps.rb @@ -300,3 +300,81 @@ def spans_from_request_list(list) .flat_map { |s| s['spans'] } .select { |s| !s.nil? } end + +# +# Find a span by name and return it +# +def find_span_by_name(span_name) + spans = spans_from_request_list(Maze::Server.list_for("traces")) + span = spans.find { |s| s['name'] == span_name } + raise Test::Unit::AssertionFailedError, "No span found with the name #{span_name}" if span.nil? + span +end + +# +# Find an attribute on a span by key +# +def find_span_attr(span, key) + attr = span['attributes']&.find { |a| a['key'] == key } + raise Test::Unit::AssertionFailedError, "No attribute '#{key}' found on span '#{span['name']}'" if attr.nil? + attr +end + +Then('the span named {string} has an attribute {string}') do |span_name, attr_key| + span = find_span_by_name(span_name) + find_span_attr(span, attr_key) # will raise if missing +end + +Then('the span named {string} has string attribute {string} equal to {string}') do |span_name, attr_key, expected| + span = find_span_by_name(span_name) + attr = find_span_attr(span, attr_key) + actual = attr.dig('value', 'stringValue') + Maze.check.equal(expected, actual, "Expected #{span_name}.#{attr_key} to be '#{expected}' but was '#{actual}'") +end + +Then('the span named {string} has integer attribute {string} greater than {int}') do |span_name, attr_key, min_value| + span = find_span_by_name(span_name) + attr = find_span_attr(span, attr_key) + actual = attr.dig('value', 'intValue').to_i + Maze.check.operator(actual, :>, min_value, "Expected #{span_name}.#{attr_key} to be > #{min_value} but was #{actual}") +end + +Then('the span named {string} has boolean attribute {string} equal to {word}') do |span_name, attr_key, expected_str| + expected = expected_str == 'true' + span = find_span_by_name(span_name) + attr = find_span_attr(span, attr_key) + actual = attr.dig('value', 'boolValue') + Maze.check.equal(expected, actual, "Expected #{span_name}.#{attr_key} to be #{expected} but was #{actual}") +end + +Then('the span named {string} has array attribute {string} with at least {int} elements') do |span_name, attr_key, min_count| + span = find_span_by_name(span_name) + attr = find_span_attr(span, attr_key) + arr = attr.dig('value', 'arrayValue', 'values') + raise Test::Unit::AssertionFailedError, "Attribute '#{attr_key}' on '#{span_name}' is not an array" if arr.nil? + Maze.check.operator(arr.length, :>=, min_count, "Expected at least #{min_count} elements but got #{arr.length}") +end + +Then('the span named {string} has double attribute {string} that is a valid percentage') do |span_name, attr_key| + span = find_span_by_name(span_name) + attr = find_span_attr(span, attr_key) + val = attr.dig('value', 'doubleValue') + raise Test::Unit::AssertionFailedError, "Attribute '#{attr_key}' on '#{span_name}' has no doubleValue" if val.nil? + num = val.to_f + Maze.check.operator(num, :>=, 0.0, "Expected #{attr_key} >= 0.0, got #{num}") + Maze.check.operator(num, :<=, 100.0, "Expected #{attr_key} <= 100.0, got #{num}") +end + +Then('the span named {string} has double array attribute {string} containing valid percentages') do |span_name, attr_key| + span = find_span_by_name(span_name) + attr = find_span_attr(span, attr_key) + arr = attr.dig('value', 'arrayValue', 'values') + raise Test::Unit::AssertionFailedError, "Attribute '#{attr_key}' on '#{span_name}' is not an array" if arr.nil? + arr.each do |el| + val = el['doubleValue'] + raise Test::Unit::AssertionFailedError, "Expected doubleValue in #{attr_key} array but got #{el}" if val.nil? + num = val.to_f + Maze.check.operator(num, :>=, 0.0, "Expected value in #{attr_key} >= 0.0, got #{num}") + Maze.check.operator(num, :<=, 100.0, "Expected value in #{attr_key} <= 100.0, got #{num}") + end +end From 3e7111efad3a226ead3076628ea5dbe5094c1190 Mon Sep 17 00:00:00 2001 From: richard elms Date: Mon, 10 Nov 2025 14:21:42 +0100 Subject: [PATCH 2/6] limit to mobile --- features/app_start_spans.feature | 1 + features/scene_load_spans.feature | 80 ++++++++++++++++--------------- features/support/env.rb | 5 ++ 3 files changed, 47 insertions(+), 39 deletions(-) diff --git a/features/app_start_spans.feature b/features/app_start_spans.feature index f536ffc8..bca03399 100644 --- a/features/app_start_spans.feature +++ b/features/app_start_spans.feature @@ -73,6 +73,7 @@ Scenario: App Start Clear Customisation * the trace "Bugsnag-Span-Sampling" header equals "1:4" * the trace payload field "resourceSpans.0.scopeSpans.0.spans.3.name" equals "[AppStart/UnityRuntime]" +@mobile_only Scenario: App Start with metrics When I run the game in the "AppStartWithMetrics" state And I wait to receive at least 4 spans diff --git a/features/scene_load_spans.feature b/features/scene_load_spans.feature index 413653d0..ee05395f 100644 --- a/features/scene_load_spans.feature +++ b/features/scene_load_spans.feature @@ -79,42 +79,44 @@ Feature: Scene Load Spans * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" string attribute "bugsnag.view.name" equals "ManualSceneSpan" * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" bool attribute "bugsnag.span.first_class" is true - Scenario: Scene load with metrics - When I run the game in the "SceneLoadWithMetrics" state - And I wait to receive at least 1 span - Then the trace Bugsnag-Integrity header is valid - And the trace "Bugsnag-Api-Key" header equals "a35a2a72bd230ac0aa0f52715bbdc6aa" - * the trace "Bugsnag-Sent-At" header matches the regex "^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" - - # identity - * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.name" equals "[ViewLoad/UnityScene]Scene1" - * the span named "[ViewLoad/UnityScene]Scene1" is first class - * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.span.category" equal to "view_load" - * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.view.type" equal to "UnityScene" - * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.view.name" equal to "Scene1" - * the span named "[ViewLoad/UnityScene]Scene1" has boolean attribute "bugsnag.span.first_class" equal to true - - # rendering metrics - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.total_frames" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_average" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.slow_frames" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 - - # memory metrics - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.timestamps" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.art.size" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.art.used" with at least 2 elements - - # CPU metrics - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_total" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages - * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage - * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage \ No newline at end of file + @mobile_only + Scenario: Scene load with metrics + When I run the game in the "SceneLoadWithMetrics" state + And I wait to receive at least 1 span + Then the trace Bugsnag-Integrity header is valid + And the trace "Bugsnag-Api-Key" header equals "a35a2a72bd230ac0aa0f52715bbdc6aa" + * the trace "Bugsnag-Sent-At" header matches the regex "^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$" + * the trace "Bugsnag-Span-Sampling" header equals "1:1" + + # identity + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.name" equals "[ViewLoad/UnityScene]Scene1" + * the span named "[ViewLoad/UnityScene]Scene1" is first class + * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.span.category" equal to "view_load" + * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.view.type" equal to "UnityScene" + * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.view.name" equal to "Scene1" + * the span named "[ViewLoad/UnityScene]Scene1" has boolean attribute "bugsnag.span.first_class" equal to true + + # rendering metrics + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.total_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_average" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.slow_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 + + # memory metrics + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.art.size" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.art.used" with at least 2 elements + + # CPU metrics + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_total" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage + * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage + \ No newline at end of file diff --git a/features/support/env.rb b/features/support/env.rb index 9b3c1419..6c0d87e0 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -51,6 +51,11 @@ skip_this_scenario('Skipping scenario') unless Maze::Helper.get_current_platform == 'android' end +Before('@mobile_only') do |_scenario| + platform = Maze::Helper.get_current_platform + skip_this_scenario('Skipping scenario') unless ['ios', 'android'].include?(platform) +end + BeforeAll do $api_key = 'a35a2a72bd230ac0aa0f52715bbdc6aa' From 48671d3a7dd324345a36fec07483f82a71f543fd Mon Sep 17 00:00:00 2001 From: richard elms Date: Mon, 10 Nov 2025 16:36:23 +0100 Subject: [PATCH 3/6] mobile platform specific --- features/app_start_spans.feature | 46 ++++++++++++++++++++++--------- features/scene_load_spans.feature | 45 ++++++++++++++++++++---------- 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/features/app_start_spans.feature b/features/app_start_spans.feature index bca03399..21730af9 100644 --- a/features/app_start_spans.feature +++ b/features/app_start_spans.feature @@ -73,21 +73,10 @@ Scenario: App Start Clear Customisation * the trace "Bugsnag-Span-Sampling" header equals "1:4" * the trace payload field "resourceSpans.0.scopeSpans.0.spans.3.name" equals "[AppStart/UnityRuntime]" -@mobile_only +@android_only Scenario: App Start with metrics When I run the game in the "AppStartWithMetrics" state - And I wait to receive at least 4 spans - - # basic structure – same as the other app start tests - * the span named "[AppStartPhase/LoadAssemblies]" exists - * the span named "[AppStartPhase/SplashScreen]" exists - * the span named "[AppStartPhase/LoadFirstScene]" exists - * the span named "[AppStart/UnityRuntime]" exists - - # root app-start metadata - * the span named "[AppStart/UnityRuntime]" has string attribute "bugsnag.span.category" equal to "app_start" - * the span named "[AppStart/UnityRuntime]" has string attribute "bugsnag.app_start.type" equal to "UnityRuntime" - * the span named "[AppStart/UnityRuntime]" has boolean attribute "bugsnag.span.first_class" equal to true + And I wait to receive 4 spans # rendering metrics on the app-start span * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.total_frames" greater than 0 @@ -116,3 +105,34 @@ Scenario: App Start with metrics * the span named "[AppStartPhase/LoadAssemblies]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 * the span named "[AppStartPhase/SplashScreen]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 * the span named "[AppStartPhase/LoadFirstScene]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + +@ios_only +Scenario: App Start with metrics + When I run the game in the "AppStartWithMetrics" state + And I wait to receive 4 spans + + # rendering metrics on the app-start span + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.total_frames" greater than 0 + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_average" greater than 0 + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 + + # memory metrics on the app-start span (arrayed samples) + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.timestamps" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 5 elements + + # CPU metrics on the app-start span + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_total" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages + * the span named "[AppStart/UnityRuntime]" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage + * the span named "[AppStart/UnityRuntime]" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage + + # phase spans should also carry the memory metrics + * the span named "[AppStartPhase/LoadAssemblies]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/SplashScreen]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/LoadFirstScene]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 diff --git a/features/scene_load_spans.feature b/features/scene_load_spans.feature index ee05395f..86a79413 100644 --- a/features/scene_load_spans.feature +++ b/features/scene_load_spans.feature @@ -79,22 +79,10 @@ Feature: Scene Load Spans * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" string attribute "bugsnag.view.name" equals "ManualSceneSpan" * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" bool attribute "bugsnag.span.first_class" is true - @mobile_only + @android_only Scenario: Scene load with metrics When I run the game in the "SceneLoadWithMetrics" state - And I wait to receive at least 1 span - Then the trace Bugsnag-Integrity header is valid - And the trace "Bugsnag-Api-Key" header equals "a35a2a72bd230ac0aa0f52715bbdc6aa" - * the trace "Bugsnag-Sent-At" header matches the regex "^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$" - * the trace "Bugsnag-Span-Sampling" header equals "1:1" - - # identity - * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.name" equals "[ViewLoad/UnityScene]Scene1" - * the span named "[ViewLoad/UnityScene]Scene1" is first class - * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.span.category" equal to "view_load" - * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.view.type" equal to "UnityScene" - * the span named "[ViewLoad/UnityScene]Scene1" has string attribute "bugsnag.view.name" equal to "Scene1" - * the span named "[ViewLoad/UnityScene]Scene1" has boolean attribute "bugsnag.span.first_class" equal to true + And I wait to receive 4 spans # rendering metrics * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.total_frames" greater than 0 @@ -119,4 +107,31 @@ Feature: Scene Load Spans * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage - \ No newline at end of file + +@ios_only + Scenario: Scene load with metrics + When I run the game in the "SceneLoadWithMetrics" state + And I wait to receive at least 4 spans + + # rendering metrics + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.total_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_average" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.slow_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 + + # memory metrics + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 2 elements + + # CPU metrics + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_total" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage + * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage + From 4f4b5e462529f188042c50f055eb79cceae73ecc Mon Sep 17 00:00:00 2001 From: richard elms Date: Tue, 11 Nov 2025 10:58:13 +0100 Subject: [PATCH 4/6] typo fix --- features/scene_load_spans.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/scene_load_spans.feature b/features/scene_load_spans.feature index 86a79413..abc3bc95 100644 --- a/features/scene_load_spans.feature +++ b/features/scene_load_spans.feature @@ -82,7 +82,7 @@ Feature: Scene Load Spans @android_only Scenario: Scene load with metrics When I run the game in the "SceneLoadWithMetrics" state - And I wait to receive 4 spans + And I wait to receive at least 1 span # rendering metrics * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.total_frames" greater than 0 @@ -111,7 +111,7 @@ Feature: Scene Load Spans @ios_only Scenario: Scene load with metrics When I run the game in the "SceneLoadWithMetrics" state - And I wait to receive at least 4 spans + And I wait to receive at least 1 span # rendering metrics * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.total_frames" greater than 0 From ef228225f9c48c0c62f9f5d4c5640c5f017e9fc1 Mon Sep 17 00:00:00 2001 From: richard elms Date: Thu, 13 Nov 2025 11:08:25 +0100 Subject: [PATCH 5/6] review changes --- features/app_start_spans.feature | 88 +++++++++++++++++-------------- features/scene_load_spans.feature | 68 ++++++++++++------------ features/steps/unity_steps.rb | 12 ++--- features/support/env.rb | 6 --- 4 files changed, 88 insertions(+), 86 deletions(-) diff --git a/features/app_start_spans.feature b/features/app_start_spans.feature index 21730af9..4d22878d 100644 --- a/features/app_start_spans.feature +++ b/features/app_start_spans.feature @@ -76,63 +76,71 @@ Scenario: App Start Clear Customisation @android_only Scenario: App Start with metrics When I run the game in the "AppStartWithMetrics" state - And I wait to receive 4 spans + + And I wait to receive a span named "[AppStart/UnityRuntime]" + And I wait to receive a span named "[AppStartPhase/LoadAssemblies]" + And I wait to receive a span named "[AppStartPhase/SplashScreen]" + And I wait to receive a span named "[AppStartPhase/LoadFirstScene]" # rendering metrics on the app-start span - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.total_frames" greater than 0 - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_average" greater than 0 - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.rendering.total_frames" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.rendering.fps_average" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.rendering.fps_maximum" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.rendering.fps_minimum" greater than 0 # memory metrics on the app-start span (arrayed samples) - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.timestamps" with at least 5 elements - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 5 elements - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.system.memory.spaces.art.size" greater than 0 - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.spaces.art.used" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.memory.timestamps" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.memory.spaces.device.used" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.system.memory.spaces.art.size" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.memory.spaces.art.used" with at least 5 elements # CPU metrics on the app-start span - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 5 elements - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_total" with at least 5 elements - * the span named "[AppStart/UnityRuntime]" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 5 elements - * the span named "[AppStart/UnityRuntime]" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages - * the span named "[AppStart/UnityRuntime]" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage - * the span named "[AppStart/UnityRuntime]" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.cpu_measures_timestamps" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.cpu_measures_total" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has a double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.cpu_measures_main_thread" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has a double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages + * the span named "[AppStart/UnityRuntime]" has a double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage + * the span named "[AppStart/UnityRuntime]" has a double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage # phase spans should also carry the memory metrics - * the span named "[AppStartPhase/LoadAssemblies]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 - * the span named "[AppStartPhase/SplashScreen]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 - * the span named "[AppStartPhase/LoadFirstScene]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/LoadAssemblies]" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/SplashScreen]" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/LoadFirstScene]" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 @ios_only Scenario: App Start with metrics When I run the game in the "AppStartWithMetrics" state - And I wait to receive 4 spans + + And I wait to receive a span named "[AppStart/UnityRuntime]" + And I wait to receive a span named "[AppStartPhase/LoadAssemblies]" + And I wait to receive a span named "[AppStartPhase/SplashScreen]" + And I wait to receive a span named "[AppStartPhase/LoadFirstScene]" # rendering metrics on the app-start span - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.total_frames" greater than 0 - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_average" greater than 0 - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.rendering.total_frames" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.rendering.fps_average" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.rendering.fps_maximum" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.rendering.fps_minimum" greater than 0 # memory metrics on the app-start span (arrayed samples) - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.timestamps" with at least 5 elements - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 - * the span named "[AppStart/UnityRuntime]" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.memory.timestamps" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.memory.spaces.device.used" with at least 5 elements # CPU metrics on the app-start span - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 5 elements - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_total" with at least 5 elements - * the span named "[AppStart/UnityRuntime]" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages - * the span named "[AppStart/UnityRuntime]" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 5 elements - * the span named "[AppStart/UnityRuntime]" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages - * the span named "[AppStart/UnityRuntime]" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage - * the span named "[AppStart/UnityRuntime]" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.cpu_measures_timestamps" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.cpu_measures_total" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has a double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[AppStart/UnityRuntime]" has an array attribute "bugsnag.system.cpu_measures_main_thread" with at least 5 elements + * the span named "[AppStart/UnityRuntime]" has a double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages + * the span named "[AppStart/UnityRuntime]" has a double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage + * the span named "[AppStart/UnityRuntime]" has a double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage # phase spans should also carry the memory metrics - * the span named "[AppStartPhase/LoadAssemblies]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 - * the span named "[AppStartPhase/SplashScreen]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 - * the span named "[AppStartPhase/LoadFirstScene]" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/LoadAssemblies]" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/SplashScreen]" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[AppStartPhase/LoadFirstScene]" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 diff --git a/features/scene_load_spans.feature b/features/scene_load_spans.feature index abc3bc95..6b7249c6 100644 --- a/features/scene_load_spans.feature +++ b/features/scene_load_spans.feature @@ -85,28 +85,28 @@ Feature: Scene Load Spans And I wait to receive at least 1 span # rendering metrics - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.total_frames" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_average" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.slow_frames" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.total_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.fps_average" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.slow_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.fps_maximum" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.fps_minimum" greater than 0 # memory metrics - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.timestamps" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.art.size" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.art.used" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.memory.timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.memory.spaces.device.used" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.system.memory.spaces.art.size" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.memory.spaces.art.used" with at least 2 elements # CPU metrics - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_total" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages - * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage - * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.cpu_measures_timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.cpu_measures_total" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has a double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.cpu_measures_main_thread" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has a double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has a double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage + * the span named "[ViewLoad/UnityScene]Scene1" has a double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage @ios_only Scenario: Scene load with metrics @@ -114,24 +114,24 @@ Feature: Scene Load Spans And I wait to receive at least 1 span # rendering metrics - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.total_frames" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_average" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.slow_frames" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_maximum" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.rendering.fps_minimum" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.total_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.fps_average" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.slow_frames" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.fps_maximum" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.rendering.fps_minimum" greater than 0 # memory metrics - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.timestamps" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.device.physical_device_memory" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.memory.spaces.device.used" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.memory.timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.device.physical_device_memory" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an integer attribute "bugsnag.system.memory.spaces.device.size" greater than 0 + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.memory.spaces.device.used" with at least 2 elements # CPU metrics - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_timestamps" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_total" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages - * the span named "[ViewLoad/UnityScene]Scene1" has array attribute "bugsnag.system.cpu_measures_main_thread" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages - * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage - * the span named "[ViewLoad/UnityScene]Scene1" has double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.cpu_measures_timestamps" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.cpu_measures_total" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has an double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.cpu_measures_main_thread" with at least 2 elements + * the span named "[ViewLoad/UnityScene]Scene1" has a double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has a double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage + * the span named "[ViewLoad/UnityScene]Scene1" has a double attribute "bugsnag.system.cpu_mean_main_thread" that is a valid percentage diff --git a/features/steps/unity_steps.rb b/features/steps/unity_steps.rb index d302e44f..cf8d6f7b 100644 --- a/features/steps/unity_steps.rb +++ b/features/steps/unity_steps.rb @@ -325,21 +325,21 @@ def find_span_attr(span, key) find_span_attr(span, attr_key) # will raise if missing end -Then('the span named {string} has string attribute {string} equal to {string}') do |span_name, attr_key, expected| +Then('the span named {string} has a string attribute {string} equal to {string}') do |span_name, attr_key, expected| span = find_span_by_name(span_name) attr = find_span_attr(span, attr_key) actual = attr.dig('value', 'stringValue') Maze.check.equal(expected, actual, "Expected #{span_name}.#{attr_key} to be '#{expected}' but was '#{actual}'") end -Then('the span named {string} has integer attribute {string} greater than {int}') do |span_name, attr_key, min_value| +Then('the span named {string} has an integer attribute {string} greater than {int}') do |span_name, attr_key, min_value| span = find_span_by_name(span_name) attr = find_span_attr(span, attr_key) actual = attr.dig('value', 'intValue').to_i Maze.check.operator(actual, :>, min_value, "Expected #{span_name}.#{attr_key} to be > #{min_value} but was #{actual}") end -Then('the span named {string} has boolean attribute {string} equal to {word}') do |span_name, attr_key, expected_str| +Then('the span named {string} has a boolean attribute {string} equal to {word}') do |span_name, attr_key, expected_str| expected = expected_str == 'true' span = find_span_by_name(span_name) attr = find_span_attr(span, attr_key) @@ -347,7 +347,7 @@ def find_span_attr(span, key) Maze.check.equal(expected, actual, "Expected #{span_name}.#{attr_key} to be #{expected} but was #{actual}") end -Then('the span named {string} has array attribute {string} with at least {int} elements') do |span_name, attr_key, min_count| +Then('the span named {string} has an array attribute {string} with at least {int} elements') do |span_name, attr_key, min_count| span = find_span_by_name(span_name) attr = find_span_attr(span, attr_key) arr = attr.dig('value', 'arrayValue', 'values') @@ -355,7 +355,7 @@ def find_span_attr(span, key) Maze.check.operator(arr.length, :>=, min_count, "Expected at least #{min_count} elements but got #{arr.length}") end -Then('the span named {string} has double attribute {string} that is a valid percentage') do |span_name, attr_key| +Then('the span named {string} has a double attribute {string} that is a valid percentage') do |span_name, attr_key| span = find_span_by_name(span_name) attr = find_span_attr(span, attr_key) val = attr.dig('value', 'doubleValue') @@ -365,7 +365,7 @@ def find_span_attr(span, key) Maze.check.operator(num, :<=, 100.0, "Expected #{attr_key} <= 100.0, got #{num}") end -Then('the span named {string} has double array attribute {string} containing valid percentages') do |span_name, attr_key| +Then('the span named {string} has a double array attribute {string} containing valid percentages') do |span_name, attr_key| span = find_span_by_name(span_name) attr = find_span_attr(span, attr_key) arr = attr.dig('value', 'arrayValue', 'values') diff --git a/features/support/env.rb b/features/support/env.rb index 6c0d87e0..7f45c803 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -51,12 +51,6 @@ skip_this_scenario('Skipping scenario') unless Maze::Helper.get_current_platform == 'android' end -Before('@mobile_only') do |_scenario| - platform = Maze::Helper.get_current_platform - skip_this_scenario('Skipping scenario') unless ['ios', 'android'].include?(platform) -end - - BeforeAll do $api_key = 'a35a2a72bd230ac0aa0f52715bbdc6aa' Maze.config.enforce_bugsnag_integrity = false From 4747d06b114fe5c670d7839a4698ea4f7d07f8aa Mon Sep 17 00:00:00 2001 From: richard elms Date: Thu, 13 Nov 2025 12:49:26 +0100 Subject: [PATCH 6/6] typo --- features/scene_load_spans.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/scene_load_spans.feature b/features/scene_load_spans.feature index 6b7249c6..fec71265 100644 --- a/features/scene_load_spans.feature +++ b/features/scene_load_spans.feature @@ -129,7 +129,7 @@ Feature: Scene Load Spans # CPU metrics * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.cpu_measures_timestamps" with at least 2 elements * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.cpu_measures_total" with at least 2 elements - * the span named "[ViewLoad/UnityScene]Scene1" has an double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages + * the span named "[ViewLoad/UnityScene]Scene1" has a double array attribute "bugsnag.system.cpu_measures_total" containing valid percentages * the span named "[ViewLoad/UnityScene]Scene1" has an array attribute "bugsnag.system.cpu_measures_main_thread" with at least 2 elements * the span named "[ViewLoad/UnityScene]Scene1" has a double array attribute "bugsnag.system.cpu_measures_main_thread" containing valid percentages * the span named "[ViewLoad/UnityScene]Scene1" has a double attribute "bugsnag.system.cpu_mean_total" that is a valid percentage