An open source Danmaku development kit for Unity3D.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Preliminary Setup

james713 f8fd9307 bd76c2b5

+10090
+1
.gitignore
··· 9 9 *UnityVS* 10 10 11 11 # Autogenerated VS/MD solution and project files 12 + .vscode 12 13 /*.csproj 13 14 /*.unityproj 14 15 /*.sln
+9
Assets/UnityTestTools.meta
··· 1 + fileFormatVersion: 2 2 + guid: b3a1679829d41bd46b5f0dc1dc9509bf 3 + folderAsset: yes 4 + timeCreated: 1494703141 5 + licenseType: Pro 6 + DefaultImporter: 7 + userData: 8 + assetBundleName: 9 + assetBundleVariant:
+5
Assets/UnityTestTools/Assertions.meta
··· 1 + fileFormatVersion: 2 2 + guid: b27b28700d3365146808b6e082748201 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+379
Assets/UnityTestTools/Assertions/AssertionComponent.cs
··· 1 + using System; 2 + using System.Collections; 3 + using System.Collections.Generic; 4 + using System.Diagnostics; 5 + using System.Linq; 6 + using UnityEngine; 7 + using Debug = UnityEngine.Debug; 8 + using Object = UnityEngine.Object; 9 + 10 + namespace UnityTest 11 + { 12 + [Serializable] 13 + public class AssertionComponent : MonoBehaviour, IAssertionComponentConfigurator 14 + { 15 + [SerializeField] public float checkAfterTime = 1f; 16 + [SerializeField] public bool repeatCheckTime = true; 17 + [SerializeField] public float repeatEveryTime = 1f; 18 + [SerializeField] public int checkAfterFrames = 1; 19 + [SerializeField] public bool repeatCheckFrame = true; 20 + [SerializeField] public int repeatEveryFrame = 1; 21 + [SerializeField] public bool hasFailed; 22 + 23 + [SerializeField] public CheckMethod checkMethods = CheckMethod.Start; 24 + [SerializeField] private ActionBase m_ActionBase; 25 + 26 + [SerializeField] public int checksPerformed = 0; 27 + 28 + private int m_CheckOnFrame; 29 + 30 + private string m_CreatedInFilePath = ""; 31 + private int m_CreatedInFileLine = -1; 32 + 33 + public ActionBase Action 34 + { 35 + get { return m_ActionBase; } 36 + set 37 + { 38 + m_ActionBase = value; 39 + m_ActionBase.go = gameObject; 40 + } 41 + } 42 + 43 + public Object GetFailureReferenceObject() 44 + { 45 + #if UNITY_EDITOR 46 + if (!string.IsNullOrEmpty(m_CreatedInFilePath)) 47 + { 48 + return UnityEditor.AssetDatabase.LoadAssetAtPath(m_CreatedInFilePath, typeof(Object)); 49 + } 50 + #endif 51 + return this; 52 + } 53 + 54 + public string GetCreationLocation() 55 + { 56 + if (!string.IsNullOrEmpty(m_CreatedInFilePath)) 57 + { 58 + var idx = m_CreatedInFilePath.LastIndexOf("\\") + 1; 59 + return string.Format("{0}, line {1} ({2})", m_CreatedInFilePath.Substring(idx), m_CreatedInFileLine, m_CreatedInFilePath); 60 + } 61 + return ""; 62 + } 63 + 64 + public void Awake() 65 + { 66 + if (!Debug.isDebugBuild) 67 + Destroy(this); 68 + OnComponentCopy(); 69 + } 70 + 71 + public void OnValidate() 72 + { 73 + if (Application.isEditor) 74 + OnComponentCopy(); 75 + } 76 + 77 + private void OnComponentCopy() 78 + { 79 + if (m_ActionBase == null) return; 80 + var oldActionList = Resources.FindObjectsOfTypeAll(typeof(AssertionComponent)).Where(o => ((AssertionComponent)o).m_ActionBase == m_ActionBase && o != this); 81 + 82 + // if it's not a copy but a new component don't do anything 83 + if (!oldActionList.Any()) return; 84 + if (oldActionList.Count() > 1) 85 + Debug.LogWarning("More than one refence to comparer found. This shouldn't happen"); 86 + 87 + var oldAction = oldActionList.First() as AssertionComponent; 88 + m_ActionBase = oldAction.m_ActionBase.CreateCopy(oldAction.gameObject, gameObject); 89 + } 90 + 91 + public void Start() 92 + { 93 + CheckAssertionFor(CheckMethod.Start); 94 + 95 + if (IsCheckMethodSelected(CheckMethod.AfterPeriodOfTime)) 96 + { 97 + StartCoroutine("CheckPeriodically"); 98 + } 99 + if (IsCheckMethodSelected(CheckMethod.Update)) 100 + { 101 + m_CheckOnFrame = Time.frameCount + checkAfterFrames; 102 + } 103 + } 104 + 105 + public IEnumerator CheckPeriodically() 106 + { 107 + yield return new WaitForSeconds(checkAfterTime); 108 + CheckAssertionFor(CheckMethod.AfterPeriodOfTime); 109 + while (repeatCheckTime) 110 + { 111 + yield return new WaitForSeconds(repeatEveryTime); 112 + CheckAssertionFor(CheckMethod.AfterPeriodOfTime); 113 + } 114 + } 115 + 116 + public bool ShouldCheckOnFrame() 117 + { 118 + if (Time.frameCount > m_CheckOnFrame) 119 + { 120 + if (repeatCheckFrame) 121 + m_CheckOnFrame += repeatEveryFrame; 122 + else 123 + m_CheckOnFrame = Int32.MaxValue; 124 + return true; 125 + } 126 + return false; 127 + } 128 + 129 + public void OnDisable() 130 + { 131 + CheckAssertionFor(CheckMethod.OnDisable); 132 + } 133 + 134 + public void OnEnable() 135 + { 136 + CheckAssertionFor(CheckMethod.OnEnable); 137 + } 138 + 139 + public void OnDestroy() 140 + { 141 + CheckAssertionFor(CheckMethod.OnDestroy); 142 + } 143 + 144 + public void Update() 145 + { 146 + if (IsCheckMethodSelected(CheckMethod.Update) && ShouldCheckOnFrame()) 147 + { 148 + CheckAssertionFor(CheckMethod.Update); 149 + } 150 + } 151 + 152 + public void FixedUpdate() 153 + { 154 + CheckAssertionFor(CheckMethod.FixedUpdate); 155 + } 156 + 157 + public void LateUpdate() 158 + { 159 + CheckAssertionFor(CheckMethod.LateUpdate); 160 + } 161 + 162 + public void OnControllerColliderHit() 163 + { 164 + CheckAssertionFor(CheckMethod.OnControllerColliderHit); 165 + } 166 + 167 + public void OnParticleCollision() 168 + { 169 + CheckAssertionFor(CheckMethod.OnParticleCollision); 170 + } 171 + 172 + public void OnJointBreak() 173 + { 174 + CheckAssertionFor(CheckMethod.OnJointBreak); 175 + } 176 + 177 + public void OnBecameInvisible() 178 + { 179 + CheckAssertionFor(CheckMethod.OnBecameInvisible); 180 + } 181 + 182 + public void OnBecameVisible() 183 + { 184 + CheckAssertionFor(CheckMethod.OnBecameVisible); 185 + } 186 + 187 + public void OnTriggerEnter() 188 + { 189 + CheckAssertionFor(CheckMethod.OnTriggerEnter); 190 + } 191 + 192 + public void OnTriggerExit() 193 + { 194 + CheckAssertionFor(CheckMethod.OnTriggerExit); 195 + } 196 + 197 + public void OnTriggerStay() 198 + { 199 + CheckAssertionFor(CheckMethod.OnTriggerStay); 200 + } 201 + 202 + public void OnCollisionEnter() 203 + { 204 + CheckAssertionFor(CheckMethod.OnCollisionEnter); 205 + } 206 + 207 + public void OnCollisionExit() 208 + { 209 + CheckAssertionFor(CheckMethod.OnCollisionExit); 210 + } 211 + 212 + public void OnCollisionStay() 213 + { 214 + CheckAssertionFor(CheckMethod.OnCollisionStay); 215 + } 216 + 217 + public void OnTriggerEnter2D() 218 + { 219 + CheckAssertionFor(CheckMethod.OnTriggerEnter2D); 220 + } 221 + 222 + public void OnTriggerExit2D() 223 + { 224 + CheckAssertionFor(CheckMethod.OnTriggerExit2D); 225 + } 226 + 227 + public void OnTriggerStay2D() 228 + { 229 + CheckAssertionFor(CheckMethod.OnTriggerStay2D); 230 + } 231 + 232 + public void OnCollisionEnter2D() 233 + { 234 + CheckAssertionFor(CheckMethod.OnCollisionEnter2D); 235 + } 236 + 237 + public void OnCollisionExit2D() 238 + { 239 + CheckAssertionFor(CheckMethod.OnCollisionExit2D); 240 + } 241 + 242 + public void OnCollisionStay2D() 243 + { 244 + CheckAssertionFor(CheckMethod.OnCollisionStay2D); 245 + } 246 + 247 + private void CheckAssertionFor(CheckMethod checkMethod) 248 + { 249 + if (IsCheckMethodSelected(checkMethod)) 250 + { 251 + Assertions.CheckAssertions(this); 252 + } 253 + } 254 + 255 + public bool IsCheckMethodSelected(CheckMethod method) 256 + { 257 + return method == (checkMethods & method); 258 + } 259 + 260 + 261 + #region Assertion Component create methods 262 + 263 + public static T Create<T>(CheckMethod checkOnMethods, GameObject gameObject, string propertyPath) where T : ActionBase 264 + { 265 + IAssertionComponentConfigurator configurator; 266 + return Create<T>(out configurator, checkOnMethods, gameObject, propertyPath); 267 + } 268 + 269 + public static T Create<T>(out IAssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath) where T : ActionBase 270 + { 271 + return CreateAssertionComponent<T>(out configurator, checkOnMethods, gameObject, propertyPath); 272 + } 273 + 274 + public static T Create<T>(CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, GameObject gameObject2, string propertyPath2) where T : ComparerBase 275 + { 276 + IAssertionComponentConfigurator configurator; 277 + return Create<T>(out configurator, checkOnMethods, gameObject, propertyPath, gameObject2, propertyPath2); 278 + } 279 + 280 + public static T Create<T>(out IAssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, GameObject gameObject2, string propertyPath2) where T : ComparerBase 281 + { 282 + var comparer = CreateAssertionComponent<T>(out configurator, checkOnMethods, gameObject, propertyPath); 283 + comparer.compareToType = ComparerBase.CompareToType.CompareToObject; 284 + comparer.other = gameObject2; 285 + comparer.otherPropertyPath = propertyPath2; 286 + return comparer; 287 + } 288 + 289 + public static T Create<T>(CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, object constValue) where T : ComparerBase 290 + { 291 + IAssertionComponentConfigurator configurator; 292 + return Create<T>(out configurator, checkOnMethods, gameObject, propertyPath, constValue); 293 + } 294 + 295 + public static T Create<T>(out IAssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath, object constValue) where T : ComparerBase 296 + { 297 + var comparer = CreateAssertionComponent<T>(out configurator, checkOnMethods, gameObject, propertyPath); 298 + if (constValue == null) 299 + { 300 + comparer.compareToType = ComparerBase.CompareToType.CompareToNull; 301 + return comparer; 302 + } 303 + comparer.compareToType = ComparerBase.CompareToType.CompareToConstantValue; 304 + comparer.ConstValue = constValue; 305 + return comparer; 306 + } 307 + 308 + private static T CreateAssertionComponent<T>(out IAssertionComponentConfigurator configurator, CheckMethod checkOnMethods, GameObject gameObject, string propertyPath) where T : ActionBase 309 + { 310 + var ac = gameObject.AddComponent<AssertionComponent>(); 311 + ac.checkMethods = checkOnMethods; 312 + var comparer = ScriptableObject.CreateInstance<T>(); 313 + ac.Action = comparer; 314 + ac.Action.go = gameObject; 315 + ac.Action.thisPropertyPath = propertyPath; 316 + configurator = ac; 317 + 318 + #if !UNITY_METRO 319 + var stackTrace = new StackTrace(true); 320 + var thisFileName = stackTrace.GetFrame(0).GetFileName(); 321 + for (int i = 1; i < stackTrace.FrameCount; i++) 322 + { 323 + var stackFrame = stackTrace.GetFrame(i); 324 + if (stackFrame.GetFileName() != thisFileName) 325 + { 326 + string filePath = stackFrame.GetFileName().Substring(Application.dataPath.Length - "Assets".Length); 327 + ac.m_CreatedInFilePath = filePath; 328 + ac.m_CreatedInFileLine = stackFrame.GetFileLineNumber(); 329 + break; 330 + } 331 + } 332 + #endif // if !UNITY_METRO 333 + return comparer; 334 + } 335 + 336 + #endregion 337 + 338 + #region AssertionComponentConfigurator 339 + public int UpdateCheckStartOnFrame { set { checkAfterFrames = value; } } 340 + public int UpdateCheckRepeatFrequency { set { repeatEveryFrame = value; } } 341 + public bool UpdateCheckRepeat { set { repeatCheckFrame = value; } } 342 + public float TimeCheckStartAfter { set { checkAfterTime = value; } } 343 + public float TimeCheckRepeatFrequency { set { repeatEveryTime = value; } } 344 + public bool TimeCheckRepeat { set { repeatCheckTime = value; } } 345 + public AssertionComponent Component { get { return this; } } 346 + #endregion 347 + } 348 + 349 + public interface IAssertionComponentConfigurator 350 + { 351 + /// <summary> 352 + /// If the assertion is evaluated in Update, after how many frame should the evaluation start. Deafult is 1 (first frame) 353 + /// </summary> 354 + int UpdateCheckStartOnFrame { set; } 355 + /// <summary> 356 + /// If the assertion is evaluated in Update and UpdateCheckRepeat is true, how many frame should pass between evaluations 357 + /// </summary> 358 + int UpdateCheckRepeatFrequency { set; } 359 + /// <summary> 360 + /// If the assertion is evaluated in Update, should the evaluation be repeated after UpdateCheckRepeatFrequency frames 361 + /// </summary> 362 + bool UpdateCheckRepeat { set; } 363 + 364 + /// <summary> 365 + /// If the assertion is evaluated after a period of time, after how many seconds the first evaluation should be done 366 + /// </summary> 367 + float TimeCheckStartAfter { set; } 368 + /// <summary> 369 + /// If the assertion is evaluated after a period of time and TimeCheckRepeat is true, after how many seconds should the next evaluation happen 370 + /// </summary> 371 + float TimeCheckRepeatFrequency { set; } 372 + /// <summary> 373 + /// If the assertion is evaluated after a period, should the evaluation happen again after TimeCheckRepeatFrequency seconds 374 + /// </summary> 375 + bool TimeCheckRepeat { set; } 376 + 377 + AssertionComponent Component { get; } 378 + } 379 + }
+8
Assets/UnityTestTools/Assertions/AssertionComponent.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 8bafa54482a87ac4cbd7ff1bfd1ac93a 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+24
Assets/UnityTestTools/Assertions/AssertionException.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class AssertionException : Exception 8 + { 9 + private readonly AssertionComponent m_Assertion; 10 + 11 + public AssertionException(AssertionComponent assertion) : base(assertion.Action.GetFailureMessage()) 12 + { 13 + m_Assertion = assertion; 14 + } 15 + 16 + public override string StackTrace 17 + { 18 + get 19 + { 20 + return "Created in " + m_Assertion.GetCreationLocation(); 21 + } 22 + } 23 + } 24 + }
+8
Assets/UnityTestTools/Assertions/AssertionException.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: ef3769ab00d50bc4fbb05a9a91c741d9 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+42
Assets/UnityTestTools/Assertions/Assertions.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + using Object = UnityEngine.Object; 5 + 6 + namespace UnityTest 7 + { 8 + public static class Assertions 9 + { 10 + public static void CheckAssertions() 11 + { 12 + var assertions = Object.FindObjectsOfType(typeof(AssertionComponent)) as AssertionComponent[]; 13 + CheckAssertions(assertions); 14 + } 15 + 16 + public static void CheckAssertions(AssertionComponent assertion) 17 + { 18 + CheckAssertions(new[] {assertion}); 19 + } 20 + 21 + public static void CheckAssertions(GameObject gameObject) 22 + { 23 + CheckAssertions(gameObject.GetComponents<AssertionComponent>()); 24 + } 25 + 26 + public static void CheckAssertions(AssertionComponent[] assertions) 27 + { 28 + if (!Debug.isDebugBuild) 29 + return; 30 + foreach (var assertion in assertions) 31 + { 32 + assertion.checksPerformed++; 33 + var result = assertion.Action.Compare(); 34 + if (!result) 35 + { 36 + assertion.hasFailed = true; 37 + assertion.Action.Fail(assertion); 38 + } 39 + } 40 + } 41 + } 42 + }
+8
Assets/UnityTestTools/Assertions/Assertions.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 85280dad1e618c143bd3fb07a197b469 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+36
Assets/UnityTestTools/Assertions/CheckMethod.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + [Flags] 8 + public enum CheckMethod 9 + { 10 + AfterPeriodOfTime = 1 << 0, 11 + Start = 1 << 1, 12 + Update = 1 << 2, 13 + FixedUpdate = 1 << 3, 14 + LateUpdate = 1 << 4, 15 + OnDestroy = 1 << 5, 16 + OnEnable = 1 << 6, 17 + OnDisable = 1 << 7, 18 + OnControllerColliderHit = 1 << 8, 19 + OnParticleCollision = 1 << 9, 20 + OnJointBreak = 1 << 10, 21 + OnBecameInvisible = 1 << 11, 22 + OnBecameVisible = 1 << 12, 23 + OnTriggerEnter = 1 << 13, 24 + OnTriggerExit = 1 << 14, 25 + OnTriggerStay = 1 << 15, 26 + OnCollisionEnter = 1 << 16, 27 + OnCollisionExit = 1 << 17, 28 + OnCollisionStay = 1 << 18, 29 + OnTriggerEnter2D = 1 << 19, 30 + OnTriggerExit2D = 1 << 20, 31 + OnTriggerStay2D = 1 << 21, 32 + OnCollisionEnter2D = 1 << 22, 33 + OnCollisionExit2D = 1 << 23, 34 + OnCollisionStay2D = 1 << 24, 35 + } 36 + }
+8
Assets/UnityTestTools/Assertions/CheckMethod.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: cbb75d1643c5a55439f8861a827f411b 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+5
Assets/UnityTestTools/Assertions/Comparers.meta
··· 1 + fileFormatVersion: 2 2 + guid: bb9e10c25f478c84f826ea85b03ec179 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+121
Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using System.Reflection; 5 + using UnityEngine; 6 + 7 + namespace UnityTest 8 + { 9 + public abstract class ActionBase : ScriptableObject 10 + { 11 + public GameObject go; 12 + protected object m_ObjVal; 13 + 14 + private MemberResolver m_MemberResolver; 15 + 16 + public string thisPropertyPath = ""; 17 + public virtual Type[] GetAccepatbleTypesForA() 18 + { 19 + return null; 20 + } 21 + public virtual int GetDepthOfSearch() { return 2; } 22 + 23 + public virtual string[] GetExcludedFieldNames() 24 + { 25 + return new string[] { }; 26 + } 27 + 28 + public bool Compare() 29 + { 30 + if (m_MemberResolver == null) 31 + m_MemberResolver = new MemberResolver(go, thisPropertyPath); 32 + m_ObjVal = m_MemberResolver.GetValue(UseCache); 33 + var result = Compare(m_ObjVal); 34 + return result; 35 + } 36 + 37 + protected abstract bool Compare(object objVal); 38 + 39 + virtual protected bool UseCache { get { return false; } } 40 + 41 + public virtual Type GetParameterType() { return typeof(object); } 42 + 43 + public virtual string GetConfigurationDescription() 44 + { 45 + string result = ""; 46 + #if !UNITY_METRO 47 + foreach (var prop in GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) 48 + .Where(info => info.FieldType.IsSerializable)) 49 + { 50 + var value = prop.GetValue(this); 51 + if (value is double) 52 + value = ((double)value).ToString("0.########"); 53 + if (value is float) 54 + value = ((float)value).ToString("0.########"); 55 + result += value + " "; 56 + } 57 + #endif // if !UNITY_METRO 58 + return result; 59 + } 60 + 61 + IEnumerable<FieldInfo> GetFields(Type type) 62 + { 63 + #if !UNITY_METRO 64 + return type.GetFields(BindingFlags.Public | BindingFlags.Instance); 65 + #else 66 + return null; 67 + #endif 68 + } 69 + 70 + public ActionBase CreateCopy(GameObject oldGameObject, GameObject newGameObject) 71 + { 72 + #if !UNITY_METRO 73 + var newObj = CreateInstance(GetType()) as ActionBase; 74 + #else 75 + var newObj = (ActionBase) this.MemberwiseClone(); 76 + #endif 77 + var fields = GetFields(GetType()); 78 + foreach (var field in fields) 79 + { 80 + var value = field.GetValue(this); 81 + if (value is GameObject) 82 + { 83 + if (value as GameObject == oldGameObject) 84 + value = newGameObject; 85 + } 86 + field.SetValue(newObj, value); 87 + } 88 + return newObj; 89 + } 90 + 91 + public virtual void Fail(AssertionComponent assertion) 92 + { 93 + Debug.LogException(new AssertionException(assertion), assertion.GetFailureReferenceObject()); 94 + } 95 + 96 + public virtual string GetFailureMessage() 97 + { 98 + return GetType().Name + " assertion failed.\n(" + go + ")." + thisPropertyPath + " failed. Value: " + m_ObjVal; 99 + } 100 + } 101 + 102 + public abstract class ActionBaseGeneric<T> : ActionBase 103 + { 104 + protected override bool Compare(object objVal) 105 + { 106 + return Compare((T)objVal); 107 + } 108 + protected abstract bool Compare(T objVal); 109 + 110 + public override Type[] GetAccepatbleTypesForA() 111 + { 112 + return new[] { typeof(T) }; 113 + } 114 + 115 + public override Type GetParameterType() 116 + { 117 + return typeof(T); 118 + } 119 + protected override bool UseCache { get { return true; } } 120 + } 121 + }
+8
Assets/UnityTestTools/Assertions/Comparers/ActionBase.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: b4995756bd539804e8143ff1e730f806 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+14
Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class BoolComparer : ComparerBaseGeneric<bool> 8 + { 9 + protected override bool Compare(bool a, bool b) 10 + { 11 + return a == b; 12 + } 13 + } 14 + }
+8
Assets/UnityTestTools/Assertions/Comparers/BoolComparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 2586c8e41f35d2f4fadde53020bf4207 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+29
Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class ColliderComparer : ComparerBaseGeneric<Bounds> 8 + { 9 + public enum CompareType 10 + { 11 + Intersects, 12 + DoesNotIntersect 13 + }; 14 + 15 + public CompareType compareType; 16 + 17 + protected override bool Compare(Bounds a, Bounds b) 18 + { 19 + switch (compareType) 20 + { 21 + case CompareType.Intersects: 22 + return a.Intersects(b); 23 + case CompareType.DoesNotIntersect: 24 + return !a.Intersects(b); 25 + } 26 + throw new Exception(); 27 + } 28 + } 29 + }
+8
Assets/UnityTestTools/Assertions/Comparers/ColliderComparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 4eff45b2ac4067b469d7994298341db6 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+145
Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + using Object = System.Object; 5 + 6 + namespace UnityTest 7 + { 8 + public abstract class ComparerBase : ActionBase 9 + { 10 + public enum CompareToType 11 + { 12 + CompareToObject, 13 + CompareToConstantValue, 14 + CompareToNull 15 + } 16 + 17 + public CompareToType compareToType = CompareToType.CompareToObject; 18 + 19 + public GameObject other; 20 + protected object m_ObjOtherVal; 21 + public string otherPropertyPath = ""; 22 + private MemberResolver m_MemberResolverB; 23 + 24 + protected abstract bool Compare(object a, object b); 25 + 26 + protected override bool Compare(object objValue) 27 + { 28 + if (compareToType == CompareToType.CompareToConstantValue) 29 + { 30 + m_ObjOtherVal = ConstValue; 31 + } 32 + else if (compareToType == CompareToType.CompareToNull) 33 + { 34 + m_ObjOtherVal = null; 35 + } 36 + else 37 + { 38 + if (other == null) 39 + m_ObjOtherVal = null; 40 + else 41 + { 42 + if (m_MemberResolverB == null) 43 + m_MemberResolverB = new MemberResolver(other, otherPropertyPath); 44 + m_ObjOtherVal = m_MemberResolverB.GetValue(UseCache); 45 + } 46 + } 47 + return Compare(objValue, m_ObjOtherVal); 48 + } 49 + 50 + public virtual Type[] GetAccepatbleTypesForB() 51 + { 52 + return null; 53 + } 54 + 55 + #region Const value 56 + 57 + public virtual object ConstValue { get; set; } 58 + public virtual object GetDefaultConstValue() 59 + { 60 + throw new NotImplementedException(); 61 + } 62 + 63 + #endregion 64 + 65 + public override string GetFailureMessage() 66 + { 67 + var message = GetType().Name + " assertion failed.\n" + go.name + "." + thisPropertyPath + " " + compareToType; 68 + switch (compareToType) 69 + { 70 + case CompareToType.CompareToObject: 71 + message += " (" + other + ")." + otherPropertyPath + " failed."; 72 + break; 73 + case CompareToType.CompareToConstantValue: 74 + message += " " + ConstValue + " failed."; 75 + break; 76 + case CompareToType.CompareToNull: 77 + message += " failed."; 78 + break; 79 + } 80 + message += " Expected: " + m_ObjOtherVal + " Actual: " + m_ObjVal; 81 + return message; 82 + } 83 + } 84 + 85 + [Serializable] 86 + public abstract class ComparerBaseGeneric<T> : ComparerBaseGeneric<T, T> 87 + { 88 + } 89 + 90 + [Serializable] 91 + public abstract class ComparerBaseGeneric<T1, T2> : ComparerBase 92 + { 93 + public T2 constantValueGeneric = default(T2); 94 + 95 + public override Object ConstValue 96 + { 97 + get 98 + { 99 + return constantValueGeneric; 100 + } 101 + set 102 + { 103 + constantValueGeneric = (T2)value; 104 + } 105 + } 106 + 107 + public override Object GetDefaultConstValue() 108 + { 109 + return default(T2); 110 + } 111 + 112 + static bool IsValueType(Type type) 113 + { 114 + #if !UNITY_METRO 115 + return type.IsValueType; 116 + #else 117 + return false; 118 + #endif 119 + } 120 + 121 + protected override bool Compare(object a, object b) 122 + { 123 + var type = typeof(T2); 124 + if (b == null && IsValueType(type)) 125 + { 126 + throw new ArgumentException("Null was passed to a value-type argument"); 127 + } 128 + return Compare((T1)a, (T2)b); 129 + } 130 + 131 + protected abstract bool Compare(T1 a, T2 b); 132 + 133 + public override Type[] GetAccepatbleTypesForA() 134 + { 135 + return new[] { typeof(T1) }; 136 + } 137 + 138 + public override Type[] GetAccepatbleTypesForB() 139 + { 140 + return new[] {typeof(T2)}; 141 + } 142 + 143 + protected override bool UseCache { get { return true; } } 144 + } 145 + }
+8
Assets/UnityTestTools/Assertions/Comparers/ComparerBase.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: c86508f389d643b40b6e1d7dcc1d4df2 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+40
Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class FloatComparer : ComparerBaseGeneric<float> 8 + { 9 + public enum CompareTypes 10 + { 11 + Equal, 12 + NotEqual, 13 + Greater, 14 + Less 15 + } 16 + 17 + public CompareTypes compareTypes; 18 + public double floatingPointError = 0.0001f; 19 + 20 + protected override bool Compare(float a, float b) 21 + { 22 + switch (compareTypes) 23 + { 24 + case CompareTypes.Equal: 25 + return Math.Abs(a - b) < floatingPointError; 26 + case CompareTypes.NotEqual: 27 + return Math.Abs(a - b) > floatingPointError; 28 + case CompareTypes.Greater: 29 + return a > b; 30 + case CompareTypes.Less: 31 + return a < b; 32 + } 33 + throw new Exception(); 34 + } 35 + public override int GetDepthOfSearch() 36 + { 37 + return 3; 38 + } 39 + } 40 + }
+8
Assets/UnityTestTools/Assertions/Comparers/FloatComparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: a4928c6c2b973874c8d4e6c9a69bb5b4 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+22
Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class GeneralComparer : ComparerBase 8 + { 9 + public enum CompareType { AEqualsB, ANotEqualsB } 10 + 11 + public CompareType compareType; 12 + 13 + protected override bool Compare(object a, object b) 14 + { 15 + if (compareType == CompareType.AEqualsB) 16 + return a.Equals(b); 17 + if (compareType == CompareType.ANotEqualsB) 18 + return !a.Equals(b); 19 + throw new Exception(); 20 + } 21 + } 22 + }
+8
Assets/UnityTestTools/Assertions/Comparers/GeneralComparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 902961c69f102f4409c29b9e54258701 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+41
Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class IntComparer : ComparerBaseGeneric<int> 8 + { 9 + public enum CompareType 10 + { 11 + Equal, 12 + NotEqual, 13 + Greater, 14 + GreaterOrEqual, 15 + Less, 16 + LessOrEqual 17 + }; 18 + 19 + public CompareType compareType; 20 + 21 + protected override bool Compare(int a, int b) 22 + { 23 + switch (compareType) 24 + { 25 + case CompareType.Equal: 26 + return a == b; 27 + case CompareType.NotEqual: 28 + return a != b; 29 + case CompareType.Greater: 30 + return a > b; 31 + case CompareType.GreaterOrEqual: 32 + return a >= b; 33 + case CompareType.Less: 34 + return a < b; 35 + case CompareType.LessOrEqual: 36 + return a <= b; 37 + } 38 + throw new Exception(); 39 + } 40 + } 41 + }
+8
Assets/UnityTestTools/Assertions/Comparers/IntComparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: da4a3a521c5c1494aae123742ca5c8f5 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+31
Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class IsRenderedByCamera : ComparerBaseGeneric<Renderer, Camera> 8 + { 9 + public enum CompareType 10 + { 11 + IsVisible, 12 + IsNotVisible, 13 + }; 14 + 15 + public CompareType compareType; 16 + 17 + protected override bool Compare(Renderer renderer, Camera camera) 18 + { 19 + var planes = GeometryUtility.CalculateFrustumPlanes(camera); 20 + var isVisible = GeometryUtility.TestPlanesAABB(planes, renderer.bounds); 21 + switch (compareType) 22 + { 23 + case CompareType.IsVisible: 24 + return isVisible; 25 + case CompareType.IsNotVisible: 26 + return !isVisible; 27 + } 28 + throw new Exception(); 29 + } 30 + } 31 + }
+8
Assets/UnityTestTools/Assertions/Comparers/IsRenderedByCamera.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 8d45a1674f5e2e04485eafef922fac41 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+42
Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class StringComparer : ComparerBaseGeneric<string> 8 + { 9 + public enum CompareType 10 + { 11 + Equal, 12 + NotEqual, 13 + Shorter, 14 + Longer 15 + } 16 + 17 + public CompareType compareType; 18 + public StringComparison comparisonType = StringComparison.Ordinal; 19 + public bool ignoreCase = false; 20 + 21 + protected override bool Compare(string a, string b) 22 + { 23 + if (ignoreCase) 24 + { 25 + a = a.ToLower(); 26 + b = b.ToLower(); 27 + } 28 + switch (compareType) 29 + { 30 + case CompareType.Equal: 31 + return String.Compare(a, b, comparisonType) == 0; 32 + case CompareType.NotEqual: 33 + return String.Compare(a, b, comparisonType) != 0; 34 + case CompareType.Longer: 35 + return String.Compare(a, b, comparisonType) > 0; 36 + case CompareType.Shorter: 37 + return String.Compare(a, b, comparisonType) < 0; 38 + } 39 + throw new Exception(); 40 + } 41 + } 42 + }
+8
Assets/UnityTestTools/Assertions/Comparers/StringComparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 58783f051e477fd4e93b42ec7a43bb64 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+26
Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class TransformComparer : ComparerBaseGeneric<Transform> 8 + { 9 + public enum CompareType { Equals, NotEquals } 10 + 11 + public CompareType compareType; 12 + 13 + protected override bool Compare(Transform a, Transform b) 14 + { 15 + if (compareType == CompareType.Equals) 16 + { 17 + return a.position == b.position; 18 + } 19 + if (compareType == CompareType.NotEquals) 20 + { 21 + return a.position != b.position; 22 + } 23 + throw new Exception(); 24 + } 25 + } 26 + }
+8
Assets/UnityTestTools/Assertions/Comparers/TransformComparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 927f2d7e4f63632448b2a63d480e601a 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+20
Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class ValueDoesNotChange : ActionBase 8 + { 9 + private object m_Value; 10 + 11 + protected override bool Compare(object a) 12 + { 13 + if (m_Value == null) 14 + m_Value = a; 15 + if (!m_Value.Equals(a)) 16 + return false; 17 + return true; 18 + } 19 + } 20 + }
+8
Assets/UnityTestTools/Assertions/Comparers/ValueDoesNotChange.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 9d6d16a58a17940419a1dcbff3c60ca5 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+36
Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class Vector2Comparer : VectorComparerBase<Vector2> 8 + { 9 + public enum CompareType 10 + { 11 + MagnitudeEquals, 12 + MagnitudeNotEquals 13 + } 14 + 15 + public CompareType compareType; 16 + public float floatingPointError = 0.0001f; 17 + 18 + protected override bool Compare(Vector2 a, Vector2 b) 19 + { 20 + switch (compareType) 21 + { 22 + case CompareType.MagnitudeEquals: 23 + return AreVectorMagnitudeEqual(a.magnitude, 24 + b.magnitude, floatingPointError); 25 + case CompareType.MagnitudeNotEquals: 26 + return !AreVectorMagnitudeEqual(a.magnitude, 27 + b.magnitude, floatingPointError); 28 + } 29 + throw new Exception(); 30 + } 31 + public override int GetDepthOfSearch() 32 + { 33 + return 3; 34 + } 35 + } 36 + }
+8
Assets/UnityTestTools/Assertions/Comparers/Vector2Comparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: a713db190443e814f8254a5a59014ec4 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+32
Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class Vector3Comparer : VectorComparerBase<Vector3> 8 + { 9 + public enum CompareType 10 + { 11 + MagnitudeEquals, 12 + MagnitudeNotEquals 13 + } 14 + 15 + public CompareType compareType; 16 + public double floatingPointError = 0.0001f; 17 + 18 + protected override bool Compare(Vector3 a, Vector3 b) 19 + { 20 + switch (compareType) 21 + { 22 + case CompareType.MagnitudeEquals: 23 + return AreVectorMagnitudeEqual(a.magnitude, 24 + b.magnitude, floatingPointError); 25 + case CompareType.MagnitudeNotEquals: 26 + return !AreVectorMagnitudeEqual(a.magnitude, 27 + b.magnitude, floatingPointError); 28 + } 29 + throw new Exception(); 30 + } 31 + } 32 + }
+8
Assets/UnityTestTools/Assertions/Comparers/Vector3Comparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 6febd2d5046657040b3da98b7010ee29 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+38
Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class Vector4Comparer : VectorComparerBase<Vector4> 8 + { 9 + public enum CompareType 10 + { 11 + MagnitudeEquals, 12 + MagnitudeNotEquals 13 + } 14 + 15 + public CompareType compareType; 16 + public double floatingPointError; 17 + 18 + protected override bool Compare(Vector4 a, Vector4 b) 19 + { 20 + switch (compareType) 21 + { 22 + case CompareType.MagnitudeEquals: 23 + return AreVectorMagnitudeEqual(a.magnitude, 24 + b.magnitude, 25 + floatingPointError); 26 + case CompareType.MagnitudeNotEquals: 27 + return !AreVectorMagnitudeEqual(a.magnitude, 28 + b.magnitude, 29 + floatingPointError); 30 + } 31 + throw new Exception(); 32 + } 33 + public override int GetDepthOfSearch() 34 + { 35 + return 3; 36 + } 37 + } 38 + }
+8
Assets/UnityTestTools/Assertions/Comparers/Vector4Comparer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 383a85a79f164d04b8a56b0ff4e04cb7 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+18
Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public abstract class VectorComparerBase<T> : ComparerBaseGeneric<T> 8 + { 9 + protected bool AreVectorMagnitudeEqual(float a, float b, double floatingPointError) 10 + { 11 + if (Math.Abs(a) < floatingPointError && Math.Abs(b) < floatingPointError) 12 + return true; 13 + if (Math.Abs(a - b) < floatingPointError) 14 + return true; 15 + return false; 16 + } 17 + } 18 + }
+8
Assets/UnityTestTools/Assertions/Comparers/VectorComparerBase.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 7b35a237804d5eb42bd8c4e67568ae24 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+5
Assets/UnityTestTools/Assertions/Editor.meta
··· 1 + fileFormatVersion: 2 2 + guid: a28bb39b4fb20514990895d9cb4eaea9 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+223
Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using System.Reflection; 5 + using UnityEditor; 6 + using UnityEngine; 7 + 8 + namespace UnityTest 9 + { 10 + [CustomEditor(typeof(AssertionComponent))] 11 + public class AssertionComponentEditor : Editor 12 + { 13 + private readonly DropDownControl<Type> m_ComparerDropDown = new DropDownControl<Type>(); 14 + 15 + private readonly PropertyPathSelector m_ThisPathSelector = new PropertyPathSelector("Compare"); 16 + private readonly PropertyPathSelector m_OtherPathSelector = new PropertyPathSelector("Compare to"); 17 + 18 + #region GUI Contents 19 + private readonly GUIContent m_GUICheckAfterTimeGuiContent = new GUIContent("Check after (seconds)", "After how many seconds the assertion should be checked"); 20 + private readonly GUIContent m_GUIRepeatCheckTimeGuiContent = new GUIContent("Repeat check", "Should the check be repeated."); 21 + private readonly GUIContent m_GUIRepeatEveryTimeGuiContent = new GUIContent("Frequency of repetitions", "How often should the check be done"); 22 + private readonly GUIContent m_GUICheckAfterFramesGuiContent = new GUIContent("Check after (frames)", "After how many frames the assertion should be checked"); 23 + private readonly GUIContent m_GUIRepeatCheckFrameGuiContent = new GUIContent("Repeat check", "Should the check be repeated."); 24 + #endregion 25 + 26 + private static List<Type> allComparersList = null; 27 + 28 + public AssertionComponentEditor() 29 + { 30 + m_ComparerDropDown.convertForButtonLabel = type => type.Name; 31 + m_ComparerDropDown.convertForGUIContent = type => type.Name; 32 + m_ComparerDropDown.ignoreConvertForGUIContent = types => false; 33 + m_ComparerDropDown.tooltip = "Comparer that will be used to compare values and determine the result of assertion."; 34 + } 35 + 36 + public override void OnInspectorGUI() 37 + { 38 + var script = (AssertionComponent)target; 39 + EditorGUILayout.BeginHorizontal(); 40 + var obj = DrawComparerSelection(script); 41 + script.checkMethods = (CheckMethod)EditorGUILayout.EnumMaskField(script.checkMethods, 42 + EditorStyles.popup, 43 + GUILayout.ExpandWidth(false)); 44 + EditorGUILayout.EndHorizontal(); 45 + 46 + if (script.IsCheckMethodSelected(CheckMethod.AfterPeriodOfTime)) 47 + { 48 + DrawOptionsForAfterPeriodOfTime(script); 49 + } 50 + 51 + if (script.IsCheckMethodSelected(CheckMethod.Update)) 52 + { 53 + DrawOptionsForOnUpdate(script); 54 + } 55 + 56 + if (obj) 57 + { 58 + EditorGUILayout.Space(); 59 + 60 + m_ThisPathSelector.Draw(script.Action.go, script.Action, 61 + script.Action.thisPropertyPath, script.Action.GetAccepatbleTypesForA(), 62 + go => 63 + { 64 + script.Action.go = go; 65 + AssertionExplorerWindow.Reload(); 66 + }, 67 + s => 68 + { 69 + script.Action.thisPropertyPath = s; 70 + AssertionExplorerWindow.Reload(); 71 + }); 72 + 73 + EditorGUILayout.Space(); 74 + 75 + DrawCustomFields(script); 76 + 77 + EditorGUILayout.Space(); 78 + 79 + if (script.Action is ComparerBase) 80 + { 81 + DrawCompareToType(script.Action as ComparerBase); 82 + } 83 + } 84 + } 85 + 86 + private void DrawOptionsForAfterPeriodOfTime(AssertionComponent script) 87 + { 88 + EditorGUILayout.Space(); 89 + script.checkAfterTime = EditorGUILayout.FloatField(m_GUICheckAfterTimeGuiContent, 90 + script.checkAfterTime); 91 + if (script.checkAfterTime < 0) 92 + script.checkAfterTime = 0; 93 + script.repeatCheckTime = EditorGUILayout.Toggle(m_GUIRepeatCheckTimeGuiContent, 94 + script.repeatCheckTime); 95 + if (script.repeatCheckTime) 96 + { 97 + script.repeatEveryTime = EditorGUILayout.FloatField(m_GUIRepeatEveryTimeGuiContent, 98 + script.repeatEveryTime); 99 + if (script.repeatEveryTime < 0) 100 + script.repeatEveryTime = 0; 101 + } 102 + } 103 + 104 + private void DrawOptionsForOnUpdate(AssertionComponent script) 105 + { 106 + EditorGUILayout.Space(); 107 + script.checkAfterFrames = EditorGUILayout.IntField(m_GUICheckAfterFramesGuiContent, 108 + script.checkAfterFrames); 109 + if (script.checkAfterFrames < 1) 110 + script.checkAfterFrames = 1; 111 + script.repeatCheckFrame = EditorGUILayout.Toggle(m_GUIRepeatCheckFrameGuiContent, 112 + script.repeatCheckFrame); 113 + if (script.repeatCheckFrame) 114 + { 115 + script.repeatEveryFrame = EditorGUILayout.IntField(m_GUIRepeatEveryTimeGuiContent, 116 + script.repeatEveryFrame); 117 + if (script.repeatEveryFrame < 1) 118 + script.repeatEveryFrame = 1; 119 + } 120 + } 121 + 122 + private void DrawCompareToType(ComparerBase comparer) 123 + { 124 + comparer.compareToType = (ComparerBase.CompareToType)EditorGUILayout.EnumPopup("Compare to type", 125 + comparer.compareToType, 126 + EditorStyles.popup); 127 + 128 + if (comparer.compareToType == ComparerBase.CompareToType.CompareToConstantValue) 129 + { 130 + try 131 + { 132 + DrawConstCompareField(comparer); 133 + } 134 + catch (NotImplementedException) 135 + { 136 + Debug.LogWarning("This comparer can't compare to static value"); 137 + comparer.compareToType = ComparerBase.CompareToType.CompareToObject; 138 + } 139 + } 140 + else if (comparer.compareToType == ComparerBase.CompareToType.CompareToObject) 141 + { 142 + DrawObjectCompareField(comparer); 143 + } 144 + } 145 + 146 + private void DrawObjectCompareField(ComparerBase comparer) 147 + { 148 + m_OtherPathSelector.Draw(comparer.other, comparer, 149 + comparer.otherPropertyPath, comparer.GetAccepatbleTypesForB(), 150 + go => 151 + { 152 + comparer.other = go; 153 + AssertionExplorerWindow.Reload(); 154 + }, 155 + s => 156 + { 157 + comparer.otherPropertyPath = s; 158 + AssertionExplorerWindow.Reload(); 159 + } 160 + ); 161 + } 162 + 163 + private void DrawConstCompareField(ComparerBase comparer) 164 + { 165 + if (comparer.ConstValue == null) 166 + { 167 + comparer.ConstValue = comparer.GetDefaultConstValue(); 168 + } 169 + 170 + var so = new SerializedObject(comparer); 171 + var sp = so.FindProperty("constantValueGeneric"); 172 + if (sp != null) 173 + { 174 + EditorGUILayout.PropertyField(sp, new GUIContent("Constant"), true); 175 + so.ApplyModifiedProperties(); 176 + } 177 + } 178 + 179 + private bool DrawComparerSelection(AssertionComponent script) 180 + { 181 + if(allComparersList == null) 182 + { 183 + allComparersList = new List<Type>(); 184 + var allAssemblies = AppDomain.CurrentDomain.GetAssemblies(); 185 + foreach (var assembly in allAssemblies) 186 + { 187 + var types = assembly.GetTypes(); 188 + allComparersList.AddRange(types.Where(type => type.IsSubclassOf(typeof(ActionBase)) && !type.IsAbstract)); 189 + } 190 + } 191 + var allComparers = allComparersList.ToArray(); 192 + 193 + if (script.Action == null) 194 + script.Action = (ActionBase)CreateInstance(allComparers.First()); 195 + 196 + m_ComparerDropDown.Draw(script.Action.GetType(), allComparers, 197 + type => 198 + { 199 + if (script.Action == null || script.Action.GetType().Name != type.Name) 200 + { 201 + script.Action = (ActionBase)CreateInstance(type); 202 + AssertionExplorerWindow.Reload(); 203 + } 204 + }); 205 + 206 + return script.Action != null; 207 + } 208 + 209 + private void DrawCustomFields(AssertionComponent script) 210 + { 211 + foreach (var prop in script.Action.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) 212 + { 213 + var so = new SerializedObject(script.Action); 214 + var sp = so.FindProperty(prop.Name); 215 + if (sp != null) 216 + { 217 + EditorGUILayout.PropertyField(sp, true); 218 + so.ApplyModifiedProperties(); 219 + } 220 + } 221 + } 222 + } 223 + }
+8
Assets/UnityTestTools/Assertions/Editor/AssertionComponentEditor.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: fd1cabf2c45d0a8489635607a6048621 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+194
Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEditor; 5 + using UnityEngine; 6 + 7 + #if UNITY_METRO 8 + #warning Assertion component is not supported on Windows Store apps 9 + #endif 10 + 11 + namespace UnityTest 12 + { 13 + [Serializable] 14 + public class AssertionExplorerWindow : EditorWindow 15 + { 16 + private List<AssertionComponent> m_AllAssertions = new List<AssertionComponent>(); 17 + [SerializeField] 18 + private string m_FilterText = ""; 19 + [SerializeField] 20 + private FilterType m_FilterType; 21 + [SerializeField] 22 + private List<string> m_FoldMarkers = new List<string>(); 23 + [SerializeField] 24 + private GroupByType m_GroupBy; 25 + [SerializeField] 26 + private Vector2 m_ScrollPosition = Vector2.zero; 27 + private DateTime m_NextReload = DateTime.Now; 28 + [SerializeField] 29 + private static bool s_ShouldReload; 30 + [SerializeField] 31 + private ShowType m_ShowType; 32 + 33 + public AssertionExplorerWindow() 34 + { 35 + titleContent = new GUIContent("Assertion Explorer"); 36 + } 37 + 38 + public void OnDidOpenScene() 39 + { 40 + ReloadAssertionList(); 41 + } 42 + 43 + public void OnFocus() 44 + { 45 + ReloadAssertionList(); 46 + } 47 + 48 + private void ReloadAssertionList() 49 + { 50 + m_NextReload = DateTime.Now.AddSeconds(1); 51 + s_ShouldReload = true; 52 + } 53 + 54 + public void OnHierarchyChange() 55 + { 56 + ReloadAssertionList(); 57 + } 58 + 59 + public void OnInspectorUpdate() 60 + { 61 + if (s_ShouldReload && m_NextReload < DateTime.Now) 62 + { 63 + s_ShouldReload = false; 64 + m_AllAssertions = new List<AssertionComponent>((AssertionComponent[])Resources.FindObjectsOfTypeAll(typeof(AssertionComponent))); 65 + Repaint(); 66 + } 67 + } 68 + 69 + public void OnGUI() 70 + { 71 + DrawMenuPanel(); 72 + 73 + m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition); 74 + if (m_AllAssertions != null) 75 + GetResultRendere().Render(FilterResults(m_AllAssertions, m_FilterText.ToLower()), m_FoldMarkers); 76 + EditorGUILayout.EndScrollView(); 77 + } 78 + 79 + private IEnumerable<AssertionComponent> FilterResults(List<AssertionComponent> assertionComponents, string text) 80 + { 81 + if (m_ShowType == ShowType.ShowDisabled) 82 + assertionComponents = assertionComponents.Where(c => !c.enabled).ToList(); 83 + else if (m_ShowType == ShowType.ShowEnabled) 84 + assertionComponents = assertionComponents.Where(c => c.enabled).ToList(); 85 + 86 + if (string.IsNullOrEmpty(text)) 87 + return assertionComponents; 88 + 89 + switch (m_FilterType) 90 + { 91 + case FilterType.ComparerName: 92 + return assertionComponents.Where(c => c.Action.GetType().Name.ToLower().Contains(text)); 93 + case FilterType.AttachedGameObject: 94 + return assertionComponents.Where(c => c.gameObject.name.ToLower().Contains(text)); 95 + case FilterType.FirstComparedGameObjectPath: 96 + return assertionComponents.Where(c => c.Action.thisPropertyPath.ToLower().Contains(text)); 97 + case FilterType.FirstComparedGameObject: 98 + return assertionComponents.Where(c => c.Action.go != null 99 + && c.Action.go.name.ToLower().Contains(text)); 100 + case FilterType.SecondComparedGameObjectPath: 101 + return assertionComponents.Where(c => 102 + c.Action is ComparerBase 103 + && (c.Action as ComparerBase).otherPropertyPath.ToLower().Contains(text)); 104 + case FilterType.SecondComparedGameObject: 105 + return assertionComponents.Where(c => 106 + c.Action is ComparerBase 107 + && (c.Action as ComparerBase).other != null 108 + && (c.Action as ComparerBase).other.name.ToLower().Contains(text)); 109 + default: 110 + return assertionComponents; 111 + } 112 + } 113 + 114 + private readonly IListRenderer m_GroupByComparerRenderer = new GroupByComparerRenderer(); 115 + private readonly IListRenderer m_GroupByExecutionMethodRenderer = new GroupByExecutionMethodRenderer(); 116 + private readonly IListRenderer m_GroupByGoRenderer = new GroupByGoRenderer(); 117 + private readonly IListRenderer m_GroupByTestsRenderer = new GroupByTestsRenderer(); 118 + private readonly IListRenderer m_GroupByNothingRenderer = new GroupByNothingRenderer(); 119 + 120 + private IListRenderer GetResultRendere() 121 + { 122 + switch (m_GroupBy) 123 + { 124 + case GroupByType.Comparer: 125 + return m_GroupByComparerRenderer; 126 + case GroupByType.ExecutionMethod: 127 + return m_GroupByExecutionMethodRenderer; 128 + case GroupByType.GameObjects: 129 + return m_GroupByGoRenderer; 130 + case GroupByType.Tests: 131 + return m_GroupByTestsRenderer; 132 + default: 133 + return m_GroupByNothingRenderer; 134 + } 135 + } 136 + 137 + private void DrawMenuPanel() 138 + { 139 + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); 140 + EditorGUILayout.LabelField("Group by:", Styles.toolbarLabel, GUILayout.MaxWidth(60)); 141 + m_GroupBy = (GroupByType)EditorGUILayout.EnumPopup(m_GroupBy, EditorStyles.toolbarPopup, GUILayout.MaxWidth(150)); 142 + 143 + GUILayout.FlexibleSpace(); 144 + 145 + m_ShowType = (ShowType)EditorGUILayout.EnumPopup(m_ShowType, EditorStyles.toolbarPopup, GUILayout.MaxWidth(100)); 146 + 147 + EditorGUILayout.LabelField("Filter by:", Styles.toolbarLabel, GUILayout.MaxWidth(50)); 148 + m_FilterType = (FilterType)EditorGUILayout.EnumPopup(m_FilterType, EditorStyles.toolbarPopup, GUILayout.MaxWidth(100)); 149 + m_FilterText = GUILayout.TextField(m_FilterText, "ToolbarSeachTextField", GUILayout.MaxWidth(100)); 150 + if (GUILayout.Button(GUIContent.none, string.IsNullOrEmpty(m_FilterText) ? "ToolbarSeachCancelButtonEmpty" : "ToolbarSeachCancelButton", GUILayout.ExpandWidth(false))) 151 + m_FilterText = ""; 152 + EditorGUILayout.EndHorizontal(); 153 + } 154 + 155 + [MenuItem("Unity Test Tools/Assertion Explorer")] 156 + public static AssertionExplorerWindow ShowWindow() 157 + { 158 + var w = GetWindow(typeof(AssertionExplorerWindow)); 159 + w.Show(); 160 + return w as AssertionExplorerWindow; 161 + } 162 + 163 + private enum FilterType 164 + { 165 + ComparerName, 166 + FirstComparedGameObject, 167 + FirstComparedGameObjectPath, 168 + SecondComparedGameObject, 169 + SecondComparedGameObjectPath, 170 + AttachedGameObject 171 + } 172 + 173 + private enum ShowType 174 + { 175 + ShowAll, 176 + ShowEnabled, 177 + ShowDisabled 178 + } 179 + 180 + private enum GroupByType 181 + { 182 + Nothing, 183 + Comparer, 184 + GameObjects, 185 + ExecutionMethod, 186 + Tests 187 + } 188 + 189 + public static void Reload() 190 + { 191 + s_ShouldReload = true; 192 + } 193 + } 194 + }
+8
Assets/UnityTestTools/Assertions/Editor/AssertionExplorerWindow.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 1a1e855053e7e2f46ace1dc93f2036f2 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+251
Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEditor; 5 + using UnityEngine; 6 + 7 + namespace UnityTest 8 + { 9 + public interface IListRenderer 10 + { 11 + void Render(IEnumerable<AssertionComponent> allAssertions, List<string> foldMarkers); 12 + } 13 + 14 + public abstract class AssertionListRenderer<T> : IListRenderer 15 + { 16 + private static class Styles 17 + { 18 + public static readonly GUIStyle redLabel; 19 + static Styles() 20 + { 21 + redLabel = new GUIStyle(EditorStyles.label); 22 + redLabel.normal.textColor = Color.red; 23 + } 24 + } 25 + 26 + public void Render(IEnumerable<AssertionComponent> allAssertions, List<string> foldMarkers) 27 + { 28 + foreach (var grouping in GroupResult(allAssertions)) 29 + { 30 + var key = GetStringKey(grouping.Key); 31 + bool isFolded = foldMarkers.Contains(key); 32 + if (key != "") 33 + { 34 + EditorGUILayout.BeginHorizontal(); 35 + 36 + EditorGUI.BeginChangeCheck(); 37 + isFolded = PrintFoldout(isFolded, 38 + grouping.Key); 39 + if (EditorGUI.EndChangeCheck()) 40 + { 41 + if (isFolded) 42 + foldMarkers.Add(key); 43 + else 44 + foldMarkers.Remove(key); 45 + } 46 + EditorGUILayout.EndHorizontal(); 47 + if (isFolded) 48 + continue; 49 + } 50 + foreach (var assertionComponent in grouping) 51 + { 52 + EditorGUILayout.BeginVertical(); 53 + EditorGUILayout.BeginHorizontal(); 54 + 55 + if (key != "") 56 + GUILayout.Space(15); 57 + 58 + var assertionKey = assertionComponent.GetHashCode().ToString(); 59 + bool isDetailsFolded = foldMarkers.Contains(assertionKey); 60 + 61 + EditorGUI.BeginChangeCheck(); 62 + if (GUILayout.Button("", 63 + EditorStyles.foldout, 64 + GUILayout.Width(15))) 65 + { 66 + isDetailsFolded = !isDetailsFolded; 67 + } 68 + if (EditorGUI.EndChangeCheck()) 69 + { 70 + if (isDetailsFolded) 71 + foldMarkers.Add(assertionKey); 72 + else 73 + foldMarkers.Remove(assertionKey); 74 + } 75 + PrintFoldedAssertionLine(assertionComponent); 76 + EditorGUILayout.EndHorizontal(); 77 + 78 + if (isDetailsFolded) 79 + { 80 + EditorGUILayout.BeginHorizontal(); 81 + if (key != "") 82 + GUILayout.Space(15); 83 + PrintAssertionLineDetails(assertionComponent); 84 + EditorGUILayout.EndHorizontal(); 85 + } 86 + GUILayout.Box("", new[] {GUILayout.ExpandWidth(true), GUILayout.Height(1)}); 87 + 88 + EditorGUILayout.EndVertical(); 89 + } 90 + } 91 + } 92 + 93 + protected abstract IEnumerable<IGrouping<T, AssertionComponent>> GroupResult(IEnumerable<AssertionComponent> assertionComponents); 94 + 95 + protected virtual string GetStringKey(T key) 96 + { 97 + return key.GetHashCode().ToString(); 98 + } 99 + 100 + protected virtual bool PrintFoldout(bool isFolded, T key) 101 + { 102 + var content = new GUIContent(GetFoldoutDisplayName(key)); 103 + var size = EditorStyles.foldout.CalcSize(content); 104 + 105 + var rect = GUILayoutUtility.GetRect(content, 106 + EditorStyles.foldout, 107 + GUILayout.MaxWidth(size.x)); 108 + var res = EditorGUI.Foldout(rect, 109 + !isFolded, 110 + content, 111 + true); 112 + 113 + return !res; 114 + } 115 + 116 + protected virtual string GetFoldoutDisplayName(T key) 117 + { 118 + return key.ToString(); 119 + } 120 + 121 + protected virtual void PrintFoldedAssertionLine(AssertionComponent assertionComponent) 122 + { 123 + EditorGUILayout.BeginHorizontal(); 124 + 125 + EditorGUILayout.BeginVertical(GUILayout.MaxWidth(300)); 126 + EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(300)); 127 + PrintPath(assertionComponent.Action.go, 128 + assertionComponent.Action.thisPropertyPath); 129 + EditorGUILayout.EndHorizontal(); 130 + EditorGUILayout.EndVertical(); 131 + 132 + EditorGUILayout.BeginVertical(GUILayout.MaxWidth(250)); 133 + var labelStr = assertionComponent.Action.GetType().Name; 134 + var labelStr2 = assertionComponent.Action.GetConfigurationDescription(); 135 + if (labelStr2 != "") 136 + labelStr += "( " + labelStr2 + ")"; 137 + EditorGUILayout.LabelField(labelStr); 138 + EditorGUILayout.EndVertical(); 139 + 140 + if (assertionComponent.Action is ComparerBase) 141 + { 142 + var comparer = assertionComponent.Action as ComparerBase; 143 + 144 + var otherStrVal = "(no value selected)"; 145 + EditorGUILayout.BeginVertical(); 146 + EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(300)); 147 + switch (comparer.compareToType) 148 + { 149 + case ComparerBase.CompareToType.CompareToObject: 150 + if (comparer.other != null) 151 + { 152 + PrintPath(comparer.other, 153 + comparer.otherPropertyPath); 154 + } 155 + else 156 + { 157 + EditorGUILayout.LabelField(otherStrVal, 158 + Styles.redLabel); 159 + } 160 + break; 161 + case ComparerBase.CompareToType.CompareToConstantValue: 162 + otherStrVal = comparer.ConstValue.ToString(); 163 + EditorGUILayout.LabelField(otherStrVal); 164 + break; 165 + case ComparerBase.CompareToType.CompareToNull: 166 + otherStrVal = "null"; 167 + EditorGUILayout.LabelField(otherStrVal); 168 + break; 169 + } 170 + EditorGUILayout.EndHorizontal(); 171 + EditorGUILayout.EndVertical(); 172 + } 173 + else 174 + { 175 + EditorGUILayout.LabelField(""); 176 + } 177 + EditorGUILayout.EndHorizontal(); 178 + EditorGUILayout.Space(); 179 + } 180 + 181 + protected virtual void PrintAssertionLineDetails(AssertionComponent assertionComponent) 182 + { 183 + EditorGUILayout.BeginHorizontal(); 184 + 185 + 186 + EditorGUILayout.BeginVertical(GUILayout.MaxWidth(320)); 187 + EditorGUILayout.BeginHorizontal(); 188 + EditorGUILayout.LabelField("Attached to", 189 + GUILayout.Width(70)); 190 + var sss = EditorStyles.objectField.CalcSize(new GUIContent(assertionComponent.gameObject.name)); 191 + EditorGUILayout.ObjectField(assertionComponent.gameObject, 192 + typeof(GameObject), 193 + true, 194 + GUILayout.Width(sss.x)); 195 + EditorGUILayout.EndHorizontal(); 196 + EditorGUILayout.EndVertical(); 197 + 198 + 199 + EditorGUILayout.BeginVertical(GUILayout.MaxWidth(250)); 200 + EditorGUILayout.EnumMaskField(assertionComponent.checkMethods, 201 + EditorStyles.popup, 202 + GUILayout.MaxWidth(150)); 203 + EditorGUILayout.EndVertical(); 204 + 205 + 206 + EditorGUILayout.BeginVertical(); 207 + EditorGUILayout.BeginHorizontal(); 208 + EditorGUILayout.LabelField("Disabled", 209 + GUILayout.Width(55)); 210 + assertionComponent.enabled = !EditorGUILayout.Toggle(!assertionComponent.enabled, 211 + GUILayout.Width(15)); 212 + EditorGUILayout.EndHorizontal(); 213 + EditorGUILayout.EndVertical(); 214 + 215 + EditorGUILayout.EndHorizontal(); 216 + } 217 + 218 + private void PrintPath(GameObject go, string propertyPath) 219 + { 220 + string contentString = ""; 221 + GUIStyle styleThisPath = EditorStyles.label; 222 + if (go != null) 223 + { 224 + var sss = EditorStyles.objectField.CalcSize(new GUIContent(go.name)); 225 + EditorGUILayout.ObjectField( 226 + go, 227 + typeof(GameObject), 228 + true, 229 + GUILayout.Width(sss.x)); 230 + 231 + if (!string.IsNullOrEmpty(propertyPath)) 232 + contentString = "." + propertyPath; 233 + } 234 + else 235 + { 236 + contentString = "(no value selected)"; 237 + styleThisPath = Styles.redLabel; 238 + } 239 + 240 + var content = new GUIContent(contentString, 241 + contentString); 242 + var rect = GUILayoutUtility.GetRect(content, 243 + EditorStyles.label, 244 + GUILayout.MaxWidth(200)); 245 + 246 + EditorGUI.LabelField(rect, 247 + content, 248 + styleThisPath); 249 + } 250 + } 251 + }
+8
Assets/UnityTestTools/Assertions/Editor/AssertionListRenderer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: d83c02fb0f220344da42a8213ed36cb5 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+25
Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEditor.Callbacks; 4 + using UnityEngine; 5 + using UnityTest; 6 + using Object = UnityEngine.Object; 7 + 8 + public class AssertionStripper 9 + { 10 + [PostProcessScene] 11 + public static void OnPostprocessScene() 12 + { 13 + if (Debug.isDebugBuild) return; 14 + RemoveAssertionsFromGameObjects(); 15 + } 16 + 17 + private static void RemoveAssertionsFromGameObjects() 18 + { 19 + var allAssertions = Resources.FindObjectsOfTypeAll(typeof(AssertionComponent)) as AssertionComponent[]; 20 + foreach (var assertion in allAssertions) 21 + { 22 + Object.DestroyImmediate(assertion); 23 + } 24 + } 25 + }
+8
Assets/UnityTestTools/Assertions/Editor/AssertionStripper.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 95c9cd9570a6fba4198b6e4f15e11e5e 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+78
Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEditor; 4 + using UnityEngine; 5 + 6 + namespace UnityTest 7 + { 8 + [Serializable] 9 + internal class DropDownControl<T> 10 + { 11 + private readonly GUILayoutOption[] m_ButtonLayoutOptions = { GUILayout.ExpandWidth(true) }; 12 + public Func<T, string> convertForButtonLabel = s => s.ToString(); 13 + public Func<T, string> convertForGUIContent = s => s.ToString(); 14 + public Func<T[], bool> ignoreConvertForGUIContent = t => t.Length <= 40; 15 + public Action<T> printContextMenu = null; 16 + public string tooltip = ""; 17 + 18 + private object m_SelectedValue; 19 + 20 + 21 + public void Draw(T selected, T[] options, Action<T> onValueSelected) 22 + { 23 + Draw(null, 24 + selected, 25 + options, 26 + onValueSelected); 27 + } 28 + 29 + public void Draw(string label, T selected, T[] options, Action<T> onValueSelected) 30 + { 31 + Draw(label, selected, () => options, onValueSelected); 32 + } 33 + 34 + public void Draw(string label, T selected, Func<T[]> loadOptions, Action<T> onValueSelected) 35 + { 36 + if (!string.IsNullOrEmpty(label)) 37 + EditorGUILayout.BeginHorizontal(); 38 + var guiContent = new GUIContent(label); 39 + var labelSize = EditorStyles.label.CalcSize(guiContent); 40 + 41 + if (!string.IsNullOrEmpty(label)) 42 + GUILayout.Label(label, EditorStyles.label, GUILayout.Width(labelSize.x)); 43 + 44 + if (GUILayout.Button(new GUIContent(convertForButtonLabel(selected), tooltip), 45 + EditorStyles.popup, m_ButtonLayoutOptions)) 46 + { 47 + if (Event.current.button == 0) 48 + { 49 + PrintMenu(loadOptions()); 50 + } 51 + else if (printContextMenu != null && Event.current.button == 1) 52 + printContextMenu(selected); 53 + } 54 + 55 + if (m_SelectedValue != null) 56 + { 57 + onValueSelected((T)m_SelectedValue); 58 + m_SelectedValue = null; 59 + } 60 + if (!string.IsNullOrEmpty(label)) 61 + EditorGUILayout.EndHorizontal(); 62 + } 63 + 64 + public void PrintMenu(T[] options) 65 + { 66 + var menu = new GenericMenu(); 67 + foreach (var s in options) 68 + { 69 + var localS = s; 70 + menu.AddItem(new GUIContent((ignoreConvertForGUIContent(options) ? localS.ToString() : convertForGUIContent(localS))), 71 + false, 72 + () => { m_SelectedValue = localS; } 73 + ); 74 + } 75 + menu.ShowAsContext(); 76 + } 77 + } 78 + }
+8
Assets/UnityTestTools/Assertions/Editor/DropDownControl.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 83ec3ed09f8f2f34ea7483e055f6d76d 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+20
Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEngine; 5 + 6 + namespace UnityTest 7 + { 8 + public class GroupByComparerRenderer : AssertionListRenderer<Type> 9 + { 10 + protected override IEnumerable<IGrouping<Type, AssertionComponent>> GroupResult(IEnumerable<AssertionComponent> assertionComponents) 11 + { 12 + return assertionComponents.GroupBy(c => c.Action.GetType()); 13 + } 14 + 15 + protected override string GetStringKey(Type key) 16 + { 17 + return key.Name; 18 + } 19 + } 20 + }
+8
Assets/UnityTestTools/Assertions/Editor/GroupByComparerRenderer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: efab536803bd0154a8a7dc78e8767ad9 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+31
Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEngine; 5 + 6 + namespace UnityTest 7 + { 8 + public class GroupByExecutionMethodRenderer : AssertionListRenderer<CheckMethod> 9 + { 10 + protected override IEnumerable<IGrouping<CheckMethod, AssertionComponent>> GroupResult(IEnumerable<AssertionComponent> assertionComponents) 11 + { 12 + var enumVals = Enum.GetValues(typeof(CheckMethod)).Cast<CheckMethod>(); 13 + var pairs = new List<CheckFunctionAssertionPair>(); 14 + 15 + foreach (var checkMethod in enumVals) 16 + { 17 + var components = assertionComponents.Where(c => (c.checkMethods & checkMethod) == checkMethod); 18 + var componentPairs = components.Select(a => new CheckFunctionAssertionPair {checkMethod = checkMethod, assertionComponent = a}); 19 + pairs.AddRange(componentPairs); 20 + } 21 + return pairs.GroupBy(pair => pair.checkMethod, 22 + pair => pair.assertionComponent); 23 + } 24 + 25 + private class CheckFunctionAssertionPair 26 + { 27 + public AssertionComponent assertionComponent; 28 + public CheckMethod checkMethod; 29 + } 30 + } 31 + }
+8
Assets/UnityTestTools/Assertions/Editor/GroupByExecutionMethodRenderer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 97340abf816b1424fa835a4f26bbdc78 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+34
Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEditor; 5 + using UnityEngine; 6 + 7 + namespace UnityTest 8 + { 9 + public class GroupByGoRenderer : AssertionListRenderer<GameObject> 10 + { 11 + protected override IEnumerable<IGrouping<GameObject, AssertionComponent>> GroupResult(IEnumerable<AssertionComponent> assertionComponents) 12 + { 13 + return assertionComponents.GroupBy(c => c.gameObject); 14 + } 15 + 16 + protected override bool PrintFoldout(bool isFolded, GameObject key) 17 + { 18 + isFolded = base.PrintFoldout(isFolded, 19 + key); 20 + 21 + EditorGUILayout.ObjectField(key, 22 + typeof(GameObject), 23 + true, 24 + GUILayout.ExpandWidth(false)); 25 + 26 + return isFolded; 27 + } 28 + 29 + protected override string GetFoldoutDisplayName(GameObject key) 30 + { 31 + return key.name; 32 + } 33 + } 34 + }
+8
Assets/UnityTestTools/Assertions/Editor/GroupByGORenderer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: cb824de9146b42343a985aaf63beffd1 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+20
Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEngine; 5 + 6 + namespace UnityTest 7 + { 8 + public class GroupByNothingRenderer : AssertionListRenderer<string> 9 + { 10 + protected override IEnumerable<IGrouping<string, AssertionComponent>> GroupResult(IEnumerable<AssertionComponent> assertionComponents) 11 + { 12 + return assertionComponents.GroupBy(c => ""); 13 + } 14 + 15 + protected override string GetStringKey(string key) 16 + { 17 + return ""; 18 + } 19 + } 20 + }
+8
Assets/UnityTestTools/Assertions/Editor/GroupByNothingRenderer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 33bf96aa461ea1d478bb757c52f51c95 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+29
Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEngine; 5 + 6 + namespace UnityTest 7 + { 8 + public class GroupByTestsRenderer : AssertionListRenderer<GameObject> 9 + { 10 + protected override IEnumerable<IGrouping<GameObject, AssertionComponent>> GroupResult(IEnumerable<AssertionComponent> assertionComponents) 11 + { 12 + return assertionComponents.GroupBy(c => 13 + { 14 + var temp = c.transform; 15 + while (temp != null) 16 + { 17 + if (temp.GetComponent("TestComponent") != null) return c.gameObject; 18 + temp = temp.parent.transform; 19 + } 20 + return null; 21 + }); 22 + } 23 + 24 + protected override string GetFoldoutDisplayName(GameObject key) 25 + { 26 + return key.name; 27 + } 28 + } 29 + }
+8
Assets/UnityTestTools/Assertions/Editor/GroupByTestsRenderer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 5e577f31e55208b4d8a1774b958e6ed5 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+207
Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using System.Reflection; 5 + using UnityEditor; 6 + using UnityEngine; 7 + 8 + namespace UnityTest 9 + { 10 + public class PropertyPathSelector 11 + { 12 + private readonly DropDownControl<string> m_ThisDropDown = new DropDownControl<string>(); 13 + private readonly Func<string, string> m_ReplaceDotWithSlashAndAddGoGroup = s => s.Replace('.', '/'); 14 + 15 + private readonly string m_Name; 16 + private bool m_FocusBackToEdit; 17 + private SelectedPathError m_Error; 18 + 19 + public PropertyPathSelector(string name) 20 + { 21 + m_Name = name; 22 + m_ThisDropDown.convertForGUIContent = m_ReplaceDotWithSlashAndAddGoGroup; 23 + m_ThisDropDown.tooltip = "Select the path to the value you want to use for comparison."; 24 + } 25 + 26 + public void Draw(GameObject go, ActionBase comparer, string propertPath, Type[] accepatbleTypes, Action<GameObject> onSelectedGo, Action<string> onSelectedPath) 27 + { 28 + var newGo = (GameObject)EditorGUILayout.ObjectField(m_Name, go, typeof(GameObject), true); 29 + if (newGo != go) 30 + onSelectedGo(newGo); 31 + 32 + if (go != null) 33 + { 34 + var newPath = DrawListOfMethods(go, comparer, propertPath, accepatbleTypes, m_ThisDropDown); 35 + 36 + if (newPath != propertPath) 37 + onSelectedPath(newPath); 38 + } 39 + } 40 + 41 + private string DrawListOfMethods(GameObject go, ActionBase comparer, string propertPath, Type[] accepatbleTypes, DropDownControl<string> dropDown) 42 + { 43 + string result = propertPath; 44 + if (accepatbleTypes == null) 45 + { 46 + result = DrawManualPropertyEditField(go, propertPath, accepatbleTypes, dropDown); 47 + } 48 + else 49 + { 50 + bool isPropertyOrFieldFound = true; 51 + if (string.IsNullOrEmpty(result)) 52 + { 53 + var options = GetFieldsAndProperties(go, comparer, result, accepatbleTypes); 54 + isPropertyOrFieldFound = options.Any(); 55 + if (isPropertyOrFieldFound) 56 + { 57 + result = options.First(); 58 + } 59 + } 60 + 61 + if (isPropertyOrFieldFound) 62 + { 63 + dropDown.Draw(go.name + '.', result, 64 + () => 65 + { 66 + try 67 + { 68 + var options = GetFieldsAndProperties(go, comparer, result, accepatbleTypes); 69 + return options.ToArray(); 70 + } 71 + catch (Exception) 72 + { 73 + Debug.LogWarning("An exception was thrown while resolving a property list. Resetting property path."); 74 + result = ""; 75 + return new string[0]; 76 + } 77 + }, s => result = s); 78 + } 79 + else 80 + { 81 + result = DrawManualPropertyEditField(go, propertPath, accepatbleTypes, dropDown); 82 + } 83 + } 84 + return result; 85 + } 86 + 87 + private static List<string> GetFieldsAndProperties(GameObject go, ActionBase comparer, string extendPath, Type[] accepatbleTypes) 88 + { 89 + var propertyResolver = new PropertyResolver {AllowedTypes = accepatbleTypes, ExcludedFieldNames = comparer.GetExcludedFieldNames()}; 90 + var options = propertyResolver.GetFieldsAndPropertiesFromGameObject(go, comparer.GetDepthOfSearch(), extendPath).ToList(); 91 + options.Sort((x, y) => 92 + { 93 + if (char.IsLower(x[0])) 94 + return -1; 95 + if (char.IsLower(y[0])) 96 + return 1; 97 + return x.CompareTo(y); 98 + }); 99 + return options; 100 + } 101 + 102 + private string DrawManualPropertyEditField(GameObject go, string propertPath, Type[] acceptableTypes, DropDownControl<string> dropDown) 103 + { 104 + var propertyResolver = new PropertyResolver { AllowedTypes = acceptableTypes }; 105 + IList<string> list; 106 + 107 + var loadProps = new Func<string[]>(() => 108 + { 109 + try 110 + { 111 + list = propertyResolver.GetFieldsAndPropertiesUnderPath(go, propertPath); 112 + } 113 + catch (ArgumentException) 114 + { 115 + list = propertyResolver.GetFieldsAndPropertiesUnderPath(go, ""); 116 + } 117 + return list.ToArray(); 118 + }); 119 + 120 + EditorGUILayout.BeginHorizontal(); 121 + 122 + var labelSize = EditorStyles.label.CalcSize(new GUIContent(go.name + '.')); 123 + GUILayout.Label(go.name + (propertPath.Length > 0 ? "." : ""), EditorStyles.label, GUILayout.Width(labelSize.x)); 124 + 125 + string btnName = "hintBtn"; 126 + if (GUI.GetNameOfFocusedControl() == btnName 127 + && Event.current.type == EventType.KeyDown 128 + && Event.current.keyCode == KeyCode.DownArrow) 129 + { 130 + Event.current.Use(); 131 + dropDown.PrintMenu(loadProps()); 132 + GUI.FocusControl(""); 133 + m_FocusBackToEdit = true; 134 + } 135 + 136 + EditorGUI.BeginChangeCheck(); 137 + GUI.SetNextControlName(btnName); 138 + var result = GUILayout.TextField(propertPath, EditorStyles.textField); 139 + if (EditorGUI.EndChangeCheck()) 140 + { 141 + m_Error = DoesPropertyExist(go, result); 142 + } 143 + 144 + if (m_FocusBackToEdit) 145 + { 146 + m_FocusBackToEdit = false; 147 + GUI.FocusControl(btnName); 148 + } 149 + 150 + if (GUILayout.Button("Clear", EditorStyles.miniButton, GUILayout.Width(38))) 151 + { 152 + result = ""; 153 + GUI.FocusControl(null); 154 + m_FocusBackToEdit = true; 155 + m_Error = DoesPropertyExist(go, result); 156 + } 157 + EditorGUILayout.EndHorizontal(); 158 + EditorGUILayout.BeginHorizontal(); 159 + GUILayout.Label("", GUILayout.Width(labelSize.x)); 160 + 161 + dropDown.Draw("", result ?? "", loadProps, s => 162 + { 163 + result = s; 164 + GUI.FocusControl(null); 165 + m_FocusBackToEdit = true; 166 + m_Error = DoesPropertyExist(go, result); 167 + }); 168 + EditorGUILayout.EndHorizontal(); 169 + 170 + switch (m_Error) 171 + { 172 + case SelectedPathError.InvalidPath: 173 + EditorGUILayout.HelpBox("This property does not exist", MessageType.Error); 174 + break; 175 + case SelectedPathError.MissingComponent: 176 + EditorGUILayout.HelpBox("This property or field is not attached or set. It will fail unless it will be attached before the check is perfomed.", MessageType.Warning); 177 + break; 178 + } 179 + 180 + return result; 181 + } 182 + 183 + private SelectedPathError DoesPropertyExist(GameObject go, string propertPath) 184 + { 185 + try 186 + { 187 + object obj; 188 + if (MemberResolver.TryGetValue(go, propertPath, out obj)) 189 + return SelectedPathError.None; 190 + return SelectedPathError.InvalidPath; 191 + } 192 + catch (TargetInvocationException e) 193 + { 194 + if (e.InnerException is MissingComponentException) 195 + return SelectedPathError.MissingComponent; 196 + throw; 197 + } 198 + } 199 + 200 + private enum SelectedPathError 201 + { 202 + None, 203 + MissingComponent, 204 + InvalidPath 205 + } 206 + } 207 + }
+8
Assets/UnityTestTools/Assertions/Editor/PropertyPathSelector.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 6619da1897737044080bdb8bc60eff87 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+188
Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using System.Reflection; 5 + using System.Text.RegularExpressions; 6 + using UnityEngine; 7 + 8 + namespace UnityTest 9 + { 10 + [Serializable] 11 + public class PropertyResolver 12 + { 13 + public string[] ExcludedFieldNames { get; set; } 14 + public Type[] ExcludedTypes { get; set; } 15 + public Type[] AllowedTypes { get; set; } 16 + 17 + public PropertyResolver() 18 + { 19 + ExcludedFieldNames = new string[] { }; 20 + ExcludedTypes = new Type[] { }; 21 + AllowedTypes = new Type[] { }; 22 + } 23 + 24 + public IList<string> GetFieldsAndPropertiesUnderPath(GameObject go, string propertPath) 25 + { 26 + propertPath = propertPath.Trim(); 27 + if (!PropertyPathIsValid(propertPath)) 28 + { 29 + throw new ArgumentException("Incorrect property path: " + propertPath); 30 + } 31 + 32 + var idx = propertPath.LastIndexOf('.'); 33 + 34 + if (idx < 0) 35 + { 36 + var components = GetFieldsAndPropertiesFromGameObject(go, 2, null); 37 + return components; 38 + } 39 + 40 + var propertyToSearch = propertPath; 41 + Type type; 42 + if (MemberResolver.TryGetMemberType(go, propertyToSearch, out type)) 43 + { 44 + idx = propertPath.Length - 1; 45 + } 46 + else 47 + { 48 + propertyToSearch = propertPath.Substring(0, idx); 49 + if (!MemberResolver.TryGetMemberType(go, propertyToSearch, out type)) 50 + { 51 + var components = GetFieldsAndPropertiesFromGameObject(go, 2, null); 52 + return components.Where(s => s.StartsWith(propertPath.Substring(idx + 1))).ToArray(); 53 + } 54 + } 55 + 56 + var resultList = new List<string>(); 57 + var path = ""; 58 + if (propertyToSearch.EndsWith(".")) 59 + propertyToSearch = propertyToSearch.Substring(0, propertyToSearch.Length - 1); 60 + foreach (var c in propertyToSearch) 61 + { 62 + if (c == '.') 63 + resultList.Add(path); 64 + path += c; 65 + } 66 + resultList.Add(path); 67 + foreach (var prop in type.GetProperties().Where(info => info.GetIndexParameters().Length == 0)) 68 + { 69 + if (prop.Name.StartsWith(propertPath.Substring(idx + 1))) 70 + resultList.Add(propertyToSearch + "." + prop.Name); 71 + } 72 + foreach (var prop in type.GetFields()) 73 + { 74 + if (prop.Name.StartsWith(propertPath.Substring(idx + 1))) 75 + resultList.Add(propertyToSearch + "." + prop.Name); 76 + } 77 + return resultList.ToArray(); 78 + } 79 + 80 + internal bool PropertyPathIsValid(string propertPath) 81 + { 82 + if (propertPath.StartsWith(".")) 83 + return false; 84 + if (propertPath.IndexOf("..") >= 0) 85 + return false; 86 + if (Regex.IsMatch(propertPath, @"\s")) 87 + return false; 88 + return true; 89 + } 90 + 91 + public IList<string> GetFieldsAndPropertiesFromGameObject(GameObject gameObject, int depthOfSearch, string extendPath) 92 + { 93 + if (depthOfSearch < 1) throw new ArgumentOutOfRangeException("depthOfSearch has to be greater than 0"); 94 + 95 + var goVals = GetPropertiesAndFieldsFromType(typeof(GameObject), 96 + depthOfSearch - 1).Select(s => "gameObject." + s); 97 + 98 + var result = new List<string>(); 99 + if (AllowedTypes == null || !AllowedTypes.Any() || AllowedTypes.Contains(typeof(GameObject))) 100 + result.Add("gameObject"); 101 + result.AddRange(goVals); 102 + 103 + foreach (var componentType in GetAllComponents(gameObject)) 104 + { 105 + if (AllowedTypes == null || !AllowedTypes.Any() || AllowedTypes.Any(t => t.IsAssignableFrom(componentType))) 106 + result.Add(componentType.Name); 107 + 108 + if (depthOfSearch > 1) 109 + { 110 + var vals = GetPropertiesAndFieldsFromType(componentType, depthOfSearch - 1); 111 + var valsFullName = vals.Select(s => componentType.Name + "." + s); 112 + result.AddRange(valsFullName); 113 + } 114 + } 115 + 116 + if (!string.IsNullOrEmpty(extendPath)) 117 + { 118 + var memberResolver = new MemberResolver(gameObject, extendPath); 119 + var pathType = memberResolver.GetMemberType(); 120 + var vals = GetPropertiesAndFieldsFromType(pathType, depthOfSearch - 1); 121 + var valsFullName = vals.Select(s => extendPath + "." + s); 122 + result.AddRange(valsFullName); 123 + } 124 + 125 + return result; 126 + } 127 + 128 + private string[] GetPropertiesAndFieldsFromType(Type type, int level) 129 + { 130 + level--; 131 + 132 + var result = new List<string>(); 133 + var fields = new List<MemberInfo>(); 134 + fields.AddRange(type.GetFields().Where(f => !Attribute.IsDefined(f, typeof(ObsoleteAttribute))).ToArray()); 135 + fields.AddRange(type.GetProperties().Where(info => info.GetIndexParameters().Length == 0 && !Attribute.IsDefined(info, typeof(ObsoleteAttribute))).ToArray()); 136 + 137 + foreach (var member in fields) 138 + { 139 + var memberType = GetMemberFieldType(member); 140 + var memberTypeName = memberType.Name; 141 + 142 + if (AllowedTypes == null 143 + || !AllowedTypes.Any() 144 + || (AllowedTypes.Any(t => t.IsAssignableFrom(memberType)) && !ExcludedFieldNames.Contains(memberTypeName))) 145 + { 146 + result.Add(member.Name); 147 + } 148 + 149 + if (level > 0 && IsTypeOrNameNotExcluded(memberType, memberTypeName)) 150 + { 151 + var vals = GetPropertiesAndFieldsFromType(memberType, level); 152 + var valsFullName = vals.Select(s => member.Name + "." + s); 153 + result.AddRange(valsFullName); 154 + } 155 + } 156 + return result.ToArray(); 157 + } 158 + 159 + private Type GetMemberFieldType(MemberInfo info) 160 + { 161 + if (info.MemberType == MemberTypes.Property) 162 + return (info as PropertyInfo).PropertyType; 163 + if (info.MemberType == MemberTypes.Field) 164 + return (info as FieldInfo).FieldType; 165 + throw new Exception("Only properties and fields are allowed"); 166 + } 167 + 168 + internal Type[] GetAllComponents(GameObject gameObject) 169 + { 170 + var result = new List<Type>(); 171 + var components = gameObject.GetComponents(typeof(Component)); 172 + foreach (var component in components) 173 + { 174 + var componentType = component.GetType(); 175 + if (IsTypeOrNameNotExcluded(componentType, null)) 176 + { 177 + result.Add(componentType); 178 + } 179 + } 180 + return result.ToArray(); 181 + } 182 + 183 + private bool IsTypeOrNameNotExcluded(Type memberType, string memberTypeName) 184 + { 185 + return !ExcludedTypes.Contains(memberType) && !ExcludedFieldNames.Contains(memberTypeName); 186 + } 187 + } 188 + }
+8
Assets/UnityTestTools/Assertions/Editor/PropertyResolver.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: bbbd193a27920d9478c2a766a7291d72 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+14
Assets/UnityTestTools/Assertions/InvalidPathException.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class InvalidPathException : Exception 8 + { 9 + public InvalidPathException(string path) 10 + : base("Invalid path part " + path) 11 + { 12 + } 13 + } 14 + }
+8
Assets/UnityTestTools/Assertions/InvalidPathException.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 3b85786dfd1aef544bf8bb873d6a4ebb 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+208
Assets/UnityTestTools/Assertions/MemberResolver.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Reflection; 4 + using System.Text.RegularExpressions; 5 + using UnityEngine; 6 + 7 + namespace UnityTest 8 + { 9 + public class MemberResolver 10 + { 11 + private object m_CallingObjectRef; 12 + private MemberInfo[] m_Callstack; 13 + private readonly GameObject m_GameObject; 14 + private readonly string m_Path; 15 + 16 + public MemberResolver(GameObject gameObject, string path) 17 + { 18 + path = path.Trim(); 19 + ValidatePath(path); 20 + 21 + m_GameObject = gameObject; 22 + m_Path = path.Trim(); 23 + } 24 + 25 + public object GetValue(bool useCache) 26 + { 27 + if (useCache && m_CallingObjectRef != null) 28 + { 29 + object val = m_CallingObjectRef; 30 + for (int i = 0; i < m_Callstack.Length; i++) 31 + val = GetValueFromMember(val, m_Callstack[i]); 32 + return val; 33 + } 34 + 35 + object result = GetBaseObject(); 36 + var fullCallStack = GetCallstack(); 37 + 38 + m_CallingObjectRef = result; 39 + var tempCallstack = new List<MemberInfo>(); 40 + for (int i = 0; i < fullCallStack.Length; i++) 41 + { 42 + var member = fullCallStack[i]; 43 + result = GetValueFromMember(result, member); 44 + tempCallstack.Add(member); 45 + if (result == null) return null; 46 + var type = result.GetType(); 47 + 48 + //String is not a value type but we don't want to cache it 49 + if (!IsValueType(type) && type != typeof(System.String)) 50 + { 51 + tempCallstack.Clear(); 52 + m_CallingObjectRef = result; 53 + } 54 + } 55 + m_Callstack = tempCallstack.ToArray(); 56 + return result; 57 + } 58 + 59 + public Type GetMemberType() 60 + { 61 + var callstack = GetCallstack(); 62 + if (callstack.Length == 0) return GetBaseObject().GetType(); 63 + 64 + var member = callstack[callstack.Length - 1]; 65 + if (member is FieldInfo) 66 + return (member as FieldInfo).FieldType; 67 + if (member is MethodInfo) 68 + return (member as MethodInfo).ReturnType; 69 + return null; 70 + } 71 + 72 + #region Static wrappers 73 + public static bool TryGetMemberType(GameObject gameObject, string path, out Type value) 74 + { 75 + try 76 + { 77 + var mr = new MemberResolver(gameObject, path); 78 + value = mr.GetMemberType(); 79 + return true; 80 + } 81 + catch (InvalidPathException) 82 + { 83 + value = null; 84 + return false; 85 + } 86 + } 87 + 88 + public static bool TryGetValue(GameObject gameObject, string path, out object value) 89 + { 90 + try 91 + { 92 + var mr = new MemberResolver(gameObject, path); 93 + value = mr.GetValue(false); 94 + return true; 95 + } 96 + catch (InvalidPathException) 97 + { 98 + value = null; 99 + return false; 100 + } 101 + } 102 + #endregion 103 + 104 + private object GetValueFromMember(object obj, MemberInfo memberInfo) 105 + { 106 + if (memberInfo is FieldInfo) 107 + return (memberInfo as FieldInfo).GetValue(obj); 108 + if (memberInfo is MethodInfo) 109 + return (memberInfo as MethodInfo).Invoke(obj, null); 110 + throw new InvalidPathException(memberInfo.Name); 111 + } 112 + 113 + private object GetBaseObject() 114 + { 115 + if (string.IsNullOrEmpty(m_Path)) return m_GameObject; 116 + var firstElement = m_Path.Split('.')[0]; 117 + var comp = m_GameObject.GetComponent(firstElement); 118 + if (comp != null) 119 + return comp; 120 + return m_GameObject; 121 + } 122 + 123 + private MemberInfo[] GetCallstack() 124 + { 125 + if (m_Path == "") return new MemberInfo[0]; 126 + var propsQueue = new Queue<string>(m_Path.Split('.')); 127 + 128 + Type type = GetBaseObject().GetType(); 129 + if (type != typeof(GameObject)) 130 + propsQueue.Dequeue(); 131 + 132 + PropertyInfo propertyTemp; 133 + FieldInfo fieldTemp; 134 + var list = new List<MemberInfo>(); 135 + while (propsQueue.Count != 0) 136 + { 137 + var nameToFind = propsQueue.Dequeue(); 138 + fieldTemp = GetField(type, nameToFind); 139 + if (fieldTemp != null) 140 + { 141 + type = fieldTemp.FieldType; 142 + list.Add(fieldTemp); 143 + continue; 144 + } 145 + propertyTemp = GetProperty(type, nameToFind); 146 + if (propertyTemp != null) 147 + { 148 + type = propertyTemp.PropertyType; 149 + var getMethod = GetGetMethod(propertyTemp); 150 + list.Add(getMethod); 151 + continue; 152 + } 153 + throw new InvalidPathException(nameToFind); 154 + } 155 + return list.ToArray(); 156 + } 157 + 158 + private void ValidatePath(string path) 159 + { 160 + bool invalid = false; 161 + if (path.StartsWith(".") || path.EndsWith(".")) 162 + invalid = true; 163 + if (path.IndexOf("..") >= 0) 164 + invalid = true; 165 + if (Regex.IsMatch(path, @"\s")) 166 + invalid = true; 167 + 168 + if (invalid) 169 + throw new InvalidPathException(path); 170 + } 171 + 172 + private static bool IsValueType(Type type) 173 + { 174 + #if !UNITY_METRO 175 + return type.IsValueType; 176 + #else 177 + return false; 178 + #endif 179 + } 180 + 181 + private static FieldInfo GetField(Type type, string fieldName) 182 + { 183 + #if !UNITY_METRO 184 + return type.GetField(fieldName); 185 + #else 186 + return null; 187 + #endif 188 + } 189 + 190 + private static PropertyInfo GetProperty(Type type, string propertyName) 191 + { 192 + #if !UNITY_METRO 193 + return type.GetProperty(propertyName); 194 + #else 195 + return null; 196 + #endif 197 + } 198 + 199 + private static MethodInfo GetGetMethod(PropertyInfo propertyInfo) 200 + { 201 + #if !UNITY_METRO 202 + return propertyInfo.GetGetMethod(); 203 + #else 204 + return null; 205 + #endif 206 + } 207 + } 208 + }
+8
Assets/UnityTestTools/Assertions/MemberResolver.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 80df8ef907961e34dbcc7c89b22729b9 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+5
Assets/UnityTestTools/Common.meta
··· 1 + fileFormatVersion: 2 2 + guid: a2caba6436df568499c84c1c607ce766 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+4
Assets/UnityTestTools/Common/Editor.meta
··· 1 + fileFormatVersion: 2 2 + guid: f4ab061d0035ee545a936bdf8f3f8620 3 + DefaultImporter: 4 + userData:
+57
Assets/UnityTestTools/Common/Editor/Icons.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using System.Linq; 5 + using UnityEditor; 6 + using UnityEngine; 7 + 8 + namespace UnityTest 9 + { 10 + public static class Icons 11 + { 12 + const string k_IconsFolderName = "icons"; 13 + private static readonly string k_IconsFolderPath = String.Format("UnityTestTools{0}Common{0}Editor{0}{1}", Path.DirectorySeparatorChar, k_IconsFolderName); 14 + 15 + private static readonly string k_IconsAssetsPath = ""; 16 + 17 + public static readonly Texture2D FailImg; 18 + public static readonly Texture2D IgnoreImg; 19 + public static readonly Texture2D SuccessImg; 20 + public static readonly Texture2D UnknownImg; 21 + public static readonly Texture2D InconclusiveImg; 22 + public static readonly Texture2D StopwatchImg; 23 + 24 + public static readonly GUIContent GUIUnknownImg; 25 + public static readonly GUIContent GUIInconclusiveImg; 26 + public static readonly GUIContent GUIIgnoreImg; 27 + public static readonly GUIContent GUISuccessImg; 28 + public static readonly GUIContent GUIFailImg; 29 + 30 + static Icons() 31 + { 32 + var dirs = Directory.GetDirectories("Assets", k_IconsFolderName, SearchOption.AllDirectories).Where(s => s.EndsWith(k_IconsFolderPath)); 33 + if (dirs.Any()) 34 + k_IconsAssetsPath = dirs.First(); 35 + else 36 + Debug.LogWarning("The UnityTestTools asset folder path is incorrect. If you relocated the tools please change the path accordingly (Icons.cs)."); 37 + 38 + FailImg = LoadTexture("failed.png"); 39 + IgnoreImg = LoadTexture("ignored.png"); 40 + SuccessImg = LoadTexture("passed.png"); 41 + UnknownImg = LoadTexture("normal.png"); 42 + InconclusiveImg = LoadTexture("inconclusive.png"); 43 + StopwatchImg = LoadTexture("stopwatch.png"); 44 + 45 + GUIUnknownImg = new GUIContent(UnknownImg); 46 + GUIInconclusiveImg = new GUIContent(InconclusiveImg); 47 + GUIIgnoreImg = new GUIContent(IgnoreImg); 48 + GUISuccessImg = new GUIContent(SuccessImg); 49 + GUIFailImg = new GUIContent(FailImg); 50 + } 51 + 52 + private static Texture2D LoadTexture(string fileName) 53 + { 54 + return (Texture2D)AssetDatabase.LoadAssetAtPath(k_IconsAssetsPath + Path.DirectorySeparatorChar + fileName, typeof(Texture2D)); 55 + } 56 + } 57 + }
+8
Assets/UnityTestTools/Common/Editor/Icons.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 8571844b0c115b84cbe8b3f67e8dec04 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+39
Assets/UnityTestTools/Common/Editor/ProjectSettingsBase.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using System.Linq; 5 + using UnityEditor; 6 + using UnityEngine; 7 + 8 + namespace UnityTest 9 + { 10 + public abstract class ProjectSettingsBase : ScriptableObject 11 + { 12 + private static readonly string k_SettingsPath = Path.Combine("UnityTestTools", "Common"); 13 + const string k_SettingsFolder = "Settings"; 14 + 15 + public virtual void Save() 16 + { 17 + EditorUtility.SetDirty(this); 18 + } 19 + 20 + public static T Load<T>() where T : ProjectSettingsBase, new () 21 + { 22 + var pathsInProject = Directory.GetDirectories("Assets", "*", SearchOption.AllDirectories) 23 + .Where(s => s.Contains(k_SettingsPath)); 24 + 25 + if (pathsInProject.Count() == 0) Debug.LogError("Can't find settings path: " + k_SettingsPath); 26 + 27 + string pathInProject = Path.Combine(pathsInProject.First(), k_SettingsFolder); 28 + var assetPath = Path.Combine(pathInProject, typeof(T).Name) + ".asset"; 29 + var settings = AssetDatabase.LoadAssetAtPath(assetPath, typeof(T)) as T; 30 + 31 + if (settings != null) return settings; 32 + 33 + settings = CreateInstance<T>(); 34 + Directory.CreateDirectory(pathInProject); 35 + AssetDatabase.CreateAsset(settings, assetPath); 36 + return settings; 37 + } 38 + } 39 + }
+8
Assets/UnityTestTools/Common/Editor/ProjectSettingsBase.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 9ac961be07107124a88dcb81927143d4 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+5
Assets/UnityTestTools/Common/Editor/ResultWriter.meta
··· 1 + fileFormatVersion: 2 2 + guid: 4ffbf5a07740aa5479651bd415f52ebb 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+173
Assets/UnityTestTools/Common/Editor/ResultWriter/ResultSummarizer.cs
··· 1 + // **************************************************************** 2 + // Based on nUnit 2.6.2 (http://www.nunit.org/) 3 + // **************************************************************** 4 + 5 + using System; 6 + using System.Collections.Generic; 7 + using UnityEngine; 8 + 9 + namespace UnityTest 10 + { 11 + /// <summary> 12 + /// Summary description for ResultSummarizer. 13 + /// </summary> 14 + public class ResultSummarizer 15 + { 16 + private int m_ErrorCount; 17 + private int m_FailureCount; 18 + private int m_IgnoreCount; 19 + private int m_InconclusiveCount; 20 + private int m_NotRunnable; 21 + private int m_ResultCount; 22 + private int m_SkipCount; 23 + private int m_SuccessCount; 24 + private int m_TestsRun; 25 + 26 + private TimeSpan m_Duration; 27 + 28 + public ResultSummarizer(IEnumerable<ITestResult> results) 29 + { 30 + foreach (var result in results) 31 + Summarize(result); 32 + } 33 + 34 + public bool Success 35 + { 36 + get { return m_FailureCount == 0; } 37 + } 38 + 39 + /// <summary> 40 + /// Returns the number of test cases for which results 41 + /// have been summarized. Any tests excluded by use of 42 + /// Category or Explicit attributes are not counted. 43 + /// </summary> 44 + public int ResultCount 45 + { 46 + get { return m_ResultCount; } 47 + } 48 + 49 + /// <summary> 50 + /// Returns the number of test cases actually run, which 51 + /// is the same as ResultCount, less any Skipped, Ignored 52 + /// or NonRunnable tests. 53 + /// </summary> 54 + public int TestsRun 55 + { 56 + get { return m_TestsRun; } 57 + } 58 + 59 + /// <summary> 60 + /// Returns the number of tests that passed 61 + /// </summary> 62 + public int Passed 63 + { 64 + get { return m_SuccessCount; } 65 + } 66 + 67 + /// <summary> 68 + /// Returns the number of test cases that had an error. 69 + /// </summary> 70 + public int Errors 71 + { 72 + get { return m_ErrorCount; } 73 + } 74 + 75 + /// <summary> 76 + /// Returns the number of test cases that failed. 77 + /// </summary> 78 + public int Failures 79 + { 80 + get { return m_FailureCount; } 81 + } 82 + 83 + /// <summary> 84 + /// Returns the number of test cases that failed. 85 + /// </summary> 86 + public int Inconclusive 87 + { 88 + get { return m_InconclusiveCount; } 89 + } 90 + 91 + /// <summary> 92 + /// Returns the number of test cases that were not runnable 93 + /// due to errors in the signature of the class or method. 94 + /// Such tests are also counted as Errors. 95 + /// </summary> 96 + public int NotRunnable 97 + { 98 + get { return m_NotRunnable; } 99 + } 100 + 101 + /// <summary> 102 + /// Returns the number of test cases that were skipped. 103 + /// </summary> 104 + public int Skipped 105 + { 106 + get { return m_SkipCount; } 107 + } 108 + 109 + public int Ignored 110 + { 111 + get { return m_IgnoreCount; } 112 + } 113 + 114 + public double Duration 115 + { 116 + get { return m_Duration.TotalSeconds; } 117 + } 118 + 119 + public int TestsNotRun 120 + { 121 + get { return m_SkipCount + m_IgnoreCount + m_NotRunnable; } 122 + } 123 + 124 + public void Summarize(ITestResult result) 125 + { 126 + m_Duration += TimeSpan.FromSeconds(result.Duration); 127 + m_ResultCount++; 128 + 129 + if(!result.Executed) 130 + { 131 + if(result.IsIgnored) 132 + { 133 + m_IgnoreCount++; 134 + return; 135 + } 136 + 137 + m_SkipCount++; 138 + return; 139 + } 140 + 141 + switch (result.ResultState) 142 + { 143 + case TestResultState.Success: 144 + m_SuccessCount++; 145 + m_TestsRun++; 146 + break; 147 + case TestResultState.Failure: 148 + m_FailureCount++; 149 + m_TestsRun++; 150 + break; 151 + case TestResultState.Error: 152 + case TestResultState.Cancelled: 153 + m_ErrorCount++; 154 + m_TestsRun++; 155 + break; 156 + case TestResultState.Inconclusive: 157 + m_InconclusiveCount++; 158 + m_TestsRun++; 159 + break; 160 + case TestResultState.NotRunnable: 161 + m_NotRunnable++; 162 + // errorCount++; 163 + break; 164 + case TestResultState.Ignored: 165 + m_IgnoreCount++; 166 + break; 167 + default: 168 + m_SkipCount++; 169 + break; 170 + } 171 + } 172 + } 173 + }
+8
Assets/UnityTestTools/Common/Editor/ResultWriter/ResultSummarizer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: ce89106be5bd4204388d58510e4e55da 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+62
Assets/UnityTestTools/Common/Editor/ResultWriter/StackTraceFilter.cs
··· 1 + // **************************************************************** 2 + // Based on nUnit 2.6.2 (http://www.nunit.org/) 3 + // **************************************************************** 4 + 5 + using System; 6 + using System.Collections.Generic; 7 + using System.IO; 8 + using UnityEngine; 9 + 10 + namespace UnityTest 11 + { 12 + /// <summary> 13 + /// Summary description for StackTraceFilter. 14 + /// </summary> 15 + public class StackTraceFilter 16 + { 17 + public static string Filter(string stack) 18 + { 19 + if (stack == null) return null; 20 + var sw = new StringWriter(); 21 + var sr = new StringReader(stack); 22 + 23 + try 24 + { 25 + string line; 26 + while ((line = sr.ReadLine()) != null) 27 + { 28 + if (!FilterLine(line)) 29 + sw.WriteLine(line.Trim()); 30 + } 31 + } 32 + catch (Exception) 33 + { 34 + return stack; 35 + } 36 + return sw.ToString(); 37 + } 38 + 39 + static bool FilterLine(string line) 40 + { 41 + string[] patterns = 42 + { 43 + "NUnit.Core.TestCase", 44 + "NUnit.Core.ExpectedExceptionTestCase", 45 + "NUnit.Core.TemplateTestCase", 46 + "NUnit.Core.TestResult", 47 + "NUnit.Core.TestSuite", 48 + "NUnit.Framework.Assertion", 49 + "NUnit.Framework.Assert", 50 + "System.Reflection.MonoMethod" 51 + }; 52 + 53 + for (int i = 0; i < patterns.Length; i++) 54 + { 55 + if (line.IndexOf(patterns[i]) > 0) 56 + return true; 57 + } 58 + 59 + return false; 60 + } 61 + } 62 + }
+8
Assets/UnityTestTools/Common/Editor/ResultWriter/StackTraceFilter.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: fe6b4d68575d4ba44b1d5c5c3f0e96d3 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+303
Assets/UnityTestTools/Common/Editor/ResultWriter/XmlResultWriter.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Globalization; 4 + using System.IO; 5 + using System.Security; 6 + using System.Text; 7 + using UnityEngine; 8 + 9 + namespace UnityTest 10 + { 11 + public class XmlResultWriter 12 + { 13 + private readonly StringBuilder m_ResultWriter = new StringBuilder(); 14 + private int m_Indend; 15 + private readonly string m_SuiteName; 16 + private readonly ITestResult[] m_Results; 17 + string m_Platform; 18 + 19 + public XmlResultWriter(string suiteName, string platform, ITestResult[] results) 20 + { 21 + m_SuiteName = suiteName; 22 + m_Results = results; 23 + m_Platform = platform; 24 + } 25 + 26 + private const string k_NUnitVersion = "2.6.2-Unity"; 27 + 28 + public string GetTestResult() 29 + { 30 + InitializeXmlFile(m_SuiteName, new ResultSummarizer(m_Results)); 31 + foreach (var result in m_Results) 32 + { 33 + WriteResultElement(result); 34 + } 35 + TerminateXmlFile(); 36 + return m_ResultWriter.ToString(); 37 + } 38 + 39 + private void InitializeXmlFile(string resultsName, ResultSummarizer summaryResults) 40 + { 41 + WriteHeader(); 42 + 43 + DateTime now = DateTime.Now; 44 + var attributes = new Dictionary<string, string> 45 + { 46 + {"name", "Unity Tests"}, 47 + {"total", summaryResults.TestsRun.ToString()}, 48 + {"errors", summaryResults.Errors.ToString()}, 49 + {"failures", summaryResults.Failures.ToString()}, 50 + {"not-run", summaryResults.TestsNotRun.ToString()}, 51 + {"inconclusive", summaryResults.Inconclusive.ToString()}, 52 + {"ignored", summaryResults.Ignored.ToString()}, 53 + {"skipped", summaryResults.Skipped.ToString()}, 54 + {"invalid", summaryResults.NotRunnable.ToString()}, 55 + {"date", now.ToString("yyyy-MM-dd")}, 56 + {"time", now.ToString("HH:mm:ss")} 57 + }; 58 + 59 + WriteOpeningElement("test-results", attributes); 60 + 61 + WriteEnvironment(m_Platform); 62 + WriteCultureInfo(); 63 + WriteTestSuite(resultsName, summaryResults); 64 + WriteOpeningElement("results"); 65 + } 66 + 67 + private void WriteOpeningElement(string elementName) 68 + { 69 + WriteOpeningElement(elementName, new Dictionary<string, string>()); 70 + } 71 + 72 + private void WriteOpeningElement(string elementName, Dictionary<string, string> attributes) 73 + { 74 + WriteOpeningElement(elementName, attributes, false); 75 + } 76 + 77 + 78 + private void WriteOpeningElement(string elementName, Dictionary<string, string> attributes, bool closeImmediatelly) 79 + { 80 + WriteIndend(); 81 + m_Indend++; 82 + m_ResultWriter.Append("<"); 83 + m_ResultWriter.Append(elementName); 84 + foreach (var attribute in attributes) 85 + { 86 + m_ResultWriter.AppendFormat(" {0}=\"{1}\"", attribute.Key, SecurityElement.Escape(attribute.Value)); 87 + } 88 + if (closeImmediatelly) 89 + { 90 + m_ResultWriter.Append(" /"); 91 + m_Indend--; 92 + } 93 + m_ResultWriter.AppendLine(">"); 94 + } 95 + 96 + private void WriteIndend() 97 + { 98 + for (int i = 0; i < m_Indend; i++) 99 + { 100 + m_ResultWriter.Append(" "); 101 + } 102 + } 103 + 104 + private void WriteClosingElement(string elementName) 105 + { 106 + m_Indend--; 107 + WriteIndend(); 108 + m_ResultWriter.AppendLine("</" + elementName + ">"); 109 + } 110 + 111 + private void WriteHeader() 112 + { 113 + m_ResultWriter.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); 114 + m_ResultWriter.AppendLine("<!--This file represents the results of running a test suite-->"); 115 + } 116 + 117 + static string GetEnvironmentUserName() 118 + { 119 + return Environment.UserName; 120 + } 121 + 122 + static string GetEnvironmentMachineName() 123 + { 124 + return Environment.MachineName; 125 + } 126 + 127 + static string GetEnvironmentUserDomainName() 128 + { 129 + return Environment.UserDomainName; 130 + } 131 + 132 + static string GetEnvironmentVersion() 133 + { 134 + return Environment.Version.ToString(); 135 + } 136 + 137 + static string GetEnvironmentOSVersion() 138 + { 139 + return Environment.OSVersion.ToString(); 140 + } 141 + 142 + static string GetEnvironmentOSVersionPlatform() 143 + { 144 + return Environment.OSVersion.Platform.ToString(); 145 + } 146 + 147 + static string EnvironmentGetCurrentDirectory() 148 + { 149 + return Environment.CurrentDirectory; 150 + } 151 + 152 + private void WriteEnvironment( string targetPlatform ) 153 + { 154 + var attributes = new Dictionary<string, string> 155 + { 156 + {"nunit-version", k_NUnitVersion}, 157 + {"clr-version", GetEnvironmentVersion()}, 158 + {"os-version", GetEnvironmentOSVersion()}, 159 + {"platform", GetEnvironmentOSVersionPlatform()}, 160 + {"cwd", EnvironmentGetCurrentDirectory()}, 161 + {"machine-name", GetEnvironmentMachineName()}, 162 + {"user", GetEnvironmentUserName()}, 163 + {"user-domain", GetEnvironmentUserDomainName()}, 164 + {"unity-version", Application.unityVersion}, 165 + {"unity-platform", targetPlatform} 166 + }; 167 + WriteOpeningElement("environment", attributes, true); 168 + } 169 + 170 + private void WriteCultureInfo() 171 + { 172 + var attributes = new Dictionary<string, string> 173 + { 174 + {"current-culture", CultureInfo.CurrentCulture.ToString()}, 175 + {"current-uiculture", CultureInfo.CurrentUICulture.ToString()} 176 + }; 177 + WriteOpeningElement("culture-info", attributes, true); 178 + } 179 + 180 + private void WriteTestSuite(string resultsName, ResultSummarizer summaryResults) 181 + { 182 + var attributes = new Dictionary<string, string> 183 + { 184 + {"name", resultsName}, 185 + {"type", "Assembly"}, 186 + {"executed", "True"}, 187 + {"result", summaryResults.Success ? "Success" : "Failure"}, 188 + {"success", summaryResults.Success ? "True" : "False"}, 189 + {"time", summaryResults.Duration.ToString("#####0.000", NumberFormatInfo.InvariantInfo)} 190 + }; 191 + WriteOpeningElement("test-suite", attributes); 192 + } 193 + 194 + private void WriteResultElement(ITestResult result) 195 + { 196 + StartTestElement(result); 197 + 198 + switch (result.ResultState) 199 + { 200 + case TestResultState.Ignored: 201 + case TestResultState.NotRunnable: 202 + case TestResultState.Skipped: 203 + WriteReasonElement(result); 204 + break; 205 + 206 + case TestResultState.Failure: 207 + case TestResultState.Error: 208 + case TestResultState.Cancelled: 209 + WriteFailureElement(result); 210 + break; 211 + case TestResultState.Success: 212 + case TestResultState.Inconclusive: 213 + if (result.Message != null) 214 + WriteReasonElement(result); 215 + break; 216 + }; 217 + 218 + WriteClosingElement("test-case"); 219 + } 220 + 221 + private void TerminateXmlFile() 222 + { 223 + WriteClosingElement("results"); 224 + WriteClosingElement("test-suite"); 225 + WriteClosingElement("test-results"); 226 + } 227 + 228 + #region Element Creation Helpers 229 + 230 + private void StartTestElement(ITestResult result) 231 + { 232 + var attributes = new Dictionary<string, string> 233 + { 234 + {"name", result.FullName}, 235 + {"executed", result.Executed.ToString()} 236 + }; 237 + string resultString; 238 + switch (result.ResultState) 239 + { 240 + case TestResultState.Cancelled: 241 + resultString = TestResultState.Failure.ToString(); 242 + break; 243 + default: 244 + resultString = result.ResultState.ToString(); 245 + break; 246 + } 247 + attributes.Add("result", resultString); 248 + if (result.Executed) 249 + { 250 + attributes.Add("success", result.IsSuccess.ToString()); 251 + attributes.Add("time", result.Duration.ToString("#####0.000", NumberFormatInfo.InvariantInfo)); 252 + } 253 + WriteOpeningElement("test-case", attributes); 254 + } 255 + 256 + private void WriteReasonElement(ITestResult result) 257 + { 258 + WriteOpeningElement("reason"); 259 + WriteOpeningElement("message"); 260 + WriteCData(result.Message); 261 + WriteClosingElement("message"); 262 + WriteClosingElement("reason"); 263 + } 264 + 265 + private void WriteFailureElement(ITestResult result) 266 + { 267 + WriteOpeningElement("failure"); 268 + WriteOpeningElement("message"); 269 + WriteCData(result.Message); 270 + WriteClosingElement("message"); 271 + WriteOpeningElement("stack-trace"); 272 + if (result.StackTrace != null) 273 + WriteCData(StackTraceFilter.Filter(result.StackTrace)); 274 + WriteClosingElement("stack-trace"); 275 + WriteClosingElement("failure"); 276 + } 277 + 278 + #endregion 279 + 280 + private void WriteCData(string text) 281 + { 282 + if (string.IsNullOrEmpty(text)) 283 + return; 284 + m_ResultWriter.AppendFormat("<![CDATA[{0}]]>", text); 285 + m_ResultWriter.AppendLine(); 286 + } 287 + 288 + public void WriteToFile(string resultDestiantion, string resultFileName) 289 + { 290 + try 291 + { 292 + var path = Path.Combine(resultDestiantion, resultFileName); 293 + Debug.Log("Saving results in " + path); 294 + File.WriteAllText(path, GetTestResult(), Encoding.UTF8); 295 + } 296 + catch (Exception e) 297 + { 298 + Debug.LogError("Error while opening file"); 299 + Debug.LogException(e); 300 + } 301 + } 302 + } 303 + }
+8
Assets/UnityTestTools/Common/Editor/ResultWriter/XmlResultWriter.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: e9bba41ace7686d4ab0c400d1e7f55b7 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+47
Assets/UnityTestTools/Common/Editor/Styles.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEditor; 4 + using UnityEngine; 5 + 6 + namespace UnityTest 7 + { 8 + public static class Styles 9 + { 10 + public static GUIStyle info; 11 + public static GUIStyle testList; 12 + 13 + public static GUIStyle selectedFoldout; 14 + public static GUIStyle foldout; 15 + public static GUIStyle toolbarLabel; 16 + 17 + public static GUIStyle testName; 18 + 19 + private static readonly Color k_SelectedColor = new Color(0.3f, 0.5f, 0.85f); 20 + 21 + static Styles() 22 + { 23 + info = new GUIStyle(EditorStyles.wordWrappedLabel); 24 + info.wordWrap = false; 25 + info.stretchHeight = true; 26 + info.margin.right = 15; 27 + 28 + testList = new GUIStyle("CN Box"); 29 + testList.margin.top = 0; 30 + testList.padding.left = 3; 31 + 32 + foldout = new GUIStyle(EditorStyles.foldout); 33 + selectedFoldout = new GUIStyle(EditorStyles.foldout); 34 + selectedFoldout.onFocused.textColor = selectedFoldout.focused.textColor = 35 + selectedFoldout.onActive.textColor = selectedFoldout.active.textColor = 36 + selectedFoldout.onNormal.textColor = selectedFoldout.normal.textColor = k_SelectedColor; 37 + 38 + toolbarLabel = new GUIStyle(EditorStyles.toolbarButton); 39 + toolbarLabel.normal.background = null; 40 + toolbarLabel.contentOffset = new Vector2(0, -2); 41 + 42 + testName = new GUIStyle(EditorStyles.label); 43 + testName.padding.left += 12; 44 + testName.focused.textColor = testName.onFocused.textColor = k_SelectedColor; 45 + } 46 + } 47 + }
+8
Assets/UnityTestTools/Common/Editor/Styles.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: a8b92379e11501742b1badcbb08da812 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+104
Assets/UnityTestTools/Common/Editor/TestFilterSettings.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + using UnityEditor; 5 + using System.Linq; 6 + 7 + namespace UnityTest 8 + { 9 + public class TestFilterSettings 10 + { 11 + public bool ShowSucceeded; 12 + public bool ShowFailed; 13 + public bool ShowIgnored; 14 + public bool ShowNotRun; 15 + 16 + public string FilterByName; 17 + public int FilterByCategory; 18 + 19 + private GUIContent _succeededBtn; 20 + private GUIContent _failedBtn; 21 + private GUIContent _ignoredBtn; 22 + private GUIContent _notRunBtn; 23 + 24 + public string[] AvailableCategories; 25 + 26 + private readonly string _prefsKey; 27 + 28 + public TestFilterSettings(string prefsKey) 29 + { 30 + _prefsKey = prefsKey; 31 + Load(); 32 + UpdateCounters(Enumerable.Empty<ITestResult>()); 33 + } 34 + 35 + public void Load() 36 + { 37 + ShowSucceeded = EditorPrefs.GetBool(_prefsKey + ".ShowSucceeded", true); 38 + ShowFailed = EditorPrefs.GetBool(_prefsKey + ".ShowFailed", true); 39 + ShowIgnored = EditorPrefs.GetBool(_prefsKey + ".ShowIgnored", true); 40 + ShowNotRun = EditorPrefs.GetBool(_prefsKey + ".ShowNotRun", true); 41 + FilterByName = EditorPrefs.GetString(_prefsKey + ".FilterByName", string.Empty); 42 + FilterByCategory = EditorPrefs.GetInt(_prefsKey + ".FilterByCategory", 0); 43 + } 44 + 45 + public void Save() 46 + { 47 + EditorPrefs.SetBool(_prefsKey + ".ShowSucceeded", ShowSucceeded); 48 + EditorPrefs.SetBool(_prefsKey + ".ShowFailed", ShowFailed); 49 + EditorPrefs.SetBool(_prefsKey + ".ShowIgnored", ShowIgnored); 50 + EditorPrefs.SetBool(_prefsKey + ".ShowNotRun", ShowNotRun); 51 + EditorPrefs.SetString(_prefsKey + ".FilterByName", FilterByName); 52 + EditorPrefs.SetInt(_prefsKey + ".FilterByCategory", FilterByCategory); 53 + } 54 + 55 + public void UpdateCounters(IEnumerable<ITestResult> results) 56 + { 57 + var summary = new ResultSummarizer(results); 58 + 59 + _succeededBtn = new GUIContent(summary.Passed.ToString(), Icons.SuccessImg, "Show tests that succeeded"); 60 + _failedBtn = new GUIContent((summary.Errors + summary.Failures + summary.Inconclusive).ToString(), Icons.FailImg, "Show tests that failed"); 61 + _ignoredBtn = new GUIContent((summary.Ignored + summary.NotRunnable).ToString(), Icons.IgnoreImg, "Show tests that are ignored"); 62 + _notRunBtn = new GUIContent((summary.TestsNotRun - summary.Ignored - summary.NotRunnable).ToString(), Icons.UnknownImg, "Show tests that didn't run"); 63 + } 64 + 65 + public string[] GetSelectedCategories() 66 + { 67 + if(AvailableCategories == null) return new string[0]; 68 + 69 + return AvailableCategories.Where ((c, i) => (FilterByCategory & (1 << i)) != 0).ToArray(); 70 + } 71 + 72 + public void OnGUI() 73 + { 74 + EditorGUI.BeginChangeCheck(); 75 + 76 + FilterByName = GUILayout.TextField(FilterByName, "ToolbarSeachTextField", GUILayout.MinWidth(100), GUILayout.MaxWidth(250), GUILayout.ExpandWidth(true)); 77 + if(GUILayout.Button (GUIContent.none, string.IsNullOrEmpty(FilterByName) ? "ToolbarSeachCancelButtonEmpty" : "ToolbarSeachCancelButton")) 78 + FilterByName = string.Empty; 79 + 80 + if (AvailableCategories != null && AvailableCategories.Length > 0) 81 + FilterByCategory = EditorGUILayout.MaskField(FilterByCategory, AvailableCategories, EditorStyles.toolbarDropDown, GUILayout.MaxWidth(90)); 82 + 83 + ShowSucceeded = GUILayout.Toggle(ShowSucceeded, _succeededBtn, EditorStyles.toolbarButton); 84 + ShowFailed = GUILayout.Toggle(ShowFailed, _failedBtn, EditorStyles.toolbarButton); 85 + ShowIgnored = GUILayout.Toggle(ShowIgnored, _ignoredBtn, EditorStyles.toolbarButton); 86 + ShowNotRun = GUILayout.Toggle(ShowNotRun, _notRunBtn, EditorStyles.toolbarButton); 87 + 88 + if(EditorGUI.EndChangeCheck()) Save (); 89 + } 90 + 91 + public RenderingOptions BuildRenderingOptions() 92 + { 93 + var options = new RenderingOptions(); 94 + options.showSucceeded = ShowSucceeded; 95 + options.showFailed = ShowFailed; 96 + options.showIgnored = ShowIgnored; 97 + options.showNotRunned = ShowNotRun; 98 + options.nameFilter = FilterByName; 99 + options.categories = GetSelectedCategories(); 100 + return options; 101 + } 102 + } 103 + 104 + }
+8
Assets/UnityTestTools/Common/Editor/TestFilterSettings.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 5a2d025e58bff433e963d0a4cd7599ef 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+4
Assets/UnityTestTools/Common/Editor/icons.meta
··· 1 + fileFormatVersion: 2 2 + guid: e8bb6eae11352f44da0d6d8a8959b69e 3 + DefaultImporter: 4 + userData:
Assets/UnityTestTools/Common/Editor/icons/failed.png

This is a binary file and will not be displayed.

+35
Assets/UnityTestTools/Common/Editor/icons/failed.png.meta
··· 1 + fileFormatVersion: 2 2 + guid: 41488feb372865440b7c01773f04c0cf 3 + TextureImporter: 4 + serializedVersion: 2 5 + mipmaps: 6 + mipMapMode: 0 7 + enableMipMap: 0 8 + linearTexture: 1 9 + correctGamma: 0 10 + fadeOut: 0 11 + borderMipMap: 0 12 + mipMapFadeDistanceStart: 1 13 + mipMapFadeDistanceEnd: 3 14 + bumpmap: 15 + convertToNormalMap: 0 16 + externalNormalMap: 0 17 + heightScale: .25 18 + normalMapFilter: 0 19 + isReadable: 0 20 + grayScaleToAlpha: 0 21 + generateCubemap: 0 22 + seamlessCubemap: 0 23 + textureFormat: -1 24 + maxTextureSize: 1024 25 + textureSettings: 26 + filterMode: -1 27 + aniso: 1 28 + mipBias: -1 29 + wrapMode: 1 30 + nPOTScale: 0 31 + lightmap: 0 32 + compressionQuality: 50 33 + textureType: 2 34 + buildTargetSettings: [] 35 + userData:
Assets/UnityTestTools/Common/Editor/icons/ignored.png

This is a binary file and will not be displayed.

+35
Assets/UnityTestTools/Common/Editor/icons/ignored.png.meta
··· 1 + fileFormatVersion: 2 2 + guid: 0076bfa6073f17546b3535ac1b456b0b 3 + TextureImporter: 4 + serializedVersion: 2 5 + mipmaps: 6 + mipMapMode: 0 7 + enableMipMap: 0 8 + linearTexture: 1 9 + correctGamma: 0 10 + fadeOut: 0 11 + borderMipMap: 0 12 + mipMapFadeDistanceStart: 1 13 + mipMapFadeDistanceEnd: 3 14 + bumpmap: 15 + convertToNormalMap: 0 16 + externalNormalMap: 0 17 + heightScale: .25 18 + normalMapFilter: 0 19 + isReadable: 0 20 + grayScaleToAlpha: 0 21 + generateCubemap: 0 22 + seamlessCubemap: 0 23 + textureFormat: -1 24 + maxTextureSize: 1024 25 + textureSettings: 26 + filterMode: -1 27 + aniso: 1 28 + mipBias: -1 29 + wrapMode: 1 30 + nPOTScale: 0 31 + lightmap: 0 32 + compressionQuality: 50 33 + textureType: 2 34 + buildTargetSettings: [] 35 + userData:
Assets/UnityTestTools/Common/Editor/icons/inconclusive.png

This is a binary file and will not be displayed.

+35
Assets/UnityTestTools/Common/Editor/icons/inconclusive.png.meta
··· 1 + fileFormatVersion: 2 2 + guid: e28761099904678488cdddf7b6be2ceb 3 + TextureImporter: 4 + serializedVersion: 2 5 + mipmaps: 6 + mipMapMode: 0 7 + enableMipMap: 0 8 + linearTexture: 1 9 + correctGamma: 0 10 + fadeOut: 0 11 + borderMipMap: 0 12 + mipMapFadeDistanceStart: 1 13 + mipMapFadeDistanceEnd: 3 14 + bumpmap: 15 + convertToNormalMap: 0 16 + externalNormalMap: 0 17 + heightScale: .25 18 + normalMapFilter: 0 19 + isReadable: 0 20 + grayScaleToAlpha: 0 21 + generateCubemap: 0 22 + seamlessCubemap: 0 23 + textureFormat: -1 24 + maxTextureSize: 1024 25 + textureSettings: 26 + filterMode: -1 27 + aniso: 1 28 + mipBias: -1 29 + wrapMode: 1 30 + nPOTScale: 0 31 + lightmap: 0 32 + compressionQuality: 50 33 + textureType: 2 34 + buildTargetSettings: [] 35 + userData:
Assets/UnityTestTools/Common/Editor/icons/normal.png

This is a binary file and will not be displayed.

+35
Assets/UnityTestTools/Common/Editor/icons/normal.png.meta
··· 1 + fileFormatVersion: 2 2 + guid: a9f3c491f4c2f9f43ac33a27c16913dd 3 + TextureImporter: 4 + serializedVersion: 2 5 + mipmaps: 6 + mipMapMode: 0 7 + enableMipMap: 0 8 + linearTexture: 1 9 + correctGamma: 0 10 + fadeOut: 0 11 + borderMipMap: 0 12 + mipMapFadeDistanceStart: 1 13 + mipMapFadeDistanceEnd: 3 14 + bumpmap: 15 + convertToNormalMap: 0 16 + externalNormalMap: 0 17 + heightScale: .25 18 + normalMapFilter: 0 19 + isReadable: 0 20 + grayScaleToAlpha: 0 21 + generateCubemap: 0 22 + seamlessCubemap: 0 23 + textureFormat: -1 24 + maxTextureSize: 1024 25 + textureSettings: 26 + filterMode: -1 27 + aniso: 1 28 + mipBias: -1 29 + wrapMode: 1 30 + nPOTScale: 0 31 + lightmap: 0 32 + compressionQuality: 50 33 + textureType: 2 34 + buildTargetSettings: [] 35 + userData:
Assets/UnityTestTools/Common/Editor/icons/passed.png

This is a binary file and will not be displayed.

+35
Assets/UnityTestTools/Common/Editor/icons/passed.png.meta
··· 1 + fileFormatVersion: 2 2 + guid: 31f7928179ee46d4690d274579efb037 3 + TextureImporter: 4 + serializedVersion: 2 5 + mipmaps: 6 + mipMapMode: 0 7 + enableMipMap: 0 8 + linearTexture: 1 9 + correctGamma: 0 10 + fadeOut: 0 11 + borderMipMap: 0 12 + mipMapFadeDistanceStart: 1 13 + mipMapFadeDistanceEnd: 3 14 + bumpmap: 15 + convertToNormalMap: 0 16 + externalNormalMap: 0 17 + heightScale: .25 18 + normalMapFilter: 0 19 + isReadable: 0 20 + grayScaleToAlpha: 0 21 + generateCubemap: 0 22 + seamlessCubemap: 0 23 + textureFormat: -1 24 + maxTextureSize: 1024 25 + textureSettings: 26 + filterMode: -1 27 + aniso: 1 28 + mipBias: -1 29 + wrapMode: 1 30 + nPOTScale: 0 31 + lightmap: 0 32 + compressionQuality: 50 33 + textureType: 2 34 + buildTargetSettings: [] 35 + userData:
Assets/UnityTestTools/Common/Editor/icons/stopwatch.png

This is a binary file and will not be displayed.

+35
Assets/UnityTestTools/Common/Editor/icons/stopwatch.png.meta
··· 1 + fileFormatVersion: 2 2 + guid: f73f95ae19d51af47ad56044f2779aa1 3 + TextureImporter: 4 + serializedVersion: 2 5 + mipmaps: 6 + mipMapMode: 0 7 + enableMipMap: 0 8 + linearTexture: 1 9 + correctGamma: 0 10 + fadeOut: 0 11 + borderMipMap: 0 12 + mipMapFadeDistanceStart: 1 13 + mipMapFadeDistanceEnd: 3 14 + bumpmap: 15 + convertToNormalMap: 0 16 + externalNormalMap: 0 17 + heightScale: .25 18 + normalMapFilter: 0 19 + isReadable: 0 20 + grayScaleToAlpha: 0 21 + generateCubemap: 0 22 + seamlessCubemap: 0 23 + textureFormat: -1 24 + maxTextureSize: 1024 25 + textureSettings: 26 + filterMode: -1 27 + aniso: 1 28 + mipBias: -1 29 + wrapMode: 1 30 + nPOTScale: 0 31 + lightmap: 0 32 + compressionQuality: 50 33 + textureType: 2 34 + buildTargetSettings: [] 35 + userData:
+29
Assets/UnityTestTools/Common/ITestResult.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + using UnityTest; 5 + 6 + public interface ITestResult 7 + { 8 + TestResultState ResultState { get; } 9 + 10 + string Message { get; } 11 + 12 + string Logs { get; } 13 + 14 + bool Executed { get; } 15 + 16 + string Name { get; } 17 + 18 + string FullName { get; } 19 + 20 + string Id { get; } 21 + 22 + bool IsSuccess { get; } 23 + 24 + double Duration { get; } 25 + 26 + string StackTrace { get; } 27 + 28 + bool IsIgnored { get; } 29 + }
+8
Assets/UnityTestTools/Common/ITestResult.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: d1e4e2c4d00b3f2469494fc0f67cdeae 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+46
Assets/UnityTestTools/Common/TestResultState.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public enum TestResultState : byte 8 + { 9 + Inconclusive = 0, 10 + 11 + /// <summary> 12 + /// The test was not runnable. 13 + /// </summary> 14 + NotRunnable = 1, 15 + 16 + /// <summary> 17 + /// The test has been skipped. 18 + /// </summary> 19 + Skipped = 2, 20 + 21 + /// <summary> 22 + /// The test has been ignored. 23 + /// </summary> 24 + Ignored = 3, 25 + 26 + /// <summary> 27 + /// The test succeeded 28 + /// </summary> 29 + Success = 4, 30 + 31 + /// <summary> 32 + /// The test failed 33 + /// </summary> 34 + Failure = 5, 35 + 36 + /// <summary> 37 + /// The test encountered an unexpected exception 38 + /// </summary> 39 + Error = 6, 40 + 41 + /// <summary> 42 + /// The test was cancelled by the user 43 + /// </summary> 44 + Cancelled = 7 45 + } 46 + }
+8
Assets/UnityTestTools/Common/TestResultState.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: da3ca54ee4cce064989d27165f3081fb 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+3
Assets/UnityTestTools/Documentation.url
··· 1 + [InternetShortcut] 2 + URL=https://bitbucket.org/Unity-Technologies/unitytesttools/wiki 3 + IconIndex=0
+4
Assets/UnityTestTools/Documentation.url.meta
··· 1 + fileFormatVersion: 2 2 + guid: 28f1b62e1364e5a4e88f7bb94dbcf183 3 + DefaultImporter: 4 + userData:
+5
Assets/UnityTestTools/IntegrationTestsFramework.meta
··· 1 + fileFormatVersion: 2 2 + guid: 241054a0fe63fbb4bb51609fce9b3112 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+9
Assets/UnityTestTools/IntegrationTestsFramework/Libs.meta
··· 1 + fileFormatVersion: 2 2 + guid: e22ba039de7077c4aa95758ef723b803 3 + folderAsset: yes 4 + timeCreated: 1445282049 5 + licenseType: Store 6 + DefaultImporter: 7 + userData: 8 + assetBundleName: 9 + assetBundleVariant:
Assets/UnityTestTools/IntegrationTestsFramework/Libs/Mono.Cecil.Mdb.dll

This is a binary file and will not be displayed.

+20
Assets/UnityTestTools/IntegrationTestsFramework/Libs/Mono.Cecil.Mdb.dll.meta
··· 1 + fileFormatVersion: 2 2 + guid: 713231d47408a06408a45470c967bae8 3 + timeCreated: 1441797177 4 + licenseType: Store 5 + PluginImporter: 6 + serializedVersion: 1 7 + iconMap: {} 8 + executionOrder: {} 9 + isPreloaded: 0 10 + platformData: 11 + Any: 12 + enabled: 0 13 + settings: {} 14 + Editor: 15 + enabled: 1 16 + settings: 17 + DefaultValueInitialized: true 18 + userData: 19 + assetBundleName: 20 + assetBundleVariant:
Assets/UnityTestTools/IntegrationTestsFramework/Libs/Mono.Cecil.dll

This is a binary file and will not be displayed.

+20
Assets/UnityTestTools/IntegrationTestsFramework/Libs/Mono.Cecil.dll.meta
··· 1 + fileFormatVersion: 2 2 + guid: 28fc22990733f8f4ea1137f15e363609 3 + timeCreated: 1441797177 4 + licenseType: Store 5 + PluginImporter: 6 + serializedVersion: 1 7 + iconMap: {} 8 + executionOrder: {} 9 + isPreloaded: 0 10 + platformData: 11 + Any: 12 + enabled: 0 13 + settings: {} 14 + Editor: 15 + enabled: 1 16 + settings: 17 + DefaultValueInitialized: true 18 + userData: 19 + assetBundleName: 20 + assetBundleVariant:
+5
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner.meta
··· 1 + fileFormatVersion: 2 2 + guid: da93545c3ab1aa043bcfb22281b1f66c 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+140
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/DTOFormatter.cs
··· 1 + using System; 2 + using System.IO; 3 + using System.Runtime.Serialization; 4 + using System.Text; 5 + using UnityEngine; 6 + 7 + namespace UnityTest 8 + { 9 + 10 + public class DTOFormatter { 11 + 12 + private interface ITransferInterface 13 + { 14 + void Transfer(ref ResultDTO.MessageType val); 15 + void Transfer(ref TestResultState val); 16 + void Transfer(ref byte val); 17 + void Transfer(ref bool val); 18 + void Transfer(ref int val); 19 + void Transfer(ref float val); 20 + void Transfer(ref double val); 21 + void Transfer(ref string val); 22 + } 23 + 24 + private class Writer : ITransferInterface 25 + { 26 + private readonly Stream _stream; 27 + public Writer(Stream stream) { _stream = stream; } 28 + 29 + private void WriteConvertedNumber(byte[] bytes) 30 + { 31 + if(BitConverter.IsLittleEndian) 32 + Array.Reverse(bytes); 33 + _stream.Write(bytes, 0, bytes.Length); 34 + } 35 + 36 + public void Transfer(ref ResultDTO.MessageType val) { _stream.WriteByte((byte)val); } 37 + public void Transfer(ref TestResultState val) { _stream.WriteByte((byte)val); } 38 + public void Transfer(ref byte val) { _stream.WriteByte(val); } 39 + public void Transfer(ref bool val) { _stream.WriteByte((byte)(val ? 0x01 : 0x00)); } 40 + public void Transfer(ref int val) { WriteConvertedNumber(BitConverter.GetBytes(val)); } 41 + public void Transfer(ref float val) { WriteConvertedNumber(BitConverter.GetBytes(val)); } 42 + public void Transfer(ref double val) { WriteConvertedNumber(BitConverter.GetBytes(val)); } 43 + 44 + public void Transfer(ref string val) 45 + { 46 + var bytes = Encoding.BigEndianUnicode.GetBytes(val); 47 + int length = bytes.Length; 48 + Transfer(ref length); 49 + _stream.Write(bytes, 0, bytes.Length); 50 + } 51 + } 52 + 53 + private class Reader : ITransferInterface 54 + { 55 + private readonly Stream _stream; 56 + public Reader(Stream stream) { _stream = stream; } 57 + 58 + private byte[] ReadConvertedNumber(int size) 59 + { 60 + byte[] buffer = new byte[size]; 61 + _stream.Read (buffer, 0, buffer.Length); 62 + if(BitConverter.IsLittleEndian) 63 + Array.Reverse(buffer); 64 + return buffer; 65 + } 66 + 67 + public void Transfer(ref ResultDTO.MessageType val) { val = (ResultDTO.MessageType)_stream.ReadByte(); } 68 + public void Transfer(ref TestResultState val) { val = (TestResultState)_stream.ReadByte(); } 69 + public void Transfer(ref byte val) { val = (byte)_stream.ReadByte(); } 70 + public void Transfer(ref bool val) { val = (_stream.ReadByte() != 0); } 71 + public void Transfer(ref int val) { val = BitConverter.ToInt32(ReadConvertedNumber(4), 0); } 72 + public void Transfer(ref float val) { val = BitConverter.ToSingle(ReadConvertedNumber(4), 0); } 73 + public void Transfer(ref double val) { val = BitConverter.ToDouble(ReadConvertedNumber(8), 0); } 74 + 75 + public void Transfer(ref string val) 76 + { 77 + int length = 0; 78 + Transfer (ref length); 79 + var bytes = new byte[length]; 80 + int remain = length; 81 + int index = 0; 82 + do { 83 + int bytesRead = _stream.Read(bytes, index, remain); 84 + remain -= bytesRead; 85 + index += bytesRead; 86 + } while (remain > 0); 87 + val = Encoding.BigEndianUnicode.GetString(bytes); 88 + } 89 + } 90 + 91 + private void Transfer(ResultDTO dto, ITransferInterface transfer) 92 + { 93 + transfer.Transfer(ref dto.messageType); 94 + 95 + transfer.Transfer(ref dto.levelCount); 96 + transfer.Transfer(ref dto.loadedLevel); 97 + transfer.Transfer(ref dto.loadedLevelName); 98 + 99 + if(dto.messageType == ResultDTO.MessageType.Ping 100 + || dto.messageType == ResultDTO.MessageType.RunStarted 101 + || dto.messageType == ResultDTO.MessageType.RunFinished 102 + || dto.messageType == ResultDTO.MessageType.RunInterrupted 103 + || dto.messageType == ResultDTO.MessageType.AllScenesFinished) 104 + return; 105 + 106 + transfer.Transfer(ref dto.testName); 107 + transfer.Transfer(ref dto.testTimeout); 108 + 109 + if(dto.messageType == ResultDTO.MessageType.TestStarted) 110 + return; 111 + 112 + if(transfer is Reader) 113 + dto.testResult = new SerializableTestResult(); 114 + SerializableTestResult str = (SerializableTestResult)dto.testResult; 115 + 116 + transfer.Transfer(ref str.resultState); 117 + transfer.Transfer(ref str.message); 118 + transfer.Transfer(ref str.executed); 119 + transfer.Transfer(ref str.name); 120 + transfer.Transfer(ref str.fullName); 121 + transfer.Transfer(ref str.id); 122 + transfer.Transfer(ref str.isSuccess); 123 + transfer.Transfer(ref str.duration); 124 + transfer.Transfer(ref str.stackTrace); 125 + } 126 + 127 + public void Serialize (Stream stream, ResultDTO dto) 128 + { 129 + Transfer(dto, new Writer(stream)); 130 + } 131 + 132 + public object Deserialize (Stream stream) 133 + { 134 + var result = (ResultDTO)FormatterServices.GetSafeUninitializedObject(typeof(ResultDTO)); 135 + Transfer (result, new Reader(stream)); 136 + return result; 137 + } 138 + } 139 + 140 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/DTOFormatter.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 7ae2470508a854b1c9df5375d03f8f58 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+5
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor.meta
··· 1 + fileFormatVersion: 2 2 + guid: caee08596a5965747b8edfde19e2f873 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+188
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using System.Linq; 5 + using UnityEditor; 6 + using UnityEditorInternal; 7 + using UnityEngine; 8 + using UnityTest.IntegrationTests; 9 + 10 + namespace UnityTest 11 + { 12 + public static partial class Batch 13 + { 14 + const string k_ResultFilePathParam = "-resultFilePath="; 15 + private const string k_TestScenesParam = "-testscenes="; 16 + private const string k_OtherBuildScenesParam = "-includeBuildScenes="; 17 + const string k_TargetPlatformParam = "-targetPlatform="; 18 + const string k_ResultFileDirParam = "-resultsFileDirectory="; 19 + 20 + public static int returnCodeTestsOk = 0; 21 + public static int returnCodeTestsFailed = 2; 22 + public static int returnCodeRunError = 3; 23 + 24 + public static void RunIntegrationTests() 25 + { 26 + var targetPlatform = GetTargetPlatform(); 27 + var otherBuildScenes = GetSceneListFromParam (k_OtherBuildScenesParam); 28 + 29 + var testScenes = GetSceneListFromParam(k_TestScenesParam); 30 + if (testScenes.Count == 0) 31 + testScenes = FindTestScenesInProject(); 32 + 33 + RunIntegrationTests(targetPlatform, testScenes, otherBuildScenes); 34 + } 35 + 36 + public static void RunIntegrationTests(BuildTarget ? targetPlatform) 37 + { 38 + var sceneList = FindTestScenesInProject(); 39 + RunIntegrationTests(targetPlatform, sceneList, new List<string>()); 40 + } 41 + 42 + 43 + public static void RunIntegrationTests(BuildTarget? targetPlatform, List<string> testScenes, List<string> otherBuildScenes) 44 + { 45 + if (targetPlatform.HasValue) 46 + BuildAndRun(targetPlatform.Value, testScenes, otherBuildScenes); 47 + else 48 + RunInEditor(testScenes, otherBuildScenes); 49 + } 50 + 51 + private static void BuildAndRun(BuildTarget target, List<string> testScenes, List<string> otherBuildScenes) 52 + { 53 + var resultFilePath = GetParameterArgument(k_ResultFileDirParam); 54 + 55 + const int port = 0; 56 + var ipList = TestRunnerConfigurator.GetAvailableNetworkIPs(); 57 + 58 + var config = new PlatformRunnerConfiguration 59 + { 60 + buildTarget = target, 61 + buildScenes = otherBuildScenes, 62 + testScenes = testScenes, 63 + projectName = "IntegrationTests", 64 + resultsDir = resultFilePath, 65 + sendResultsOverNetwork = InternalEditorUtility.inBatchMode, 66 + ipList = ipList, 67 + port = port 68 + }; 69 + 70 + if (Application.isWebPlayer) 71 + { 72 + config.sendResultsOverNetwork = false; 73 + Debug.Log("You can't use WebPlayer as active platform for running integration tests. Switching to Standalone"); 74 + EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTarget.StandaloneWindows); 75 + } 76 + 77 + PlatformRunner.BuildAndRunInPlayer(config); 78 + } 79 + 80 + private static void RunInEditor(List<string> testScenes, List<string> otherBuildScenes) 81 + { 82 + CheckActiveBuildTarget(); 83 + 84 + NetworkResultsReceiver.StopReceiver(); 85 + if (testScenes == null || testScenes.Count == 0) 86 + { 87 + Debug.Log("No test scenes on the list"); 88 + EditorApplication.Exit(returnCodeRunError); 89 + return; 90 + } 91 + EditorBuildSettings.scenes = (testScenes.Concat(otherBuildScenes).ToList()).Select(s => new EditorBuildSettingsScene(s, true)).ToArray(); 92 + EditorApplication.OpenScene(testScenes.First()); 93 + GuiHelper.SetConsoleErrorPause(false); 94 + 95 + var config = new PlatformRunnerConfiguration 96 + { 97 + resultsDir = GetParameterArgument(k_ResultFileDirParam), 98 + ipList = TestRunnerConfigurator.GetAvailableNetworkIPs(), 99 + port = PlatformRunnerConfiguration.TryToGetFreePort(), 100 + runInEditor = true 101 + }; 102 + 103 + var settings = new PlayerSettingConfigurator(true); 104 + settings.AddConfigurationFile(TestRunnerConfigurator.integrationTestsNetwork, string.Join("\n", config.GetConnectionIPs())); 105 + 106 + NetworkResultsReceiver.StartReceiver(config); 107 + 108 + EditorApplication.isPlaying = true; 109 + } 110 + 111 + private static string GetParameterArgument(string parameterName) 112 + { 113 + foreach (var arg in Environment.GetCommandLineArgs()) 114 + { 115 + if (arg.ToLower().StartsWith(parameterName.ToLower())) 116 + { 117 + return arg.Substring(parameterName.Length); 118 + } 119 + } 120 + return null; 121 + } 122 + 123 + static void CheckActiveBuildTarget() 124 + { 125 + var notSupportedPlatforms = new[] { "MetroPlayer", "WebPlayer", "WebPlayerStreamed" }; 126 + if (notSupportedPlatforms.Contains(EditorUserBuildSettings.activeBuildTarget.ToString())) 127 + { 128 + Debug.Log("activeBuildTarget can not be " 129 + + EditorUserBuildSettings.activeBuildTarget + 130 + " use buildTarget parameter to open Unity."); 131 + } 132 + } 133 + 134 + private static BuildTarget ? GetTargetPlatform() 135 + { 136 + string platformString = null; 137 + BuildTarget buildTarget; 138 + foreach (var arg in Environment.GetCommandLineArgs()) 139 + { 140 + if (arg.ToLower().StartsWith(k_TargetPlatformParam.ToLower())) 141 + { 142 + platformString = arg.Substring(k_ResultFilePathParam.Length); 143 + break; 144 + } 145 + } 146 + try 147 + { 148 + if (platformString == null) return null; 149 + buildTarget = (BuildTarget)Enum.Parse(typeof(BuildTarget), platformString); 150 + } 151 + catch 152 + { 153 + return null; 154 + } 155 + return buildTarget; 156 + } 157 + 158 + private static List<string> FindTestScenesInProject() 159 + { 160 + var integrationTestScenePattern = "*Test?.unity"; 161 + return Directory.GetFiles("Assets", integrationTestScenePattern, SearchOption.AllDirectories).ToList(); 162 + } 163 + 164 + private static List<string> GetSceneListFromParam(string param) 165 + { 166 + var sceneList = new List<string>(); 167 + foreach (var arg in Environment.GetCommandLineArgs()) 168 + { 169 + if (arg.ToLower().StartsWith(param.ToLower())) 170 + { 171 + var scenesFromParam = arg.Substring(param.Length).Split(','); 172 + foreach (var scene in scenesFromParam) 173 + { 174 + var sceneName = scene; 175 + if (!sceneName.EndsWith(".unity")) 176 + sceneName += ".unity"; 177 + var foundScenes = Directory.GetFiles(Directory.GetCurrentDirectory(), sceneName, SearchOption.AllDirectories); 178 + if (foundScenes.Length == 1) 179 + sceneList.Add(foundScenes[0].Substring(Directory.GetCurrentDirectory().Length + 1)); 180 + else 181 + Debug.Log(sceneName + " not found or multiple entries found"); 182 + } 183 + } 184 + } 185 + return sceneList.Where(s => !string.IsNullOrEmpty(s)).Distinct().ToList(); 186 + } 187 + } 188 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Batch.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 29d4fb050362c5b43aea52342045543a 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+102
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/EditorReferencesUtil.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using System.Linq; 5 + using UnityEditor; 6 + using UnityEngine; 7 + using Object = UnityEngine.Object; 8 + 9 + namespace UnityTest 10 + { 11 + public static class EditorReferencesUtil 12 + { 13 + 14 + public static List<Object> FindScenesWhichContainAsset(string file) 15 + { 16 + string assetPath = GetAssetPathFromFileNameAndExtension (file); 17 + Object cur = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Object)); 18 + return AllScenes.Where(a => ADependsOnB(a, cur)).ToList(); 19 + } 20 + 21 + private static string CleanPathSeparators(string s) 22 + { 23 + const string forwardSlash = "/"; 24 + const string backSlash = "\\"; 25 + return s.Replace(backSlash, forwardSlash); 26 + } 27 + 28 + private static string GetRelativeAssetPathFromFullPath(string fullPath) 29 + { 30 + fullPath = CleanPathSeparators(fullPath); 31 + if (fullPath.Contains(Application.dataPath)) 32 + { 33 + return fullPath.Replace(Application.dataPath, "Assets"); 34 + } 35 + Debug.LogWarning("Path does not point to a location within Assets: " + fullPath); 36 + return null; 37 + } 38 + 39 + private static string GetAssetPathFromFileNameAndExtension(string assetName) 40 + { 41 + string[] assets = AssetDatabase.FindAssets (Path.GetFileNameWithoutExtension (assetName)); 42 + string assetPath = null; 43 + 44 + foreach (string guid in assets) { 45 + string relativePath = AssetDatabase.GUIDToAssetPath (guid); 46 + 47 + if (Path.GetFileName (relativePath) == Path.GetFileName (assetName)) 48 + assetPath = relativePath; 49 + } 50 + 51 + return assetPath; 52 + } 53 + 54 + private static List<FileInfo> DirSearch(DirectoryInfo d, string searchFor) 55 + { 56 + List<FileInfo> founditems = d.GetFiles(searchFor).ToList(); 57 + 58 + // Add (by recursing) subdirectory items. 59 + DirectoryInfo[] dis = d.GetDirectories(); 60 + foreach (DirectoryInfo di in dis) 61 + founditems.AddRange(DirSearch(di, searchFor)); 62 + 63 + return (founditems); 64 + } 65 + 66 + private static List<Object> AllScenes 67 + { 68 + get 69 + { 70 + // get every single one of the files in the Assets folder. 71 + List<FileInfo> files = DirSearch(new DirectoryInfo(Application.dataPath), "*.unity"); 72 + 73 + // now make them all into Asset references. 74 + List<Object> assetRefs = new List<Object>(); 75 + 76 + foreach (FileInfo fi in files) 77 + { 78 + if (fi.Name.StartsWith(".")) 79 + continue; // Unity ignores dotfiles. 80 + assetRefs.Add(AssetDatabase.LoadMainAssetAtPath(GetRelativeAssetPathFromFullPath(fi.FullName))); 81 + } 82 + return assetRefs; 83 + } 84 + } 85 + 86 + private static bool ADependsOnB(Object obj, Object selectedObj) 87 + { 88 + if (selectedObj == null) return false; 89 + 90 + //optionally, exclude self. 91 + if (selectedObj == obj) return false; 92 + 93 + Object[] dependencies = EditorUtility.CollectDependencies(new Object[1] { obj }); 94 + if (dependencies.Length < 2) return false; // if there's only one, it's us. 95 + 96 + foreach (Object dep in dependencies) 97 + if (dep == selectedObj) 98 + return true; 99 + return false; 100 + } 101 + } 102 + }
+12
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/EditorReferencesUtil.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: aad501c968b324cf3a8d1c52eb09ca04 3 + timeCreated: 1437322927 4 + licenseType: Store 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+35
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/GuiHelper.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using System.Reflection; 5 + using System.Text.RegularExpressions; 6 + using Mono.Cecil; 7 + using Mono.Cecil.Cil; 8 + using Mono.Cecil.Mdb; 9 + using Mono.Collections.Generic; 10 + using UnityEditor; 11 + using UnityEditorInternal; 12 + using UnityEngine; 13 + 14 + namespace UnityTest 15 + { 16 + public static class GuiHelper 17 + { 18 + public static bool GetConsoleErrorPause() 19 + { 20 + Assembly assembly = Assembly.GetAssembly(typeof(SceneView)); 21 + Type type = assembly.GetType("UnityEditorInternal.LogEntries"); 22 + PropertyInfo method = type.GetProperty("consoleFlags"); 23 + var result = (int)method.GetValue(new object(), new object[] { }); 24 + return (result & (1 << 2)) != 0; 25 + } 26 + 27 + public static void SetConsoleErrorPause(bool b) 28 + { 29 + Assembly assembly = Assembly.GetAssembly(typeof(SceneView)); 30 + Type type = assembly.GetType("UnityEditorInternal.LogEntries"); 31 + MethodInfo method = type.GetMethod("SetConsoleFlag"); 32 + method.Invoke(new object(), new object[] { 1 << 2, b }); 33 + } 34 + } 35 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/GuiHelper.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: b0b95014154ef554485afc9c0316556d 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+44
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsHierarchyAnnotation.cs
··· 1 + using UnityEngine; 2 + using System.Collections; 3 + using UnityEditor; 4 + 5 + namespace UnityTest 6 + { 7 + 8 + [InitializeOnLoad] 9 + public class IntegrationTestsHierarchyAnnotation { 10 + 11 + static IntegrationTestsHierarchyAnnotation() 12 + { 13 + EditorApplication.hierarchyWindowItemOnGUI += DoAnnotationGUI; 14 + } 15 + 16 + public static void DoAnnotationGUI(int id, Rect rect) 17 + { 18 + var obj = EditorUtility.InstanceIDToObject(id) as GameObject; 19 + if(!obj) return; 20 + 21 + var tc = obj.GetComponent<TestComponent>(); 22 + if(!tc) return; 23 + 24 + if (!EditorApplication.isPlayingOrWillChangePlaymode 25 + && rect.Contains(Event.current.mousePosition) 26 + && Event.current.type == EventType.MouseDown 27 + && Event.current.button == 1) 28 + { 29 + IntegrationTestRendererBase.DrawContextMenu(tc); 30 + Event.current.Use (); 31 + } 32 + 33 + EditorGUIUtility.SetIconSize(new Vector2(15, 15)); 34 + var result = IntegrationTestsRunnerWindow.GetResultForTest(tc); 35 + if (result != null) 36 + { 37 + var icon = result.Executed ? IntegrationTestRendererBase.GetIconForResult(result.resultType) : Icons.UnknownImg; 38 + EditorGUI.LabelField(new Rect(rect.xMax - 18, rect.yMin - 2, rect.width, rect.height), new GUIContent(icon)); 39 + } 40 + EditorGUIUtility.SetIconSize(Vector2.zero); 41 + } 42 + } 43 + 44 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsHierarchyAnnotation.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 219cdb080b08741948fc5deb8c7d47f0 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+25
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerSettings.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + using UnityEditor; 5 + 6 + namespace UnityTest 7 + { 8 + public class IntegrationTestsRunnerSettings : ProjectSettingsBase 9 + { 10 + public bool blockUIWhenRunning = true; 11 + public bool pauseOnTestFailure; 12 + 13 + public void ToggleBlockUIWhenRunning () 14 + { 15 + blockUIWhenRunning = !blockUIWhenRunning; 16 + Save (); 17 + } 18 + 19 + public void TogglePauseOnTestFailure() 20 + { 21 + pauseOnTestFailure = !pauseOnTestFailure; 22 + Save (); 23 + } 24 + } 25 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerSettings.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 5d01dc4c8f278da489d7d54c83f19cb9 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+588
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using System.Text; 5 + using System.Text.RegularExpressions; 6 + using UnityEditor; 7 + using UnityEngine; 8 + using UnityTest.IntegrationTestRunner; 9 + 10 + namespace UnityTest 11 + { 12 + [Serializable] 13 + public class IntegrationTestsRunnerWindow : EditorWindow, IHasCustomMenu 14 + { 15 + #region GUI Contents 16 + private readonly GUIContent m_GUICreateNewTest = new GUIContent("Create", "Create new test"); 17 + private readonly GUIContent m_GUIRunSelectedTests = new GUIContent("Run Selected", "Run selected test(s)"); 18 + private readonly GUIContent m_GUIRunAllTests = new GUIContent("Run All", "Run all tests"); 19 + private readonly GUIContent m_GUIBlockUI = new GUIContent("Block UI when running", "Block UI when running tests"); 20 + private readonly GUIContent m_GUIPauseOnFailure = new GUIContent("Pause on test failure"); 21 + #endregion 22 + 23 + #region runner steerign vars 24 + private static IntegrationTestsRunnerWindow s_Instance; 25 + [SerializeField] private List<GameObject> m_TestsToRun; 26 + [SerializeField] private List<string> m_DynamicTestsToRun; 27 + [SerializeField] private bool m_ReadyToRun; 28 + private bool m_IsBuilding; 29 + public static bool selectedInHierarchy; 30 + private float m_HorizontalSplitBarPosition = 200; 31 + private Vector2 m_TestInfoScroll, m_TestListScroll; 32 + private IntegrationTestRendererBase[] m_TestLines; 33 + private string m_CurrectSceneName; 34 + private TestFilterSettings m_FilterSettings; 35 + 36 + Vector2 m_resultTextSize; 37 + string m_resultText; 38 + GameObject m_lastSelectedGO; 39 + int m_resultTestMaxLength = 15000; 40 + 41 + [SerializeField] private GameObject m_SelectedLine; 42 + [SerializeField] private List<TestResult> m_ResultList = new List<TestResult>(); 43 + [SerializeField] private List<GameObject> m_FoldMarkers = new List<GameObject>(); 44 + 45 + private IntegrationTestsRunnerSettings m_Settings; 46 + 47 + #endregion 48 + 49 + 50 + static IntegrationTestsRunnerWindow() 51 + { 52 + InitBackgroundRunners(); 53 + } 54 + 55 + private static void InitBackgroundRunners() 56 + { 57 + EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw; 58 + EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyWindowItemDraw; 59 + EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate; 60 + EditorApplication.hierarchyWindowChanged += OnHierarchyChangeUpdate; 61 + EditorApplication.update -= BackgroundSceneChangeWatch; 62 + EditorApplication.update += BackgroundSceneChangeWatch; 63 + EditorApplication.playmodeStateChanged -= OnPlaymodeStateChanged; 64 + EditorApplication.playmodeStateChanged += OnPlaymodeStateChanged; 65 + } 66 + 67 + private static void OnPlaymodeStateChanged() 68 + { 69 + if (s_Instance && EditorApplication.isPlaying == EditorApplication.isPlayingOrWillChangePlaymode) 70 + s_Instance.RebuildTestList(); 71 + } 72 + 73 + public void OnDestroy() 74 + { 75 + EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw; 76 + EditorApplication.update -= BackgroundSceneChangeWatch; 77 + EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate; 78 + EditorApplication.playmodeStateChanged -= OnPlaymodeStateChanged; 79 + 80 + TestComponent.DestroyAllDynamicTests(); 81 + } 82 + 83 + private static void BackgroundSceneChangeWatch() 84 + { 85 + if (!s_Instance) return; 86 + if (s_Instance.m_CurrectSceneName != null && s_Instance.m_CurrectSceneName == EditorApplication.currentScene) return; 87 + if (EditorApplication.isPlayingOrWillChangePlaymode) return; 88 + TestComponent.DestroyAllDynamicTests(); 89 + s_Instance.m_CurrectSceneName = EditorApplication.currentScene; 90 + s_Instance.m_ResultList.Clear(); 91 + s_Instance.RebuildTestList(); 92 + } 93 + 94 + public void OnEnable() 95 + { 96 + titleContent = new GUIContent("Integration Tests"); 97 + s_Instance = this; 98 + 99 + m_Settings = ProjectSettingsBase.Load<IntegrationTestsRunnerSettings>(); 100 + m_FilterSettings = new TestFilterSettings("UnityTest.IntegrationTestsRunnerWindow"); 101 + 102 + InitBackgroundRunners(); 103 + if (!EditorApplication.isPlayingOrWillChangePlaymode && !m_ReadyToRun) RebuildTestList(); 104 + } 105 + 106 + public void OnSelectionChange() 107 + { 108 + if (EditorApplication.isPlayingOrWillChangePlaymode 109 + || Selection.objects == null 110 + || Selection.objects.Length == 0) return; 111 + 112 + if (Selection.gameObjects.Length == 1) 113 + { 114 + var go = Selection.gameObjects.Single(); 115 + var temp = go.transform; 116 + while (temp != null) 117 + { 118 + var tc = temp.GetComponent<TestComponent>(); 119 + if (tc != null) break; 120 + temp = temp.parent; 121 + } 122 + 123 + if (temp != null) 124 + { 125 + SelectInHierarchy(temp.gameObject); 126 + Selection.activeGameObject = temp.gameObject; 127 + m_SelectedLine = temp.gameObject; 128 + } 129 + } 130 + } 131 + 132 + public static void OnHierarchyChangeUpdate() 133 + { 134 + if (!s_Instance || s_Instance.m_TestLines == null || EditorApplication.isPlayingOrWillChangePlaymode) return; 135 + 136 + // create a test runner if it doesn't exist 137 + TestRunner.GetTestRunner(); 138 + 139 + // make tests are not places under a go that is not a test itself 140 + foreach (var test in TestComponent.FindAllTestsOnScene()) 141 + { 142 + if (test.gameObject.transform.parent != null && test.gameObject.transform.parent.gameObject.GetComponent<TestComponent>() == null) 143 + { 144 + test.gameObject.transform.parent = null; 145 + Debug.LogWarning("Tests need to be on top of the hierarchy or directly under another test."); 146 + } 147 + } 148 + if (selectedInHierarchy) selectedInHierarchy = false; 149 + else s_Instance.RebuildTestList(); 150 + } 151 + 152 + public static TestResult GetResultForTest(TestComponent tc) 153 + { 154 + if(!s_Instance) return new TestResult(tc); 155 + return s_Instance.m_ResultList.FirstOrDefault(r => r.GameObject == tc.gameObject); 156 + } 157 + 158 + public static void OnHierarchyWindowItemDraw(int id, Rect rect) 159 + { 160 + var o = EditorUtility.InstanceIDToObject(id); 161 + if (o is GameObject) 162 + { 163 + var go = o as GameObject; 164 + 165 + if (Event.current.type == EventType.MouseDown 166 + && Event.current.button == 0 167 + && rect.Contains(Event.current.mousePosition)) 168 + { 169 + var temp = go.transform; 170 + while (temp != null) 171 + { 172 + var c = temp.GetComponent<TestComponent>(); 173 + if (c != null) break; 174 + temp = temp.parent; 175 + } 176 + if (temp != null) SelectInHierarchy(temp.gameObject); 177 + } 178 + } 179 + } 180 + 181 + private static void SelectInHierarchy(GameObject gameObject) 182 + { 183 + if (!s_Instance) return; 184 + if (gameObject == s_Instance.m_SelectedLine && gameObject.activeInHierarchy) return; 185 + if (EditorApplication.isPlayingOrWillChangePlaymode) return; 186 + if (!gameObject.activeSelf) 187 + { 188 + selectedInHierarchy = true; 189 + gameObject.SetActive(true); 190 + } 191 + 192 + var tests = TestComponent.FindAllTestsOnScene(); 193 + var skipList = gameObject.GetComponentsInChildren(typeof(TestComponent), true).ToList(); 194 + tests.RemoveAll(skipList.Contains); 195 + foreach (var test in tests) 196 + { 197 + var enable = test.GetComponentsInChildren(typeof(TestComponent), true).Any(c => c.gameObject == gameObject); 198 + if (test.gameObject.activeSelf != enable) test.gameObject.SetActive(enable); 199 + } 200 + } 201 + 202 + private void RunTests(IList<ITestComponent> tests) 203 + { 204 + if (!tests.Any() || EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode) 205 + return; 206 + FocusWindowIfItsOpen(GetType()); 207 + 208 + var testComponents = tests.Where(t => t is TestComponent).Cast<TestComponent>().ToList(); 209 + var dynaminTests = testComponents.Where(t => t.dynamic).ToList(); 210 + m_DynamicTestsToRun = dynaminTests.Select(c => c.dynamicTypeName).ToList(); 211 + testComponents.RemoveAll(dynaminTests.Contains); 212 + 213 + m_TestsToRun = testComponents.Select( tc => tc.gameObject ).ToList(); 214 + 215 + m_ReadyToRun = true; 216 + TestComponent.DisableAllTests(); 217 + 218 + EditorApplication.isPlaying = true; 219 + } 220 + 221 + public void Update() 222 + { 223 + if (m_ReadyToRun && EditorApplication.isPlaying) 224 + { 225 + m_ReadyToRun = false; 226 + var testRunner = TestRunner.GetTestRunner(); 227 + testRunner.TestRunnerCallback.Add(new RunnerCallback(this)); 228 + var testComponents = m_TestsToRun.Select(go => go.GetComponent<TestComponent>()).ToList(); 229 + testRunner.InitRunner(testComponents, m_DynamicTestsToRun); 230 + } 231 + } 232 + 233 + private void RebuildTestList() 234 + { 235 + m_TestLines = null; 236 + if (!TestComponent.AnyTestsOnScene() 237 + && !TestComponent.AnyDynamicTestForCurrentScene()) return; 238 + 239 + if (!EditorApplication.isPlayingOrWillChangePlaymode) 240 + { 241 + var dynamicTestsOnScene = TestComponent.FindAllDynamicTestsOnScene(); 242 + var dynamicTestTypes = TestComponent.GetTypesWithHelpAttribute(EditorApplication.currentScene); 243 + 244 + foreach (var dynamicTestType in dynamicTestTypes) 245 + { 246 + var existingTests = dynamicTestsOnScene.Where(component => component.dynamicTypeName == dynamicTestType.AssemblyQualifiedName); 247 + if (existingTests.Any()) 248 + { 249 + var testComponent = existingTests.Single(); 250 + foreach (var c in testComponent.gameObject.GetComponents<Component>()) 251 + { 252 + var type = Type.GetType(testComponent.dynamicTypeName); 253 + if (c is TestComponent || c is Transform || type.IsInstanceOfType(c)) continue; 254 + DestroyImmediate(c); 255 + } 256 + dynamicTestsOnScene.Remove(existingTests.Single()); 257 + continue; 258 + } 259 + TestComponent.CreateDynamicTest(dynamicTestType); 260 + } 261 + 262 + foreach (var testComponent in dynamicTestsOnScene) 263 + DestroyImmediate(testComponent.gameObject); 264 + } 265 + 266 + var topTestList = TestComponent.FindAllTopTestsOnScene(); 267 + 268 + var newResultList = new List<TestResult>(); 269 + m_TestLines = ParseTestList(topTestList, newResultList); 270 + 271 + var oldDynamicResults = m_ResultList.Where(result => result.dynamicTest); 272 + foreach (var oldResult in m_ResultList) 273 + { 274 + var result = newResultList.Find(r => r.Id == oldResult.Id); 275 + if (result == null) continue; 276 + result.Update(oldResult); 277 + } 278 + newResultList.AddRange(oldDynamicResults.Where(r => !newResultList.Contains(r))); 279 + m_ResultList = newResultList; 280 + 281 + IntegrationTestRendererBase.RunTest = RunTests; 282 + IntegrationTestGroupLine.FoldMarkers = m_FoldMarkers; 283 + IntegrationTestLine.Results = m_ResultList; 284 + 285 + m_FilterSettings.UpdateCounters(m_ResultList.Cast<ITestResult>()); 286 + 287 + m_FoldMarkers.RemoveAll(o => o == null); 288 + 289 + selectedInHierarchy = true; 290 + Repaint(); 291 + } 292 + 293 + 294 + private IntegrationTestRendererBase[] ParseTestList(List<TestComponent> testList, List<TestResult> results) 295 + { 296 + var tempList = new List<IntegrationTestRendererBase>(); 297 + foreach (var testObject in testList) 298 + { 299 + if (!testObject.IsTestGroup()) 300 + { 301 + var result = new TestResult(testObject); 302 + if (results != null) 303 + results.Add(result); 304 + tempList.Add(new IntegrationTestLine(testObject.gameObject, result)); 305 + continue; 306 + } 307 + var group = new IntegrationTestGroupLine(testObject.gameObject); 308 + var children = testObject.gameObject.GetComponentsInChildren(typeof(TestComponent), true).Cast<TestComponent>().ToList(); 309 + children = children.Where(c => c.gameObject.transform.parent == testObject.gameObject.transform).ToList(); 310 + group.AddChildren(ParseTestList(children, results)); 311 + tempList.Add(group); 312 + } 313 + tempList.Sort(); 314 + return tempList.ToArray(); 315 + } 316 + 317 + public void OnGUI() 318 + { 319 + if (BuildPipeline.isBuildingPlayer) 320 + { 321 + m_IsBuilding = true; 322 + } 323 + else if (m_IsBuilding) 324 + { 325 + m_IsBuilding = false; 326 + Repaint(); 327 + } 328 + 329 + PrintHeadPanel(); 330 + 331 + EditorGUILayout.BeginVertical(Styles.testList); 332 + m_TestListScroll = EditorGUILayout.BeginScrollView(m_TestListScroll); 333 + bool repaint = PrintTestList(m_TestLines); 334 + GUILayout.FlexibleSpace(); 335 + EditorGUILayout.EndScrollView(); 336 + EditorGUILayout.EndVertical(); 337 + 338 + RenderDetails(); 339 + 340 + if (repaint) Repaint(); 341 + } 342 + 343 + public void PrintHeadPanel() 344 + { 345 + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); 346 + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); 347 + if (GUILayout.Button(m_GUIRunAllTests, EditorStyles.toolbarButton)) 348 + { 349 + RunTests(TestComponent.FindAllTestsOnScene().Cast<ITestComponent>().ToList()); 350 + } 351 + EditorGUI.BeginDisabledGroup(!Selection.gameObjects.Any (t => t.GetComponent(typeof(ITestComponent)))); 352 + if (GUILayout.Button(m_GUIRunSelectedTests, EditorStyles.toolbarButton)) 353 + { 354 + RunTests(Selection.gameObjects.Select(t => t.GetComponent(typeof(TestComponent))).Cast<ITestComponent>().ToList()); 355 + } 356 + EditorGUI.EndDisabledGroup(); 357 + if (GUILayout.Button(m_GUICreateNewTest, EditorStyles.toolbarButton)) 358 + { 359 + var test = TestComponent.CreateTest(); 360 + if (Selection.gameObjects.Length == 1 361 + && Selection.activeGameObject != null 362 + && Selection.activeGameObject.GetComponent<TestComponent>()) 363 + { 364 + test.transform.parent = Selection.activeGameObject.transform.parent; 365 + } 366 + Selection.activeGameObject = test; 367 + RebuildTestList(); 368 + } 369 + EditorGUI.EndDisabledGroup(); 370 + 371 + GUILayout.FlexibleSpace (); 372 + 373 + m_FilterSettings.OnGUI (); 374 + 375 + EditorGUILayout.EndHorizontal (); 376 + } 377 + 378 + public void AddItemsToMenu(GenericMenu menu) 379 + { 380 + menu.AddItem(m_GUIBlockUI, m_Settings.blockUIWhenRunning, m_Settings.ToggleBlockUIWhenRunning); 381 + menu.AddItem(m_GUIPauseOnFailure, m_Settings.pauseOnTestFailure, m_Settings.TogglePauseOnTestFailure); 382 + } 383 + 384 + private bool PrintTestList(IntegrationTestRendererBase[] renderedLines) 385 + { 386 + if (renderedLines == null) return false; 387 + 388 + var filter = m_FilterSettings.BuildRenderingOptions(); 389 + 390 + bool repaint = false; 391 + foreach (var renderedLine in renderedLines) 392 + { 393 + repaint |= renderedLine.Render(filter); 394 + } 395 + return repaint; 396 + } 397 + 398 + private void RenderDetails() 399 + { 400 + var ctrlId = GUIUtility.GetControlID(FocusType.Passive); 401 + 402 + Rect rect = GUILayoutUtility.GetLastRect(); 403 + rect.y = rect.height + rect.y - 1; 404 + rect.height = 3; 405 + 406 + EditorGUIUtility.AddCursorRect(rect, MouseCursor.ResizeVertical); 407 + var e = Event.current; 408 + switch (e.type) 409 + { 410 + case EventType.MouseDown: 411 + if (GUIUtility.hotControl == 0 && rect.Contains(e.mousePosition)) 412 + GUIUtility.hotControl = ctrlId; 413 + break; 414 + case EventType.MouseDrag: 415 + if (GUIUtility.hotControl == ctrlId) 416 + { 417 + m_HorizontalSplitBarPosition -= e.delta.y; 418 + if (m_HorizontalSplitBarPosition < 20) m_HorizontalSplitBarPosition = 20; 419 + Repaint(); 420 + } 421 + break; 422 + case EventType.MouseUp: 423 + if (GUIUtility.hotControl == ctrlId) 424 + GUIUtility.hotControl = 0; 425 + break; 426 + } 427 + 428 + m_TestInfoScroll = EditorGUILayout.BeginScrollView(m_TestInfoScroll, GUILayout.MinHeight(m_HorizontalSplitBarPosition)); 429 + 430 + if (m_SelectedLine != null) 431 + UpdateResultText(m_SelectedLine); 432 + 433 + EditorGUILayout.SelectableLabel(m_resultText, Styles.info, 434 + GUILayout.ExpandHeight(true), 435 + GUILayout.ExpandWidth(true), 436 + GUILayout.MinWidth(m_resultTextSize.x), 437 + GUILayout.MinHeight(m_resultTextSize.y)); 438 + EditorGUILayout.EndScrollView(); 439 + } 440 + 441 + private void UpdateResultText(GameObject go) 442 + { 443 + if(go == m_lastSelectedGO) return; 444 + m_lastSelectedGO = go; 445 + var result = m_ResultList.Find(r => r.GameObject == go); 446 + if (result == null) 447 + { 448 + m_resultText = string.Empty; 449 + m_resultTextSize = Styles.info.CalcSize(new GUIContent(string.Empty)); 450 + return; 451 + } 452 + var sb = new StringBuilder(result.Name.Trim()); 453 + if (!string.IsNullOrEmpty(result.messages)) 454 + { 455 + sb.Append("\n---\n"); 456 + sb.Append(result.messages.Trim()); 457 + } 458 + if (!string.IsNullOrEmpty(result.stacktrace)) 459 + { 460 + sb.Append("\n---\n"); 461 + sb.Append(result.stacktrace.Trim()); 462 + } 463 + if(sb.Length>m_resultTestMaxLength) 464 + { 465 + sb.Length = m_resultTestMaxLength; 466 + sb.AppendFormat("...\n\n---MESSAGE TRUNCATED AT {0} CHARACTERS---", m_resultTestMaxLength); 467 + } 468 + m_resultText = sb.ToString().Trim(); 469 + m_resultTextSize = Styles.info.CalcSize(new GUIContent(m_resultText)); 470 + } 471 + 472 + public void OnInspectorUpdate() 473 + { 474 + if (focusedWindow != this) Repaint(); 475 + } 476 + 477 + private void SetCurrentTest(TestComponent tc) 478 + { 479 + foreach (var line in m_TestLines) 480 + line.SetCurrentTest(tc); 481 + } 482 + 483 + class RunnerCallback : ITestRunnerCallback 484 + { 485 + private readonly IntegrationTestsRunnerWindow m_Window; 486 + private int m_TestNumber; 487 + private int m_CurrentTestNumber; 488 + 489 + private readonly bool m_ConsoleErrorOnPauseValue; 490 + private readonly bool m_RunInBackground; 491 + private TestComponent m_CurrentTest; 492 + 493 + public RunnerCallback(IntegrationTestsRunnerWindow window) 494 + { 495 + m_Window = window; 496 + 497 + m_ConsoleErrorOnPauseValue = GuiHelper.GetConsoleErrorPause(); 498 + GuiHelper.SetConsoleErrorPause(false); 499 + m_RunInBackground = PlayerSettings.runInBackground; 500 + PlayerSettings.runInBackground = true; 501 + } 502 + 503 + public void RunStarted(string platform, List<TestComponent> testsToRun) 504 + { 505 + EditorApplication.update += OnEditorUpdate; 506 + m_TestNumber = testsToRun.Count; 507 + foreach (var test in testsToRun) 508 + { 509 + var result = m_Window.m_ResultList.Find(r => r.TestComponent == test); 510 + if (result != null) result.Reset(); 511 + } 512 + } 513 + 514 + public void RunFinished(List<TestResult> testResults) 515 + { 516 + m_Window.SetCurrentTest(null); 517 + m_CurrentTest = null; 518 + EditorApplication.update -= OnEditorUpdate; 519 + EditorApplication.isPlaying = false; 520 + EditorUtility.ClearProgressBar(); 521 + GuiHelper.SetConsoleErrorPause(m_ConsoleErrorOnPauseValue); 522 + PlayerSettings.runInBackground = m_RunInBackground; 523 + } 524 + 525 + public void AllScenesFinished() 526 + { 527 + 528 + } 529 + 530 + public void TestStarted(TestResult test) 531 + { 532 + m_Window.SetCurrentTest(test.TestComponent); 533 + m_CurrentTest = test.TestComponent; 534 + } 535 + 536 + 537 + public void TestFinished(TestResult test) 538 + { 539 + m_CurrentTestNumber++; 540 + 541 + var result = m_Window.m_ResultList.Find(r => r.Id == test.Id); 542 + if (result != null) 543 + result.Update(test); 544 + else 545 + m_Window.m_ResultList.Add(test); 546 + 547 + if(test.IsFailure && m_Window.m_Settings.pauseOnTestFailure) 548 + { 549 + EditorUtility.ClearProgressBar(); 550 + EditorApplication.isPaused = true; 551 + } 552 + } 553 + 554 + public void TestRunInterrupted(List<ITestComponent> testsNotRun) 555 + { 556 + Debug.Log("Test run interrupted"); 557 + RunFinished(new List<TestResult>()); 558 + } 559 + 560 + private void OnEditorUpdate() 561 + { 562 + if(!EditorApplication.isPlaying) 563 + { 564 + TestRunInterrupted(null); 565 + return; 566 + } 567 + 568 + if (m_Window.m_Settings.blockUIWhenRunning 569 + && m_CurrentTest != null 570 + && !EditorApplication.isPaused 571 + && EditorUtility.DisplayCancelableProgressBar("Integration Test Runner", 572 + "Running " + m_CurrentTest.Name, 573 + (float)m_CurrentTestNumber / m_TestNumber)) 574 + { 575 + TestRunInterrupted(null); 576 + } 577 + } 578 + } 579 + 580 + [MenuItem("Unity Test Tools/Integration Test Runner %#&t")] 581 + public static IntegrationTestsRunnerWindow ShowWindow() 582 + { 583 + var w = GetWindow(typeof(IntegrationTestsRunnerWindow)); 584 + w.Show(); 585 + return w as IntegrationTestsRunnerWindow; 586 + } 587 + } 588 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/IntegrationTestsRunnerWindow.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 2c898357efb599944818326bb43ba879 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+4
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner.meta
··· 1 + fileFormatVersion: 2 2 + guid: c44e9167d633ee94bb6e078238178308 3 + DefaultImporter: 4 + userData:
+261
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/NetworkResultsReceiver.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using System.Linq; 5 + using System.Net; 6 + using System.Net.Sockets; 7 + using UnityEditor; 8 + using UnityEditorInternal; 9 + using UnityEngine; 10 + 11 + namespace UnityTest 12 + { 13 + [Serializable] 14 + public class NetworkResultsReceiver : EditorWindow 15 + { 16 + public static NetworkResultsReceiver Instance; 17 + 18 + private string m_StatusLabel; 19 + private TcpListener m_Listener; 20 + 21 + [SerializeField] 22 + private PlatformRunnerConfiguration m_Configuration; 23 + 24 + private List<ITestResult> m_TestResults = new List<ITestResult>(); 25 + 26 + #region steering variables 27 + private bool m_RunFinished; 28 + private bool m_Repaint; 29 + 30 + private TimeSpan m_TestTimeout = TimeSpan.Zero; 31 + private DateTime m_LastMessageReceived; 32 + private bool m_Running; 33 + 34 + public TimeSpan ReceiveMessageTimeout = TimeSpan.FromSeconds(30); 35 + private readonly TimeSpan m_InitialConnectionTimeout = TimeSpan.FromSeconds(300); 36 + private bool m_TestFailed; 37 + #endregion 38 + 39 + private void AcceptCallback(TcpClient client) 40 + { 41 + m_Repaint = true; 42 + ResultDTO dto; 43 + try 44 + { 45 + m_LastMessageReceived = DateTime.Now; 46 + using (var stream = client.GetStream()) 47 + { 48 + var bf = new DTOFormatter(); 49 + dto = (ResultDTO)bf.Deserialize(stream); 50 + stream.Close(); 51 + } 52 + client.Close(); 53 + } 54 + catch (ObjectDisposedException e) 55 + { 56 + Debug.LogException(e); 57 + m_StatusLabel = "Got disconnected"; 58 + return; 59 + } 60 + catch (Exception e) 61 + { 62 + Debug.LogException(e); 63 + return; 64 + } 65 + 66 + switch (dto.messageType) 67 + { 68 + case ResultDTO.MessageType.TestStarted: 69 + m_StatusLabel = dto.testName; 70 + m_TestTimeout = TimeSpan.FromSeconds(dto.testTimeout); 71 + break; 72 + case ResultDTO.MessageType.TestFinished: 73 + m_TestResults.Add(dto.testResult); 74 + m_TestTimeout = TimeSpan.Zero; 75 + if (dto.testResult.Executed && dto.testResult.ResultState != TestResultState.Ignored && !dto.testResult.IsSuccess) 76 + m_TestFailed = true; 77 + break; 78 + case ResultDTO.MessageType.RunStarted: 79 + m_TestResults = new List<ITestResult>(); 80 + m_StatusLabel = "Run started: " + dto.loadedLevelName; 81 + break; 82 + case ResultDTO.MessageType.RunFinished: 83 + WriteResultsToLog(dto, m_TestResults); 84 + if (!string.IsNullOrEmpty(m_Configuration.resultsDir)) 85 + { 86 + var platform = m_Configuration.runInEditor ? "Editor" : m_Configuration.buildTarget.ToString(); 87 + var resultWriter = new XmlResultWriter(dto.loadedLevelName, platform, m_TestResults.ToArray()); 88 + try 89 + { 90 + if (!Directory.Exists(m_Configuration.resultsDir)) 91 + { 92 + Directory.CreateDirectory(m_Configuration.resultsDir); 93 + } 94 + var filePath = Path.Combine(m_Configuration.resultsDir, dto.loadedLevelName + ".xml"); 95 + File.WriteAllText(filePath, resultWriter.GetTestResult()); 96 + } 97 + catch (Exception e) 98 + { 99 + Debug.LogException(e); 100 + } 101 + } 102 + break; 103 + case ResultDTO.MessageType.AllScenesFinished: 104 + m_Running = false; 105 + m_RunFinished = true; 106 + break; 107 + case ResultDTO.MessageType.Ping: 108 + break; 109 + } 110 + } 111 + 112 + private void WriteResultsToLog(ResultDTO dto, List<ITestResult> list) 113 + { 114 + string result = "Run finished for: " + dto.loadedLevelName; 115 + var failCount = list.Count(t => t.Executed && !t.IsSuccess); 116 + if (failCount == 0) 117 + result += "\nAll tests passed"; 118 + else 119 + result += "\n" + failCount + " tests failed"; 120 + 121 + if (failCount == 0) 122 + Debug.Log(result); 123 + else 124 + Debug.LogWarning(result); 125 + } 126 + 127 + public void Update() 128 + { 129 + if (EditorApplication.isCompiling 130 + && m_Listener != null) 131 + { 132 + m_Running = false; 133 + m_Listener.Stop(); 134 + return; 135 + } 136 + 137 + if (m_Running) 138 + { 139 + try 140 + { 141 + if (m_Listener != null && m_Listener.Pending()) 142 + { 143 + using (var client = m_Listener.AcceptTcpClient()) 144 + { 145 + AcceptCallback(client); 146 + client.Close(); 147 + } 148 + } 149 + } 150 + catch (InvalidOperationException e) 151 + { 152 + m_StatusLabel = "Exception happened: " + e.Message; 153 + Repaint(); 154 + Debug.LogException(e); 155 + } 156 + } 157 + 158 + if (m_Running) 159 + { 160 + var adjustedtestTimeout = m_TestTimeout.Add(m_TestTimeout); 161 + var timeout = ReceiveMessageTimeout > adjustedtestTimeout ? ReceiveMessageTimeout : adjustedtestTimeout; 162 + if ((DateTime.Now - m_LastMessageReceived) > timeout) 163 + { 164 + Debug.LogError("Timeout when waiting for test results"); 165 + m_RunFinished = true; 166 + } 167 + } 168 + if (m_RunFinished) 169 + { 170 + if (InternalEditorUtility.inBatchMode) 171 + EditorApplication.Exit(m_TestFailed ? Batch.returnCodeTestsFailed : Batch.returnCodeTestsOk); 172 + Close(); 173 + } 174 + if (m_Repaint) Repaint(); 175 + } 176 + 177 + public void OnEnable() 178 + { 179 + minSize = new Vector2(300, 100); 180 + titleContent = new GUIContent("Test run monitor"); 181 + Instance = this; 182 + m_StatusLabel = "Initializing..."; 183 + if (EditorApplication.isCompiling) return; 184 + EnableServer(); 185 + } 186 + 187 + private void EnableServer() 188 + { 189 + if (m_Configuration == null) throw new Exception("No result receiver server configuration."); 190 + 191 + var ipAddress = IPAddress.Any; 192 + if (m_Configuration.ipList != null && m_Configuration.ipList.Count == 1) 193 + ipAddress = IPAddress.Parse(m_Configuration.ipList.Single()); 194 + 195 + var ipAddStr = Equals(ipAddress, IPAddress.Any) ? "[All interfaces]" : ipAddress.ToString(); 196 + 197 + m_Listener = new TcpListener(ipAddress, m_Configuration.port); 198 + m_StatusLabel = "Waiting for connection on: " + ipAddStr + ":" + m_Configuration.port; 199 + 200 + try 201 + { 202 + m_Listener.Start(100); 203 + } 204 + catch (SocketException e) 205 + { 206 + m_StatusLabel = "Exception happened: " + e.Message; 207 + Repaint(); 208 + Debug.LogException(e); 209 + } 210 + m_Running = true; 211 + m_LastMessageReceived = DateTime.Now + m_InitialConnectionTimeout; 212 + } 213 + 214 + public void OnDisable() 215 + { 216 + Instance = null; 217 + if (m_Listener != null) 218 + m_Listener.Stop(); 219 + } 220 + 221 + public void OnGUI() 222 + { 223 + EditorGUILayout.LabelField("Status:", EditorStyles.boldLabel); 224 + EditorGUILayout.LabelField(m_StatusLabel); 225 + GUILayout.FlexibleSpace(); 226 + if (GUILayout.Button("Stop")) 227 + { 228 + StopReceiver(); 229 + if (InternalEditorUtility.inBatchMode) 230 + EditorApplication.Exit(Batch.returnCodeRunError); 231 + } 232 + } 233 + 234 + public static void StartReceiver(PlatformRunnerConfiguration configuration) 235 + { 236 + var w = (NetworkResultsReceiver)GetWindow(typeof(NetworkResultsReceiver), false); 237 + w.SetConfiguration(configuration); 238 + if (!EditorApplication.isCompiling) 239 + { 240 + w.EnableServer(); 241 + } 242 + w.Show(true); 243 + } 244 + 245 + private void SetConfiguration(PlatformRunnerConfiguration configuration) 246 + { 247 + m_Configuration = configuration; 248 + } 249 + 250 + public static void StopReceiver() 251 + { 252 + if (Instance == null) return; 253 + try{ 254 + Instance.Close(); 255 + }catch(Exception e){ 256 + Debug.LogException(e); 257 + DestroyImmediate(Instance); 258 + } 259 + } 260 + } 261 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/NetworkResultsReceiver.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: ade4197221f35dc44adb7649f99af2e7 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+130
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Net; 4 + using System.Net.Sockets; 5 + using UnityEditor; 6 + using UnityEditorInternal; 7 + using UnityEngine; 8 + using System.Linq; 9 + 10 + namespace UnityTest.IntegrationTests 11 + { 12 + public class PlatformRunner 13 + { 14 + public static BuildTarget defaultBuildTarget 15 + { 16 + get 17 + { 18 + var target = EditorPrefs.GetString("ITR-platformRunnerBuildTarget"); 19 + BuildTarget buildTarget; 20 + try 21 + { 22 + buildTarget = (BuildTarget)Enum.Parse(typeof(BuildTarget), target); 23 + } 24 + catch 25 + { 26 + return GetDefaultBuildTarget(); 27 + } 28 + return buildTarget; 29 + } 30 + set { EditorPrefs.SetString("ITR-platformRunnerBuildTarget", value.ToString()); } 31 + } 32 + 33 + [MenuItem("Unity Test Tools/Platform Runner/Run current scene %#&r")] 34 + public static void BuildAndRunCurrentScene() 35 + { 36 + Debug.Log("Building and running current test for " + defaultBuildTarget); 37 + BuildAndRunInPlayer(new PlatformRunnerConfiguration(defaultBuildTarget)); 38 + } 39 + 40 + [MenuItem("Unity Test Tools/Platform Runner/Run on platform %#r")] 41 + public static void RunInPlayer() 42 + { 43 + var w = EditorWindow.GetWindow(typeof(PlatformRunnerSettingsWindow)); 44 + w.Show(); 45 + } 46 + 47 + public static void BuildAndRunInPlayer(PlatformRunnerConfiguration configuration) 48 + { 49 + NetworkResultsReceiver.StopReceiver(); 50 + 51 + var settings = new PlayerSettingConfigurator(false); 52 + 53 + if (configuration.sendResultsOverNetwork) 54 + { 55 + try 56 + { 57 + var l = new TcpListener(IPAddress.Any, configuration.port); 58 + l.Start(); 59 + configuration.port = ((IPEndPoint)l.Server.LocalEndPoint).Port; 60 + l.Stop(); 61 + } 62 + catch (SocketException e) 63 + { 64 + Debug.LogException(e); 65 + if (InternalEditorUtility.inBatchMode) 66 + EditorApplication.Exit(Batch.returnCodeRunError); 67 + } 68 + } 69 + 70 + if (InternalEditorUtility.inBatchMode) 71 + settings.AddConfigurationFile(TestRunnerConfigurator.batchRunFileMarker, ""); 72 + 73 + if (configuration.sendResultsOverNetwork) 74 + settings.AddConfigurationFile(TestRunnerConfigurator.integrationTestsNetwork, 75 + string.Join("\n", configuration.GetConnectionIPs())); 76 + 77 + settings.AddConfigurationFile (TestRunnerConfigurator.testScenesToRun, string.Join ("\n", configuration.testScenes.ToArray())); 78 + 79 + settings.ChangeSettingsForIntegrationTests(); 80 + 81 + AssetDatabase.Refresh(); 82 + 83 + var result = BuildPipeline.BuildPlayer(configuration.testScenes.Concat(configuration.buildScenes).ToArray(), 84 + configuration.GetTempPath(), 85 + configuration.buildTarget, 86 + BuildOptions.AutoRunPlayer | BuildOptions.Development); 87 + 88 + settings.RevertSettingsChanges(); 89 + settings.RemoveAllConfigurationFiles(); 90 + 91 + AssetDatabase.Refresh(); 92 + 93 + if (!string.IsNullOrEmpty(result)) 94 + { 95 + if (InternalEditorUtility.inBatchMode) 96 + EditorApplication.Exit(Batch.returnCodeRunError); 97 + return; 98 + } 99 + 100 + if (configuration.sendResultsOverNetwork) 101 + NetworkResultsReceiver.StartReceiver(configuration); 102 + else if (InternalEditorUtility.inBatchMode) 103 + EditorApplication.Exit(Batch.returnCodeTestsOk); 104 + } 105 + 106 + private static BuildTarget GetDefaultBuildTarget() 107 + { 108 + switch (EditorUserBuildSettings.selectedBuildTargetGroup) 109 + { 110 + case BuildTargetGroup.Android: 111 + return BuildTarget.Android; 112 + case BuildTargetGroup.WebPlayer: 113 + return BuildTarget.WebPlayer; 114 + default: 115 + { 116 + switch (Application.platform) 117 + { 118 + case RuntimePlatform.WindowsPlayer: 119 + return BuildTarget.StandaloneWindows; 120 + case RuntimePlatform.OSXPlayer: 121 + return BuildTarget.StandaloneOSXIntel; 122 + case RuntimePlatform.LinuxPlayer: 123 + return BuildTarget.StandaloneLinux; 124 + } 125 + return BuildTarget.WebPlayer; 126 + } 127 + } 128 + } 129 + } 130 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunner.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: a3581fa3f207a8a4c9988b9f59a510d3 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+78
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerConfiguration.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using System.Linq; 5 + using System.Net; 6 + using System.Net.Sockets; 7 + using UnityEditor; 8 + using UnityEngine; 9 + 10 + [Serializable] 11 + public class PlatformRunnerConfiguration 12 + { 13 + public List<string> buildScenes; 14 + public List<string> testScenes; 15 + public BuildTarget buildTarget; 16 + public bool runInEditor; 17 + public string projectName = EditorApplication.currentScene; 18 + 19 + public string resultsDir = null; 20 + public bool sendResultsOverNetwork; 21 + public List<string> ipList; 22 + public int port; 23 + 24 + public PlatformRunnerConfiguration(BuildTarget buildTarget) 25 + { 26 + this.buildTarget = buildTarget; 27 + projectName = EditorApplication.currentScene; 28 + } 29 + 30 + public PlatformRunnerConfiguration() 31 + : this(BuildTarget.StandaloneWindows) 32 + { 33 + } 34 + 35 + public string GetTempPath() 36 + { 37 + if (string.IsNullOrEmpty(projectName)) 38 + projectName = Path.GetTempFileName(); 39 + 40 + var path = Path.Combine("Temp", projectName); 41 + switch (buildTarget) 42 + { 43 + case BuildTarget.StandaloneWindows: 44 + case BuildTarget.StandaloneWindows64: 45 + return path + ".exe"; 46 + case BuildTarget.StandaloneOSXIntel: 47 + return path + ".app"; 48 + case BuildTarget.Android: 49 + return path + ".apk"; 50 + default: 51 + if (buildTarget.ToString() == "BlackBerry" || buildTarget.ToString() == "BB10") 52 + return path + ".bar"; 53 + return path; 54 + } 55 + } 56 + 57 + public string[] GetConnectionIPs() 58 + { 59 + return ipList.Select(ip => ip + ":" + port).ToArray(); 60 + } 61 + 62 + public static int TryToGetFreePort() 63 + { 64 + var port = -1; 65 + try 66 + { 67 + var l = new TcpListener(IPAddress.Any, 0); 68 + l.Start(); 69 + port = ((IPEndPoint)l.Server.LocalEndPoint).Port; 70 + l.Stop(); 71 + } 72 + catch (SocketException e) 73 + { 74 + Debug.LogException(e); 75 + } 76 + return port; 77 + } 78 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerConfiguration.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: b98fe8c3761da2d4b8cfd8bd6df7050f 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+12
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettings.cs
··· 1 + using System; 2 + using UnityEngine; 3 + 4 + namespace UnityTest 5 + { 6 + public class PlatformRunnerSettings : ProjectSettingsBase 7 + { 8 + public string resultsPath; 9 + public bool sendResultsOverNetwork = true; 10 + public int port = 0; 11 + } 12 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettings.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 964f5f0db2c95bb41aa3dc3beba1f06b 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+315
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using System.Linq; 5 + using System.Net; 6 + using UnityEditor; 7 + using UnityEngine; 8 + using Object = UnityEngine.Object; 9 + 10 + namespace UnityTest.IntegrationTests 11 + { 12 + [Serializable] 13 + public class PlatformRunnerSettingsWindow : EditorWindow 14 + { 15 + private BuildTarget m_BuildTarget; 16 + 17 + private List<string> m_IntegrationTestScenes; 18 + private List<string> m_OtherScenesToBuild; 19 + private List<string> m_AllScenesInProject; 20 + 21 + private Vector2 m_ScrollPosition; 22 + private readonly List<string> m_Interfaces = new List<string>(); 23 + private readonly List<string> m_SelectedScenes = new List<string>(); 24 + 25 + private int m_SelectedInterface; 26 + [SerializeField] 27 + private bool m_AdvancedNetworkingSettings; 28 + 29 + private PlatformRunnerSettings m_Settings; 30 + 31 + private string m_SelectedSceneInAll; 32 + private string m_SelectedSceneInTest; 33 + private string m_SelectedSceneInBuild; 34 + 35 + readonly GUIContent m_Label = new GUIContent("Results target directory", "Directory where the results will be saved. If no value is specified, the results will be generated in project's data folder."); 36 + 37 + public PlatformRunnerSettingsWindow() 38 + { 39 + if (m_OtherScenesToBuild == null) 40 + m_OtherScenesToBuild = new List<string> (); 41 + 42 + if (m_IntegrationTestScenes == null) 43 + m_IntegrationTestScenes = new List<string> (); 44 + 45 + titleContent = new GUIContent("Platform runner"); 46 + m_BuildTarget = PlatformRunner.defaultBuildTarget; 47 + position.Set(position.xMin, position.yMin, 200, position.height); 48 + m_AllScenesInProject = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.unity", SearchOption.AllDirectories).ToList(); 49 + m_AllScenesInProject.Sort(); 50 + var currentScene = (Directory.GetCurrentDirectory() + EditorApplication.currentScene).Replace("\\", "").Replace("/", ""); 51 + var currentScenePath = m_AllScenesInProject.Where(s => s.Replace("\\", "").Replace("/", "") == currentScene); 52 + m_SelectedScenes.AddRange(currentScenePath); 53 + 54 + m_Interfaces.Add("(Any)"); 55 + m_Interfaces.AddRange(TestRunnerConfigurator.GetAvailableNetworkIPs()); 56 + m_Interfaces.Add("127.0.0.1"); 57 + 58 + LoadFromPrefereneces (); 59 + } 60 + 61 + public void OnEnable() 62 + { 63 + m_Settings = ProjectSettingsBase.Load<PlatformRunnerSettings>(); 64 + 65 + // If not configured pre populate with all scenes that have test components on game objects 66 + // This needs to be done outsie of constructor 67 + if (m_IntegrationTestScenes.Count == 0) 68 + m_IntegrationTestScenes = GetScenesWithTestComponents (m_AllScenesInProject); 69 + } 70 + 71 + public void OnGUI() 72 + { 73 + EditorGUILayout.BeginVertical(); 74 + GUIContent label; 75 + 76 + /* We have three lists here, The tests to run, supporting scenes to include in the build and the list of all scenes so users can 77 + * pick the scenes they want to include. The motiviation here is that test scenes may require to additively load other scenes as part of the tests 78 + */ 79 + EditorGUILayout.BeginHorizontal (); 80 + 81 + // Integration Tests To Run 82 + EditorGUILayout.BeginVertical (); 83 + 84 + label = new GUIContent("Tests:", "All Integration Test scenes that you wish to run on the platform"); 85 + EditorGUILayout.LabelField(label, EditorStyles.boldLabel, GUILayout.Height(20f)); 86 + 87 + EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(m_SelectedSceneInTest)); 88 + if (GUILayout.Button("Remove Integration Test")) { 89 + m_IntegrationTestScenes.Remove(m_SelectedSceneInTest); 90 + m_SelectedSceneInTest = ""; 91 + } 92 + EditorGUI.EndDisabledGroup(); 93 + 94 + DrawVerticalSceneList (ref m_IntegrationTestScenes, ref m_SelectedSceneInTest); 95 + EditorGUILayout.EndVertical (); 96 + 97 + // Extra scenes to include in build 98 + EditorGUILayout.BeginVertical (); 99 + label = new GUIContent("Other Scenes in Build:", "If your Integration Tests additivly load any other scenes then you want to include them here so they are part of the build"); 100 + EditorGUILayout.LabelField(label, EditorStyles.boldLabel, GUILayout.Height(20f)); 101 + 102 + 103 + EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(m_SelectedSceneInBuild)); 104 + if (GUILayout.Button("Remove From Build")) { 105 + m_OtherScenesToBuild.Remove(m_SelectedSceneInBuild); 106 + m_SelectedSceneInBuild = ""; 107 + } 108 + EditorGUI.EndDisabledGroup(); 109 + 110 + DrawVerticalSceneList (ref m_OtherScenesToBuild, ref m_SelectedSceneInBuild); 111 + EditorGUILayout.EndVertical (); 112 + 113 + EditorGUILayout.Separator (); 114 + 115 + // All Scenes 116 + EditorGUILayout.BeginVertical (); 117 + label = new GUIContent("Availble Scenes", "These are all the scenes within your project, please select some to run tests"); 118 + EditorGUILayout.LabelField(label, EditorStyles.boldLabel, GUILayout.Height(20f)); 119 + 120 + 121 + EditorGUILayout.BeginHorizontal (); 122 + EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(m_SelectedSceneInAll)); 123 + if (GUILayout.Button("Add As Test")) { 124 + if (!m_IntegrationTestScenes.Contains (m_SelectedSceneInAll) && !m_OtherScenesToBuild.Contains (m_SelectedSceneInAll)) { 125 + m_IntegrationTestScenes.Add(m_SelectedSceneInAll); 126 + } 127 + } 128 + 129 + if (GUILayout.Button("Add to Build")) { 130 + if (!m_IntegrationTestScenes.Contains (m_SelectedSceneInAll) && !m_OtherScenesToBuild.Contains (m_SelectedSceneInAll)) { 131 + m_OtherScenesToBuild.Add(m_SelectedSceneInAll); 132 + } 133 + } 134 + EditorGUI.EndDisabledGroup(); 135 + 136 + EditorGUILayout.EndHorizontal (); 137 + 138 + DrawVerticalSceneList (ref m_AllScenesInProject, ref m_SelectedSceneInAll); 139 + EditorGUILayout.EndVertical (); 140 + 141 + // ButtoNetworkResultsReceiverns to edit scenes in lists 142 + 143 + 144 + EditorGUILayout.EndHorizontal (); 145 + 146 + GUILayout.Space(3); 147 + 148 + // Select target platform 149 + m_BuildTarget = (BuildTarget)EditorGUILayout.EnumPopup("Build tests for", m_BuildTarget); 150 + 151 + if (PlatformRunner.defaultBuildTarget != m_BuildTarget) 152 + { 153 + if (GUILayout.Button("Make default target platform")) 154 + { 155 + PlatformRunner.defaultBuildTarget = m_BuildTarget; 156 + } 157 + } 158 + GUI.enabled = true; 159 + 160 + // Select various Network settings 161 + DrawSetting(); 162 + var build = GUILayout.Button("Build and run tests"); 163 + EditorGUILayout.EndVertical(); 164 + 165 + if (build) 166 + { 167 + BuildAndRun (); 168 + } 169 + } 170 + 171 + private void DrawVerticalSceneList(ref List<string> sourceList, ref string selectString) 172 + { 173 + m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition, Styles.testList); 174 + EditorGUI.indentLevel++; 175 + foreach (var scenePath in sourceList) 176 + { 177 + var path = Path.GetFileNameWithoutExtension(scenePath); 178 + var guiContent = new GUIContent(path, scenePath); 179 + var rect = GUILayoutUtility.GetRect(guiContent, EditorStyles.label); 180 + if (rect.Contains(Event.current.mousePosition)) 181 + { 182 + if (Event.current.type == EventType.mouseDown && Event.current.button == 0) 183 + { 184 + selectString = scenePath; 185 + Event.current.Use(); 186 + } 187 + } 188 + var style = new GUIStyle(EditorStyles.label); 189 + 190 + if (selectString == scenePath) 191 + style.normal.textColor = new Color(0.3f, 0.5f, 0.85f); 192 + EditorGUI.LabelField(rect, guiContent, style); 193 + } 194 + EditorGUI.indentLevel--; 195 + EditorGUILayout.EndScrollView(); 196 + } 197 + 198 + public static List<string> GetScenesWithTestComponents(List<string> allScenes) 199 + { 200 + List<Object> results = EditorReferencesUtil.FindScenesWhichContainAsset("TestComponent.cs"); 201 + List<string> integrationTestScenes = new List<string>(); 202 + 203 + foreach (Object obj in results) { 204 + string result = allScenes.FirstOrDefault(s => s.Contains(obj.name)); 205 + if (!string.IsNullOrEmpty(result)) 206 + integrationTestScenes.Add(result); 207 + } 208 + 209 + return integrationTestScenes; 210 + } 211 + 212 + private void DrawSetting() 213 + { 214 + EditorGUI.BeginChangeCheck(); 215 + 216 + EditorGUILayout.BeginHorizontal(); 217 + m_Settings.resultsPath = EditorGUILayout.TextField(m_Label, m_Settings.resultsPath); 218 + if (GUILayout.Button("Search", EditorStyles.miniButton, GUILayout.Width(50))) 219 + { 220 + var selectedPath = EditorUtility.SaveFolderPanel("Result files destination", m_Settings.resultsPath, ""); 221 + if (!string.IsNullOrEmpty(selectedPath)) 222 + m_Settings.resultsPath = Path.GetFullPath(selectedPath); 223 + } 224 + EditorGUILayout.EndHorizontal(); 225 + 226 + if (!string.IsNullOrEmpty(m_Settings.resultsPath)) 227 + { 228 + Uri uri; 229 + if (!Uri.TryCreate(m_Settings.resultsPath, UriKind.Absolute, out uri) || !uri.IsFile || uri.IsWellFormedOriginalString()) 230 + { 231 + EditorGUILayout.HelpBox("Invalid URI path", MessageType.Warning); 232 + } 233 + } 234 + 235 + m_Settings.sendResultsOverNetwork = EditorGUILayout.Toggle("Send results to editor", m_Settings.sendResultsOverNetwork); 236 + EditorGUI.BeginDisabledGroup(!m_Settings.sendResultsOverNetwork); 237 + m_AdvancedNetworkingSettings = EditorGUILayout.Foldout(m_AdvancedNetworkingSettings, "Advanced network settings"); 238 + if (m_AdvancedNetworkingSettings) 239 + { 240 + m_SelectedInterface = EditorGUILayout.Popup("Network interface", m_SelectedInterface, m_Interfaces.ToArray()); 241 + EditorGUI.BeginChangeCheck(); 242 + m_Settings.port = EditorGUILayout.IntField("Network port", m_Settings.port); 243 + if (EditorGUI.EndChangeCheck()) 244 + { 245 + if (m_Settings.port > IPEndPoint.MaxPort) 246 + m_Settings.port = IPEndPoint.MaxPort; 247 + else if (m_Settings.port < IPEndPoint.MinPort) 248 + m_Settings.port = IPEndPoint.MinPort; 249 + } 250 + EditorGUI.EndDisabledGroup(); 251 + } 252 + if (EditorGUI.EndChangeCheck()) 253 + { 254 + m_Settings.Save(); 255 + } 256 + } 257 + 258 + private void BuildAndRun() 259 + { 260 + SaveToPreferences (); 261 + 262 + var config = new PlatformRunnerConfiguration 263 + { 264 + buildTarget = m_BuildTarget, 265 + buildScenes = m_OtherScenesToBuild, 266 + testScenes = m_IntegrationTestScenes, 267 + projectName = m_IntegrationTestScenes.Count > 1 ? "IntegrationTests" : Path.GetFileNameWithoutExtension(EditorApplication.currentScene), 268 + resultsDir = m_Settings.resultsPath, 269 + sendResultsOverNetwork = m_Settings.sendResultsOverNetwork, 270 + ipList = m_Interfaces.Skip(1).ToList(), 271 + port = m_Settings.port 272 + }; 273 + 274 + if (m_SelectedInterface > 0) 275 + config.ipList = new List<string> {m_Interfaces.ElementAt(m_SelectedInterface)}; 276 + 277 + PlatformRunner.BuildAndRunInPlayer(config); 278 + Close (); 279 + } 280 + 281 + public void OnLostFocus() { 282 + SaveToPreferences (); 283 + } 284 + 285 + public void OnDestroy() { 286 + SaveToPreferences (); 287 + } 288 + 289 + private void SaveToPreferences() 290 + { 291 + EditorPrefs.SetString (Animator.StringToHash (Application.dataPath + "uttTestScenes").ToString (), String.Join (",",m_IntegrationTestScenes.ToArray())); 292 + EditorPrefs.SetString (Animator.StringToHash (Application.dataPath + "uttBuildScenes").ToString (), String.Join (",",m_OtherScenesToBuild.ToArray())); 293 + } 294 + 295 + private void LoadFromPrefereneces() 296 + { 297 + string storedTestScenes = EditorPrefs.GetString (Animator.StringToHash (Application.dataPath + "uttTestScenes").ToString ()); 298 + string storedBuildScenes = EditorPrefs.GetString (Animator.StringToHash (Application.dataPath + "uttBuildScenes").ToString ()); 299 + 300 + List<string> parsedTestScenes = storedTestScenes.Split (',').ToList (); 301 + List<string> parsedBuildScenes = storedBuildScenes.Split (',').ToList (); 302 + 303 + // Sanity check scenes actually exist 304 + foreach (string str in parsedTestScenes) { 305 + if (m_AllScenesInProject.Contains(str)) 306 + m_IntegrationTestScenes.Add(str); 307 + } 308 + 309 + foreach (string str in parsedBuildScenes) { 310 + if (m_AllScenesInProject.Contains(str)) 311 + m_OtherScenesToBuild.Add(str); 312 + } 313 + } 314 + } 315 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlatformRunnerSettingsWindow.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 3819282b0887bc742911b89745080acb 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+73
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlayerSettingConfigurator.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using UnityEditor; 5 + using UnityEngine; 6 + 7 + namespace UnityTest 8 + { 9 + class PlayerSettingConfigurator 10 + { 11 + private string resourcesPath { 12 + get { return m_Temp ? k_TempPath : m_ProjectResourcesPath; } 13 + } 14 + 15 + private readonly string m_ProjectResourcesPath = Path.Combine("Assets", "Resources"); 16 + const string k_TempPath = "Temp"; 17 + private readonly bool m_Temp; 18 + 19 + private ResolutionDialogSetting m_DisplayResolutionDialog; 20 + private bool m_RunInBackground; 21 + private bool m_FullScreen; 22 + private bool m_ResizableWindow; 23 + private readonly List<string> m_TempFileList = new List<string>(); 24 + 25 + public PlayerSettingConfigurator(bool saveInTempFolder) 26 + { 27 + m_Temp = saveInTempFolder; 28 + } 29 + 30 + public void ChangeSettingsForIntegrationTests() 31 + { 32 + m_DisplayResolutionDialog = PlayerSettings.displayResolutionDialog; 33 + PlayerSettings.displayResolutionDialog = ResolutionDialogSetting.Disabled; 34 + 35 + m_RunInBackground = PlayerSettings.runInBackground; 36 + PlayerSettings.runInBackground = true; 37 + 38 + m_FullScreen = PlayerSettings.defaultIsFullScreen; 39 + PlayerSettings.defaultIsFullScreen = false; 40 + 41 + m_ResizableWindow = PlayerSettings.resizableWindow; 42 + PlayerSettings.resizableWindow = true; 43 + } 44 + 45 + public void RevertSettingsChanges() 46 + { 47 + PlayerSettings.defaultIsFullScreen = m_FullScreen; 48 + PlayerSettings.runInBackground = m_RunInBackground; 49 + PlayerSettings.displayResolutionDialog = m_DisplayResolutionDialog; 50 + PlayerSettings.resizableWindow = m_ResizableWindow; 51 + } 52 + 53 + public void AddConfigurationFile(string fileName, string content) 54 + { 55 + var resourcesPathExists = Directory.Exists(resourcesPath); 56 + if (!resourcesPathExists) AssetDatabase.CreateFolder("Assets", "Resources"); 57 + 58 + var filePath = Path.Combine(resourcesPath, fileName); 59 + File.WriteAllText(filePath, content); 60 + 61 + m_TempFileList.Add(filePath); 62 + } 63 + 64 + public void RemoveAllConfigurationFiles() 65 + { 66 + foreach (var filePath in m_TempFileList) 67 + AssetDatabase.DeleteAsset(filePath); 68 + if (Directory.Exists(resourcesPath) 69 + && Directory.GetFiles(resourcesPath).Length == 0) 70 + AssetDatabase.DeleteAsset(resourcesPath); 71 + } 72 + } 73 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/PlatformRunner/PlayerSettingConfigurator.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: c7adbe43058d54047b6109b2e66894fd 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+4
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer.meta
··· 1 + fileFormatVersion: 2 2 + guid: 5944b82e46f1682439d20b4c3a4f029c 3 + DefaultImporter: 4 + userData:
+84
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEditor; 5 + using UnityEngine; 6 + 7 + namespace UnityTest 8 + { 9 + class IntegrationTestGroupLine : IntegrationTestRendererBase 10 + { 11 + public static List<GameObject> FoldMarkers; 12 + private IntegrationTestRendererBase[] m_Children; 13 + 14 + public IntegrationTestGroupLine(GameObject gameObject) : base(gameObject) 15 + { 16 + } 17 + 18 + protected internal override void DrawLine(Rect rect, GUIContent label, bool isSelected, RenderingOptions options) 19 + { 20 + EditorGUI.BeginChangeCheck(); 21 + var isClassFolded = !EditorGUI.Foldout(rect, !Folded, label, isSelected ? Styles.selectedFoldout : Styles.foldout); 22 + if (EditorGUI.EndChangeCheck()) Folded = isClassFolded; 23 + } 24 + 25 + private bool Folded 26 + { 27 + get { return FoldMarkers.Contains(m_GameObject); } 28 + 29 + set 30 + { 31 + if (value) FoldMarkers.Add(m_GameObject); 32 + else FoldMarkers.RemoveAll(s => s == m_GameObject); 33 + } 34 + } 35 + 36 + protected internal override void Render(int indend, RenderingOptions options) 37 + { 38 + base.Render(indend, options); 39 + if (!Folded) 40 + foreach (var child in m_Children) 41 + child.Render(indend + 1, options); 42 + } 43 + 44 + protected internal override TestResult.ResultType GetResult() 45 + { 46 + bool ignored = false; 47 + bool success = false; 48 + foreach (var child in m_Children) 49 + { 50 + var result = child.GetResult(); 51 + 52 + if (result == TestResult.ResultType.Failed || result == TestResult.ResultType.FailedException || result == TestResult.ResultType.Timeout) 53 + return TestResult.ResultType.Failed; 54 + if (result == TestResult.ResultType.Success) 55 + success = true; 56 + else if (result == TestResult.ResultType.Ignored) 57 + ignored = true; 58 + else 59 + ignored = false; 60 + } 61 + if (success) return TestResult.ResultType.Success; 62 + if (ignored) return TestResult.ResultType.Ignored; 63 + return TestResult.ResultType.NotRun; 64 + } 65 + 66 + protected internal override bool IsVisible(RenderingOptions options) 67 + { 68 + return m_Children.Any(c => c.IsVisible(options)); 69 + } 70 + 71 + public override bool SetCurrentTest(TestComponent tc) 72 + { 73 + m_IsRunning = false; 74 + foreach (var child in m_Children) 75 + m_IsRunning |= child.SetCurrentTest(tc); 76 + return m_IsRunning; 77 + } 78 + 79 + public void AddChildren(IntegrationTestRendererBase[] parseTestList) 80 + { 81 + m_Children = parseTestList; 82 + } 83 + } 84 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestGroupLine.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: f6dc74195aa98ef4da8901199cda4a63 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+57
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEditor; 4 + using UnityEngine; 5 + 6 + namespace UnityTest 7 + { 8 + class IntegrationTestLine : IntegrationTestRendererBase 9 + { 10 + public static List<TestResult> Results; 11 + protected TestResult m_Result; 12 + 13 + public IntegrationTestLine(GameObject gameObject, TestResult testResult) : base(gameObject) 14 + { 15 + m_Result = testResult; 16 + } 17 + 18 + protected internal override void DrawLine(Rect rect, GUIContent label, bool isSelected, RenderingOptions options) 19 + { 20 + if(Event.current.type != EventType.repaint) 21 + return; 22 + 23 + Styles.testName.Draw (rect, label, false, false, false, isSelected); 24 + 25 + if (m_Result.IsTimeout) 26 + { 27 + float min, max; 28 + Styles.testName.CalcMinMaxWidth(label, out min, out max); 29 + var timeoutRect = new Rect(rect); 30 + timeoutRect.x += min - 12; 31 + Styles.testName.Draw(timeoutRect, s_GUITimeoutIcon, false, false, false, isSelected); 32 + } 33 + } 34 + 35 + protected internal override TestResult.ResultType GetResult() 36 + { 37 + if (!m_Result.Executed && test.ignored) return TestResult.ResultType.Ignored; 38 + return m_Result.resultType; 39 + } 40 + 41 + protected internal override bool IsVisible(RenderingOptions options) 42 + { 43 + if (!string.IsNullOrEmpty(options.nameFilter) && !m_GameObject.name.ToLower().Contains(options.nameFilter.ToLower())) return false; 44 + if (!options.showSucceeded && m_Result.IsSuccess) return false; 45 + if (!options.showFailed && m_Result.IsFailure) return false; 46 + if (!options.showNotRunned && !m_Result.Executed) return false; 47 + if (!options.showIgnored && test.ignored) return false; 48 + return true; 49 + } 50 + 51 + public override bool SetCurrentTest(TestComponent tc) 52 + { 53 + m_IsRunning = test == tc; 54 + return m_IsRunning; 55 + } 56 + } 57 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestLine.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 212be02e4a7da194688b08ab0c946fbd 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+161
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEditor; 5 + using UnityEngine; 6 + using Object = UnityEngine.Object; 7 + 8 + namespace UnityTest 9 + { 10 + public abstract class IntegrationTestRendererBase : IComparable<IntegrationTestRendererBase> 11 + { 12 + public static Action<IList<ITestComponent>> RunTest; 13 + 14 + protected static bool s_Refresh; 15 + 16 + private static readonly GUIContent k_GUIRunSelected = new GUIContent("Run Selected"); 17 + private static readonly GUIContent k_GUIRun = new GUIContent("Run"); 18 + private static readonly GUIContent k_GUIDelete = new GUIContent("Delete"); 19 + private static readonly GUIContent k_GUIDeleteSelected = new GUIContent("Delete selected"); 20 + 21 + protected static GUIContent s_GUITimeoutIcon = new GUIContent(Icons.StopwatchImg, "Timeout"); 22 + 23 + protected GameObject m_GameObject; 24 + public TestComponent test; 25 + private readonly string m_Name; 26 + 27 + protected IntegrationTestRendererBase(GameObject gameObject) 28 + { 29 + test = gameObject.GetComponent(typeof(TestComponent)) as TestComponent; 30 + if (test == null) throw new ArgumentException("Provided GameObject is not a test object"); 31 + m_GameObject = gameObject; 32 + m_Name = test.Name; 33 + } 34 + 35 + public int CompareTo(IntegrationTestRendererBase other) 36 + { 37 + return test.CompareTo(other.test); 38 + } 39 + 40 + public bool Render(RenderingOptions options) 41 + { 42 + s_Refresh = false; 43 + EditorGUIUtility.SetIconSize(new Vector2(15, 15)); 44 + Render(0, options); 45 + EditorGUIUtility.SetIconSize(Vector2.zero); 46 + return s_Refresh; 47 + } 48 + 49 + protected internal virtual void Render(int indend, RenderingOptions options) 50 + { 51 + if (!IsVisible(options)) return; 52 + EditorGUILayout.BeginHorizontal(); 53 + GUILayout.Space(indend * 10); 54 + 55 + var tempColor = GUI.color; 56 + if (m_IsRunning) 57 + { 58 + var frame = Mathf.Abs(Mathf.Cos(Time.realtimeSinceStartup * 4)) * 0.6f + 0.4f; 59 + GUI.color = new Color(1, 1, 1, frame); 60 + } 61 + 62 + var isSelected = Selection.gameObjects.Contains(m_GameObject); 63 + 64 + var value = GetResult(); 65 + var icon = GetIconForResult(value); 66 + 67 + var label = new GUIContent(m_Name, icon); 68 + var labelRect = GUILayoutUtility.GetRect(label, EditorStyles.label, GUILayout.ExpandWidth(true), GUILayout.Height(18)); 69 + 70 + OnLeftMouseButtonClick(labelRect); 71 + OnContextClick(labelRect); 72 + DrawLine(labelRect, label, isSelected, options); 73 + 74 + if (m_IsRunning) GUI.color = tempColor; 75 + EditorGUILayout.EndHorizontal(); 76 + } 77 + 78 + protected void OnSelect() 79 + { 80 + if (!Event.current.control && !Event.current.command) 81 + { 82 + Selection.objects = new Object[0]; 83 + GUIUtility.keyboardControl = 0; 84 + } 85 + 86 + if ((Event.current.control || Event.current.command) && Selection.gameObjects.Contains(test.gameObject)) 87 + Selection.objects = Selection.gameObjects.Where(o => o != test.gameObject).ToArray(); 88 + else 89 + Selection.objects = Selection.gameObjects.Concat(new[] { test.gameObject }).ToArray(); 90 + } 91 + 92 + protected void OnLeftMouseButtonClick(Rect rect) 93 + { 94 + if (rect.Contains(Event.current.mousePosition) && Event.current.type == EventType.mouseDown && Event.current.button == 0) 95 + { 96 + rect.width = 20; 97 + if (rect.Contains(Event.current.mousePosition)) return; 98 + Event.current.Use(); 99 + OnSelect(); 100 + } 101 + } 102 + 103 + protected void OnContextClick(Rect rect) 104 + { 105 + if (rect.Contains(Event.current.mousePosition) && Event.current.type == EventType.ContextClick) 106 + { 107 + DrawContextMenu(test); 108 + } 109 + } 110 + 111 + public static void DrawContextMenu(TestComponent testComponent) 112 + { 113 + if (EditorApplication.isPlayingOrWillChangePlaymode) return; 114 + 115 + var selectedTests = Selection.gameObjects.Where(go => go.GetComponent(typeof(TestComponent))); 116 + var manySelected = selectedTests.Count() > 1; 117 + 118 + var m = new GenericMenu(); 119 + if (manySelected) 120 + { 121 + // var testsToRun 122 + m.AddItem(k_GUIRunSelected, false, data => RunTest(selectedTests.Select(o => o.GetComponent(typeof(TestComponent))).Cast<ITestComponent>().ToList()), null); 123 + } 124 + m.AddItem(k_GUIRun, false, data => RunTest(new[] { testComponent }), null); 125 + m.AddSeparator(""); 126 + m.AddItem(manySelected ? k_GUIDeleteSelected : k_GUIDelete, false, data => RemoveTests(selectedTests.ToArray()), null); 127 + m.ShowAsContext(); 128 + } 129 + 130 + private static void RemoveTests(GameObject[] testsToDelete) 131 + { 132 + foreach (var t in testsToDelete) 133 + { 134 + Undo.DestroyObjectImmediate(t); 135 + } 136 + } 137 + 138 + public static Texture GetIconForResult(TestResult.ResultType resultState) 139 + { 140 + switch (resultState) 141 + { 142 + case TestResult.ResultType.Success: 143 + return Icons.SuccessImg; 144 + case TestResult.ResultType.Timeout: 145 + case TestResult.ResultType.Failed: 146 + case TestResult.ResultType.FailedException: 147 + return Icons.FailImg; 148 + case TestResult.ResultType.Ignored: 149 + return Icons.IgnoreImg; 150 + default: 151 + return Icons.UnknownImg; 152 + } 153 + } 154 + 155 + protected internal bool m_IsRunning; 156 + protected internal abstract void DrawLine(Rect rect, GUIContent label, bool isSelected, RenderingOptions options); 157 + protected internal abstract TestResult.ResultType GetResult(); 158 + protected internal abstract bool IsVisible(RenderingOptions options); 159 + public abstract bool SetCurrentTest(TestComponent tc); 160 + } 161 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/IntegrationTestRendererBase.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 604645a3b57179a4d873906b625ef8ec 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+16
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/RenderingOptions.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class RenderingOptions 8 + { 9 + public string nameFilter; 10 + public bool showSucceeded; 11 + public bool showFailed; 12 + public bool showIgnored; 13 + public bool showNotRunned; 14 + public string[] categories; 15 + } 16 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/Renderer/RenderingOptions.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 5c0aec4b4a6d1b047a98e8cc213e1a36 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+128
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEditor; 5 + using UnityEngine; 6 + using Object = UnityEngine.Object; 7 + 8 + namespace UnityTest 9 + { 10 + [CanEditMultipleObjects] 11 + [CustomEditor(typeof(TestComponent))] 12 + public class TestComponentEditor : Editor 13 + { 14 + private SerializedProperty m_ExpectException; 15 + private SerializedProperty m_ExpectedExceptionList; 16 + private SerializedProperty m_Ignored; 17 + private SerializedProperty m_SucceedAssertions; 18 + private SerializedProperty m_SucceedWhenExceptionIsThrown; 19 + private SerializedProperty m_Timeout; 20 + 21 + #region GUI Contens 22 + 23 + private readonly GUIContent m_GUIExpectException = new GUIContent("Expect exception", "Should the test expect an exception"); 24 + private readonly GUIContent m_GUIExpectExceptionList = new GUIContent("Expected exception list", "A comma separated list of exception types which will not fail the test when thrown"); 25 + private readonly GUIContent m_GUIIgnore = new GUIContent("Ignore", "Ignore the tests in runs"); 26 + private readonly GUIContent m_GUIIncludePlatforms = new GUIContent("Included platforms", "Platform on which the test should run"); 27 + private readonly GUIContent m_GUISuccedOnAssertions = new GUIContent("Succeed on assertions", "Succeed after all assertions are executed"); 28 + private readonly GUIContent m_GUISucceedWhenExceptionIsThrown = new GUIContent("Succeed when exception is thrown", "Should the test succeed when an expected exception is thrown"); 29 + private readonly GUIContent m_GUITestName = new GUIContent("Test name", "Name of the test (is equal to the GameObject name)"); 30 + private readonly GUIContent m_GUITimeout = new GUIContent("Timeout", "Number of seconds after which the test will timeout"); 31 + 32 + #endregion 33 + 34 + public void OnEnable() 35 + { 36 + m_Timeout = serializedObject.FindProperty("timeout"); 37 + m_Ignored = serializedObject.FindProperty("ignored"); 38 + m_SucceedAssertions = serializedObject.FindProperty("succeedAfterAllAssertionsAreExecuted"); 39 + m_ExpectException = serializedObject.FindProperty("expectException"); 40 + m_ExpectedExceptionList = serializedObject.FindProperty("expectedExceptionList"); 41 + m_SucceedWhenExceptionIsThrown = serializedObject.FindProperty("succeedWhenExceptionIsThrown"); 42 + } 43 + 44 + public override void OnInspectorGUI() 45 + { 46 + var component = (TestComponent)target; 47 + 48 + if (component.dynamic) 49 + { 50 + if(GUILayout.Button("Reload dynamic tests")) 51 + { 52 + TestComponent.DestroyAllDynamicTests(); 53 + Selection.objects = new Object[0]; 54 + IntegrationTestsRunnerWindow.selectedInHierarchy = false; 55 + GUIUtility.ExitGUI(); 56 + return; 57 + } 58 + EditorGUILayout.HelpBox("This is a test generated from code. No changes in the component will be persisted.", MessageType.Info); 59 + } 60 + 61 + if (component.IsTestGroup()) 62 + { 63 + EditorGUI.BeginChangeCheck(); 64 + var newGroupName = EditorGUILayout.TextField(m_GUITestName, component.name); 65 + if (EditorGUI.EndChangeCheck()) component.name = newGroupName; 66 + 67 + serializedObject.ApplyModifiedProperties(); 68 + return; 69 + } 70 + 71 + serializedObject.Update(); 72 + 73 + EditorGUI.BeginDisabledGroup(serializedObject.isEditingMultipleObjects); 74 + 75 + EditorGUI.BeginChangeCheck(); 76 + var newName = EditorGUILayout.TextField(m_GUITestName, component.name); 77 + if (EditorGUI.EndChangeCheck()) component.name = newName; 78 + 79 + if (component.platformsToIgnore == null) 80 + { 81 + component.platformsToIgnore = GetListOfIgnoredPlatforms(Enum.GetNames(typeof(TestComponent.IncludedPlatforms)), (int)component.includedPlatforms); 82 + } 83 + 84 + var enumList = Enum.GetNames(typeof(RuntimePlatform)); 85 + var flags = GetFlagList(enumList, component.platformsToIgnore); 86 + flags = EditorGUILayout.MaskField(m_GUIIncludePlatforms, flags, enumList, EditorStyles.popup); 87 + var newList = GetListOfIgnoredPlatforms(enumList, flags); 88 + if (!component.dynamic) 89 + component.platformsToIgnore = newList; 90 + EditorGUI.EndDisabledGroup(); 91 + 92 + EditorGUILayout.PropertyField(m_Timeout, m_GUITimeout); 93 + EditorGUILayout.PropertyField(m_Ignored, m_GUIIgnore); 94 + EditorGUILayout.PropertyField(m_SucceedAssertions, m_GUISuccedOnAssertions); 95 + EditorGUILayout.PropertyField(m_ExpectException, m_GUIExpectException); 96 + 97 + EditorGUI.BeginDisabledGroup(!m_ExpectException.boolValue); 98 + EditorGUILayout.PropertyField(m_ExpectedExceptionList, m_GUIExpectExceptionList); 99 + EditorGUILayout.PropertyField(m_SucceedWhenExceptionIsThrown, m_GUISucceedWhenExceptionIsThrown); 100 + EditorGUI.EndDisabledGroup(); 101 + 102 + if (!component.dynamic) 103 + serializedObject.ApplyModifiedProperties(); 104 + if(GUI.changed) 105 + EditorApplication.MarkSceneDirty(); 106 + } 107 + 108 + private string[] GetListOfIgnoredPlatforms(string[] enumList, int flags) 109 + { 110 + var notSelectedPlatforms = new List<string>(); 111 + for (int i = 0; i < enumList.Length; i++) 112 + { 113 + var sel = (flags & (1 << i)) != 0; 114 + if (!sel) notSelectedPlatforms.Add(enumList[i]); 115 + } 116 + return notSelectedPlatforms.ToArray(); 117 + } 118 + 119 + private int GetFlagList(string[] enumList, string[] platformsToIgnore) 120 + { 121 + int flags = ~0; 122 + for (int i = 0; i < enumList.Length; i++) 123 + if (platformsToIgnore != null && platformsToIgnore.Any(s => s == enumList[i])) 124 + flags &= ~(1 << i); 125 + return flags; 126 + } 127 + } 128 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/Editor/TestComponentEditor.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 160889f21f4d5944b9f6fcaf9c33f684 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+16
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest.IntegrationTestRunner 6 + { 7 + public interface ITestRunnerCallback 8 + { 9 + void RunStarted(string platform, List<TestComponent> testsToRun); 10 + void RunFinished(List<TestResult> testResults); 11 + void AllScenesFinished(); 12 + void TestStarted(TestResult test); 13 + void TestFinished(TestResult test); 14 + void TestRunInterrupted(List<ITestComponent> testsNotRun); 15 + } 16 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ITestRunnerCallback.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 35af7d395e501a348ae1a0aa3c91dee4 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+176
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using System.Linq; 5 + using UnityEngine; 6 + 7 + public static class IntegrationTest 8 + { 9 + public const string passMessage = "IntegrationTest Pass"; 10 + public const string failMessage = "IntegrationTest Fail"; 11 + 12 + public static void Pass() 13 + { 14 + LogResult(passMessage); 15 + } 16 + 17 + public static void Pass(GameObject go) 18 + { 19 + LogResult(go, passMessage); 20 + } 21 + 22 + public static void Fail(string reason) 23 + { 24 + Fail(); 25 + if (!string.IsNullOrEmpty(reason)) Debug.Log(reason); 26 + } 27 + 28 + public static void Fail(GameObject go, string reason) 29 + { 30 + Fail(go); 31 + if (!string.IsNullOrEmpty(reason)) Debug.Log(reason); 32 + } 33 + 34 + public static void Fail() 35 + { 36 + LogResult(failMessage); 37 + } 38 + 39 + public static void Fail(GameObject go) 40 + { 41 + LogResult(go, failMessage); 42 + } 43 + 44 + public static void Assert(bool condition) 45 + { 46 + Assert(condition, ""); 47 + } 48 + 49 + public static void Assert(GameObject go, bool condition) 50 + { 51 + Assert(go, condition, ""); 52 + } 53 + 54 + public static void Assert(bool condition, string message) 55 + { 56 + if (!condition) 57 + Fail(message); 58 + } 59 + 60 + public static void Assert(GameObject go, bool condition, string message) 61 + { 62 + if (!condition) 63 + Fail(go, message); 64 + } 65 + 66 + private static void LogResult(string message) 67 + { 68 + Debug.Log(message); 69 + } 70 + 71 + private static void LogResult(GameObject go, string message) 72 + { 73 + Debug.Log(message + " (" + FindTestObject(go).name + ")", go); 74 + } 75 + 76 + private static GameObject FindTestObject(GameObject go) 77 + { 78 + var temp = go; 79 + while (temp.transform.parent != null) 80 + { 81 + if (temp.GetComponent("TestComponent") != null) 82 + return temp; 83 + temp = temp.transform.parent.gameObject; 84 + } 85 + return go; 86 + } 87 + 88 + #region Dynamic test attributes 89 + 90 + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 91 + public class ExcludePlatformAttribute : Attribute 92 + { 93 + public string[] platformsToExclude; 94 + 95 + public ExcludePlatformAttribute(params RuntimePlatform[] platformsToExclude) 96 + { 97 + this.platformsToExclude = platformsToExclude.Select(platform => platform.ToString()).ToArray(); 98 + } 99 + } 100 + 101 + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 102 + public class ExpectExceptions : Attribute 103 + { 104 + public string[] exceptionTypeNames; 105 + public bool succeedOnException; 106 + 107 + public ExpectExceptions() : this(false) 108 + { 109 + } 110 + 111 + public ExpectExceptions(bool succeedOnException) : this(succeedOnException, new string[0]) 112 + { 113 + } 114 + 115 + public ExpectExceptions(bool succeedOnException, params string[] exceptionTypeNames) 116 + { 117 + this.succeedOnException = succeedOnException; 118 + this.exceptionTypeNames = exceptionTypeNames; 119 + } 120 + 121 + public ExpectExceptions(bool succeedOnException, params Type[] exceptionTypes) 122 + : this(succeedOnException, exceptionTypes.Select(type => type.FullName).ToArray()) 123 + { 124 + } 125 + 126 + public ExpectExceptions(params string[] exceptionTypeNames) : this(false, exceptionTypeNames) 127 + { 128 + } 129 + 130 + public ExpectExceptions(params Type[] exceptionTypes) : this(false, exceptionTypes) 131 + { 132 + } 133 + } 134 + 135 + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 136 + public class IgnoreAttribute : Attribute 137 + { 138 + } 139 + 140 + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 141 + public class DynamicTestAttribute : Attribute 142 + { 143 + private readonly string m_SceneName; 144 + 145 + public DynamicTestAttribute(string sceneName) 146 + { 147 + if (sceneName.EndsWith(".unity")) 148 + sceneName = sceneName.Substring(0, sceneName.Length - ".unity".Length); 149 + m_SceneName = sceneName; 150 + } 151 + 152 + public bool IncludeOnScene(string sceneName) 153 + { 154 + var fileName = Path.GetFileNameWithoutExtension(sceneName); 155 + return fileName == m_SceneName; 156 + } 157 + } 158 + 159 + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 160 + public class SucceedWithAssertions : Attribute 161 + { 162 + } 163 + 164 + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 165 + public class TimeoutAttribute : Attribute 166 + { 167 + public float timeout; 168 + 169 + public TimeoutAttribute(float seconds) 170 + { 171 + timeout = seconds; 172 + } 173 + } 174 + 175 + #endregion 176 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTest.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: eb367bbc76e489443a4ebc8b0a8642f4 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+24
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.IO; 4 + using UnityEngine; 5 + 6 + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 7 + public class IntegrationTestAttribute : Attribute 8 + { 9 + private readonly string m_Path; 10 + 11 + public IntegrationTestAttribute(string path) 12 + { 13 + if (path.EndsWith(".unity")) 14 + path = path.Substring(0, path.Length - ".unity".Length); 15 + m_Path = path; 16 + } 17 + 18 + public bool IncludeOnScene(string scenePath) 19 + { 20 + if (scenePath == m_Path) return true; 21 + var fileName = Path.GetFileNameWithoutExtension(scenePath); 22 + return fileName == m_Path; 23 + } 24 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestAttribute.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: f1a5c61a06ed66e41a6ee1b5f88b5afd 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+109
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEngine; 5 + 6 + namespace UnityTest.IntegrationTestRunner 7 + { 8 + class IntegrationTestsProvider 9 + { 10 + internal Dictionary<ITestComponent, HashSet<ITestComponent>> testCollection = new Dictionary<ITestComponent, HashSet<ITestComponent>>(); 11 + internal ITestComponent currentTestGroup; 12 + internal IEnumerable<ITestComponent> testToRun; 13 + 14 + public IntegrationTestsProvider(IEnumerable<ITestComponent> tests) 15 + { 16 + testToRun = tests; 17 + foreach (var test in tests.OrderBy(component => component)) 18 + { 19 + if (test.IsTestGroup()) 20 + { 21 + throw new Exception(test.Name + " is test a group"); 22 + } 23 + AddTestToList(test); 24 + } 25 + if (currentTestGroup == null) 26 + { 27 + currentTestGroup = FindInnerTestGroup(TestComponent.NullTestComponent); 28 + } 29 + } 30 + 31 + private void AddTestToList(ITestComponent test) 32 + { 33 + var group = test.GetTestGroup(); 34 + if (!testCollection.ContainsKey(group)) 35 + testCollection.Add(group, new HashSet<ITestComponent>()); 36 + testCollection[group].Add(test); 37 + if (group == TestComponent.NullTestComponent) return; 38 + AddTestToList(group); 39 + } 40 + 41 + public ITestComponent GetNextTest() 42 + { 43 + var test = testCollection[currentTestGroup].First(); 44 + testCollection[currentTestGroup].Remove(test); 45 + test.EnableTest(true); 46 + return test; 47 + } 48 + 49 + public void FinishTest(ITestComponent test) 50 + { 51 + try 52 + { 53 + test.EnableTest(false); 54 + currentTestGroup = FindNextTestGroup(currentTestGroup); 55 + } 56 + catch (MissingReferenceException e) 57 + { 58 + Debug.LogException(e); 59 + } 60 + } 61 + 62 + private ITestComponent FindNextTestGroup(ITestComponent testGroup) 63 + { 64 + if (testGroup == null) 65 + throw new Exception ("No test left"); 66 + 67 + if (testCollection[testGroup].Any()) 68 + { 69 + testGroup.EnableTest(true); 70 + return FindInnerTestGroup(testGroup); 71 + } 72 + testCollection.Remove(testGroup); 73 + testGroup.EnableTest(false); 74 + 75 + var parentTestGroup = testGroup.GetTestGroup(); 76 + if (parentTestGroup == null) return null; 77 + 78 + testCollection[parentTestGroup].Remove(testGroup); 79 + return FindNextTestGroup(parentTestGroup); 80 + } 81 + 82 + private ITestComponent FindInnerTestGroup(ITestComponent group) 83 + { 84 + var innerGroups = testCollection[group]; 85 + foreach (var innerGroup in innerGroups) 86 + { 87 + if (!innerGroup.IsTestGroup()) continue; 88 + innerGroup.EnableTest(true); 89 + return FindInnerTestGroup(innerGroup); 90 + } 91 + return group; 92 + } 93 + 94 + public bool AnyTestsLeft() 95 + { 96 + return testCollection.Count != 0; 97 + } 98 + 99 + public List<ITestComponent> GetRemainingTests() 100 + { 101 + var remainingTests = new List<ITestComponent>(); 102 + foreach (var test in testCollection) 103 + { 104 + remainingTests.AddRange(test.Value); 105 + } 106 + return remainingTests; 107 + } 108 + } 109 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/IntegrationTestsProvider.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 21d32637b19ee51489062a66ad922193 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+112
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/NetworkResultSender.cs
··· 1 + #if !UNITY_METRO && (UNITY_PRO_LICENSE || !(UNITY_ANDROID || UNITY_IPHONE)) 2 + #define UTT_SOCKETS_SUPPORTED 3 + #endif 4 + using System; 5 + using System.Collections.Generic; 6 + using UnityEngine; 7 + using UnityTest.IntegrationTestRunner; 8 + 9 + #if UTT_SOCKETS_SUPPORTED 10 + using System.Net.Sockets; 11 + using System.Runtime.Serialization.Formatters.Binary; 12 + #endif 13 + 14 + namespace UnityTest 15 + { 16 + public class NetworkResultSender : ITestRunnerCallback 17 + { 18 + #if UTT_SOCKETS_SUPPORTED 19 + private readonly TimeSpan m_ConnectionTimeout = TimeSpan.FromSeconds(5); 20 + 21 + private readonly string m_Ip; 22 + private readonly int m_Port; 23 + #endif 24 + private bool m_LostConnection; 25 + 26 + public NetworkResultSender(string ip, int port) 27 + { 28 + #if UTT_SOCKETS_SUPPORTED 29 + m_Ip = ip; 30 + m_Port = port; 31 + #endif 32 + } 33 + 34 + private bool SendDTO(ResultDTO dto) 35 + { 36 + if (m_LostConnection) return false; 37 + #if UTT_SOCKETS_SUPPORTED 38 + try 39 + { 40 + using (var tcpClient = new TcpClient()) 41 + { 42 + var result = tcpClient.BeginConnect(m_Ip, m_Port, null, null); 43 + var success = result.AsyncWaitHandle.WaitOne(m_ConnectionTimeout); 44 + if (!success) 45 + { 46 + return false; 47 + } 48 + try 49 + { 50 + tcpClient.EndConnect(result); 51 + } 52 + catch (SocketException) 53 + { 54 + m_LostConnection = true; 55 + return false; 56 + } 57 + 58 + var bf = new DTOFormatter(); 59 + bf.Serialize(tcpClient.GetStream(), dto); 60 + tcpClient.GetStream().Close(); 61 + tcpClient.Close(); 62 + Debug.Log("Sent " + dto.messageType); 63 + } 64 + } 65 + catch (SocketException e) 66 + { 67 + Debug.LogException(e); 68 + m_LostConnection = true; 69 + return false; 70 + } 71 + #endif // if UTT_SOCKETS_SUPPORTED 72 + return true; 73 + } 74 + 75 + public bool Ping() 76 + { 77 + var result = SendDTO(ResultDTO.CreatePing()); 78 + m_LostConnection = false; 79 + return result; 80 + } 81 + 82 + public void RunStarted(string platform, List<TestComponent> testsToRun) 83 + { 84 + SendDTO(ResultDTO.CreateRunStarted()); 85 + } 86 + 87 + public void RunFinished(List<TestResult> testResults) 88 + { 89 + SendDTO(ResultDTO.CreateRunFinished(testResults)); 90 + } 91 + 92 + public void TestStarted(TestResult test) 93 + { 94 + SendDTO(ResultDTO.CreateTestStarted(test)); 95 + } 96 + 97 + public void TestFinished(TestResult test) 98 + { 99 + SendDTO(ResultDTO.CreateTestFinished(test)); 100 + } 101 + 102 + public void AllScenesFinished() 103 + { 104 + SendDTO (ResultDTO.CreateAllScenesFinished ()); 105 + } 106 + 107 + public void TestRunInterrupted(List<ITestComponent> testsNotRun) 108 + { 109 + RunFinished(new List<TestResult>()); 110 + } 111 + } 112 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/NetworkResultSender.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 80b91644bbbc487479429368d4e8d596 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+167
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ResultDTO.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + [Serializable] 8 + public class ResultDTO 9 + { 10 + public MessageType messageType; 11 + public int levelCount; 12 + public int loadedLevel; 13 + public string loadedLevelName; 14 + public string testName; 15 + public float testTimeout; 16 + public ITestResult testResult; 17 + 18 + private ResultDTO(MessageType messageType) 19 + { 20 + this.messageType = messageType; 21 + levelCount = Application.levelCount; 22 + loadedLevel = Application.loadedLevel; 23 + loadedLevelName = Application.loadedLevelName; 24 + } 25 + 26 + public enum MessageType : byte 27 + { 28 + Ping, 29 + RunStarted, 30 + RunFinished, 31 + TestStarted, 32 + TestFinished, 33 + RunInterrupted, 34 + AllScenesFinished 35 + } 36 + 37 + public static ResultDTO CreatePing() 38 + { 39 + var dto = new ResultDTO(MessageType.Ping); 40 + return dto; 41 + } 42 + 43 + public static ResultDTO CreateRunStarted() 44 + { 45 + var dto = new ResultDTO(MessageType.RunStarted); 46 + return dto; 47 + } 48 + 49 + public static ResultDTO CreateRunFinished(List<TestResult> testResults) 50 + { 51 + var dto = new ResultDTO(MessageType.RunFinished); 52 + return dto; 53 + } 54 + 55 + public static ResultDTO CreateTestStarted(TestResult test) 56 + { 57 + var dto = new ResultDTO(MessageType.TestStarted); 58 + dto.testName = test.FullName; 59 + dto.testTimeout = test.TestComponent.timeout; 60 + return dto; 61 + } 62 + 63 + public static ResultDTO CreateTestFinished(TestResult test) 64 + { 65 + var dto = new ResultDTO(MessageType.TestFinished); 66 + dto.testName = test.FullName; 67 + dto.testResult = GetSerializableTestResult(test); 68 + return dto; 69 + } 70 + 71 + public static ResultDTO CreateAllScenesFinished() 72 + { 73 + var dto = new ResultDTO(MessageType.AllScenesFinished); 74 + return dto; 75 + } 76 + 77 + private static ITestResult GetSerializableTestResult(TestResult test) 78 + { 79 + var str = new SerializableTestResult(); 80 + 81 + str.resultState = test.ResultState; 82 + str.message = test.messages; 83 + str.executed = test.Executed; 84 + str.name = test.Name; 85 + str.fullName = test.FullName; 86 + str.id = test.id; 87 + str.isSuccess = test.IsSuccess; 88 + str.duration = test.duration; 89 + str.stackTrace = test.stacktrace; 90 + str.isIgnored = test.IsIgnored; 91 + 92 + return str; 93 + } 94 + } 95 + 96 + #region SerializableTestResult 97 + [Serializable] 98 + internal class SerializableTestResult : ITestResult 99 + { 100 + public TestResultState resultState; 101 + public string message; 102 + public bool executed; 103 + public string name; 104 + public string fullName; 105 + public string id; 106 + public bool isSuccess; 107 + public double duration; 108 + public string stackTrace; 109 + public bool isIgnored; 110 + 111 + public TestResultState ResultState 112 + { 113 + get { return resultState; } 114 + } 115 + 116 + public string Message 117 + { 118 + get { return message; } 119 + } 120 + 121 + public string Logs 122 + { 123 + get { return null; } 124 + } 125 + 126 + public bool Executed 127 + { 128 + get { return executed; } 129 + } 130 + 131 + public string Name 132 + { 133 + get { return name; } 134 + } 135 + 136 + public string FullName 137 + { 138 + get { return fullName; } 139 + } 140 + 141 + public string Id 142 + { 143 + get { return id; } 144 + } 145 + 146 + public bool IsSuccess 147 + { 148 + get { return isSuccess; } 149 + } 150 + 151 + public double Duration 152 + { 153 + get { return duration; } 154 + } 155 + 156 + public string StackTrace 157 + { 158 + get { return stackTrace; } 159 + } 160 + 161 + public bool IsIgnored 162 + { 163 + get { return isIgnored; } 164 + } 165 + } 166 + #endregion 167 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/ResultDTO.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 37c772b6d1ba4274aa96c83710cb27e8 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+411
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using System.Reflection; 5 + using UnityEngine; 6 + 7 + #if UNITY_EDITOR 8 + using UnityEditor; 9 + #endif 10 + 11 + namespace UnityTest 12 + { 13 + public interface ITestComponent : IComparable<ITestComponent> 14 + { 15 + void EnableTest(bool enable); 16 + bool IsTestGroup(); 17 + GameObject gameObject { get; } 18 + string Name { get; } 19 + ITestComponent GetTestGroup(); 20 + bool IsExceptionExpected(string exceptionType); 21 + bool ShouldSucceedOnException(); 22 + double GetTimeout(); 23 + bool IsIgnored(); 24 + bool ShouldSucceedOnAssertions(); 25 + bool IsExludedOnThisPlatform(); 26 + } 27 + 28 + public class TestComponent : MonoBehaviour, ITestComponent 29 + { 30 + public static ITestComponent NullTestComponent = new NullTestComponentImpl(); 31 + 32 + public float timeout = 5; 33 + public bool ignored = false; 34 + public bool succeedAfterAllAssertionsAreExecuted = false; 35 + public bool expectException = false; 36 + public string expectedExceptionList = ""; 37 + public bool succeedWhenExceptionIsThrown = false; 38 + public IncludedPlatforms includedPlatforms = (IncludedPlatforms) ~0L; 39 + public string[] platformsToIgnore = null; 40 + 41 + public bool dynamic; 42 + public string dynamicTypeName; 43 + 44 + public bool IsExludedOnThisPlatform() 45 + { 46 + return platformsToIgnore != null && platformsToIgnore.Any(platform => platform == Application.platform.ToString()); 47 + } 48 + 49 + static bool IsAssignableFrom(Type a, Type b) 50 + { 51 + #if !UNITY_METRO 52 + return a.IsAssignableFrom(b); 53 + #else 54 + return false; 55 + #endif 56 + } 57 + 58 + public bool IsExceptionExpected(string exception) 59 + { 60 + exception = exception.Trim(); 61 + if (!expectException) 62 + return false; 63 + if(string.IsNullOrEmpty(expectedExceptionList.Trim())) 64 + return true; 65 + foreach (var expectedException in expectedExceptionList.Split(',').Select(e => e.Trim())) 66 + { 67 + if (exception == expectedException) 68 + return true; 69 + var exceptionType = Type.GetType(exception) ?? GetTypeByName(exception); 70 + var expectedExceptionType = Type.GetType(expectedException) ?? GetTypeByName(expectedException); 71 + if (exceptionType != null && expectedExceptionType != null && IsAssignableFrom(expectedExceptionType, exceptionType)) 72 + return true; 73 + } 74 + return false; 75 + } 76 + 77 + public bool ShouldSucceedOnException() 78 + { 79 + return succeedWhenExceptionIsThrown; 80 + } 81 + 82 + public double GetTimeout() 83 + { 84 + return timeout; 85 + } 86 + 87 + public bool IsIgnored() 88 + { 89 + return ignored; 90 + } 91 + 92 + public bool ShouldSucceedOnAssertions() 93 + { 94 + return succeedAfterAllAssertionsAreExecuted; 95 + } 96 + 97 + private static Type GetTypeByName(string className) 98 + { 99 + #if !UNITY_METRO 100 + return AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).FirstOrDefault(type => type.Name == className); 101 + #else 102 + return null; 103 + #endif 104 + } 105 + 106 + public void OnValidate() 107 + { 108 + if (timeout < 0.01f) timeout = 0.01f; 109 + } 110 + 111 + // Legacy 112 + [Flags] 113 + public enum IncludedPlatforms 114 + { 115 + WindowsEditor = 1 << 0, 116 + OSXEditor = 1 << 1, 117 + WindowsPlayer = 1 << 2, 118 + OSXPlayer = 1 << 3, 119 + LinuxPlayer = 1 << 4, 120 + MetroPlayerX86 = 1 << 5, 121 + MetroPlayerX64 = 1 << 6, 122 + MetroPlayerARM = 1 << 7, 123 + WindowsWebPlayer = 1 << 8, 124 + OSXWebPlayer = 1 << 9, 125 + Android = 1 << 10, 126 + // ReSharper disable once InconsistentNaming 127 + IPhonePlayer = 1 << 11, 128 + TizenPlayer = 1 << 12, 129 + WP8Player = 1 << 13, 130 + BB10Player = 1 << 14, 131 + NaCl = 1 << 15, 132 + PS3 = 1 << 16, 133 + XBOX360 = 1 << 17, 134 + WiiPlayer = 1 << 18, 135 + PSP2 = 1 << 19, 136 + PS4 = 1 << 20, 137 + PSMPlayer = 1 << 21, 138 + XboxOne = 1 << 22, 139 + } 140 + 141 + #region ITestComponent implementation 142 + 143 + public void EnableTest(bool enable) 144 + { 145 + if (enable && dynamic) 146 + { 147 + Type t = Type.GetType(dynamicTypeName); 148 + var s = gameObject.GetComponent(t) as MonoBehaviour; 149 + if (s != null) 150 + DestroyImmediate(s); 151 + 152 + gameObject.AddComponent(t); 153 + } 154 + 155 + if (gameObject.activeSelf != enable) gameObject.SetActive(enable); 156 + } 157 + 158 + public int CompareTo(ITestComponent obj) 159 + { 160 + if (obj == NullTestComponent) 161 + return 1; 162 + var result = gameObject.name.CompareTo(obj.gameObject.name); 163 + if (result == 0) 164 + result = gameObject.GetInstanceID().CompareTo(obj.gameObject.GetInstanceID()); 165 + return result; 166 + } 167 + 168 + public bool IsTestGroup() 169 + { 170 + for (int i = 0; i < gameObject.transform.childCount; i++) 171 + { 172 + var childTc = gameObject.transform.GetChild(i).GetComponent(typeof(TestComponent)); 173 + if (childTc != null) 174 + return true; 175 + } 176 + return false; 177 + } 178 + 179 + public string Name { get { return gameObject == null ? "" : gameObject.name; } } 180 + 181 + public ITestComponent GetTestGroup() 182 + { 183 + var parent = gameObject.transform.parent; 184 + if (parent == null) 185 + return NullTestComponent; 186 + return parent.GetComponent<TestComponent>(); 187 + } 188 + 189 + public override bool Equals(object o) 190 + { 191 + if (o is TestComponent) 192 + return this == (o as TestComponent); 193 + return false; 194 + } 195 + 196 + public override int GetHashCode() 197 + { 198 + return base.GetHashCode(); 199 + } 200 + 201 + public static bool operator ==(TestComponent a, TestComponent b) 202 + { 203 + if (ReferenceEquals(a, b)) 204 + return true; 205 + if (((object)a == null) || ((object)b == null)) 206 + return false; 207 + if (a.dynamic && b.dynamic) 208 + return a.dynamicTypeName == b.dynamicTypeName; 209 + if (a.dynamic || b.dynamic) 210 + return false; 211 + return a.gameObject == b.gameObject; 212 + } 213 + 214 + public static bool operator !=(TestComponent a, TestComponent b) 215 + { 216 + return !(a == b); 217 + } 218 + 219 + #endregion 220 + 221 + #region Static helpers 222 + 223 + public static TestComponent CreateDynamicTest(Type type) 224 + { 225 + var go = CreateTest(type.Name); 226 + go.hideFlags |= HideFlags.DontSave; 227 + go.SetActive(false); 228 + 229 + var tc = go.GetComponent<TestComponent>(); 230 + tc.dynamic = true; 231 + tc.dynamicTypeName = type.AssemblyQualifiedName; 232 + 233 + #if !UNITY_METRO 234 + foreach (var typeAttribute in type.GetCustomAttributes(false)) 235 + { 236 + if (typeAttribute is IntegrationTest.TimeoutAttribute) 237 + tc.timeout = (typeAttribute as IntegrationTest.TimeoutAttribute).timeout; 238 + else if (typeAttribute is IntegrationTest.IgnoreAttribute) 239 + tc.ignored = true; 240 + else if (typeAttribute is IntegrationTest.SucceedWithAssertions) 241 + tc.succeedAfterAllAssertionsAreExecuted = true; 242 + else if (typeAttribute is IntegrationTest.ExcludePlatformAttribute) 243 + tc.platformsToIgnore = (typeAttribute as IntegrationTest.ExcludePlatformAttribute).platformsToExclude; 244 + else if (typeAttribute is IntegrationTest.ExpectExceptions) 245 + { 246 + var attribute = (typeAttribute as IntegrationTest.ExpectExceptions); 247 + tc.expectException = true; 248 + tc.expectedExceptionList = string.Join(",", attribute.exceptionTypeNames); 249 + tc.succeedWhenExceptionIsThrown = attribute.succeedOnException; 250 + } 251 + } 252 + go.AddComponent(type); 253 + #endif // if !UNITY_METRO 254 + return tc; 255 + } 256 + 257 + public static GameObject CreateTest() 258 + { 259 + return CreateTest("New Test"); 260 + } 261 + 262 + private static GameObject CreateTest(string name) 263 + { 264 + var go = new GameObject(name); 265 + go.AddComponent<TestComponent>(); 266 + #if UNITY_EDITOR 267 + Undo.RegisterCreatedObjectUndo(go, "Created test"); 268 + #endif 269 + return go; 270 + } 271 + 272 + public static List<TestComponent> FindAllTestsOnScene() 273 + { 274 + var tests = Resources.FindObjectsOfTypeAll (typeof(TestComponent)).Cast<TestComponent> (); 275 + #if UNITY_EDITOR 276 + tests = tests.Where( t => {var p = PrefabUtility.GetPrefabType(t); return p != PrefabType.Prefab && p != PrefabType.ModelPrefab;} ); 277 + 278 + #endif 279 + return tests.ToList (); 280 + } 281 + 282 + public static List<TestComponent> FindAllTopTestsOnScene() 283 + { 284 + return FindAllTestsOnScene().Where(component => component.gameObject.transform.parent == null).ToList(); 285 + } 286 + 287 + public static List<TestComponent> FindAllDynamicTestsOnScene() 288 + { 289 + return FindAllTestsOnScene().Where(t => t.dynamic).ToList(); 290 + } 291 + 292 + public static void DestroyAllDynamicTests() 293 + { 294 + foreach (var dynamicTestComponent in FindAllDynamicTestsOnScene()) 295 + DestroyImmediate(dynamicTestComponent.gameObject); 296 + } 297 + 298 + public static void DisableAllTests() 299 + { 300 + foreach (var t in FindAllTestsOnScene()) t.EnableTest(false); 301 + } 302 + 303 + public static bool AnyTestsOnScene() 304 + { 305 + return FindAllTestsOnScene().Any(); 306 + } 307 + 308 + public static bool AnyDynamicTestForCurrentScene() 309 + { 310 + #if UNITY_EDITOR 311 + return TestComponent.GetTypesWithHelpAttribute(EditorApplication.currentScene).Any(); 312 + #else 313 + return TestComponent.GetTypesWithHelpAttribute(Application.loadedLevelName).Any(); 314 + #endif 315 + } 316 + 317 + #endregion 318 + 319 + private sealed class NullTestComponentImpl : ITestComponent 320 + { 321 + public int CompareTo(ITestComponent other) 322 + { 323 + if (other == this) return 0; 324 + return -1; 325 + } 326 + 327 + public void EnableTest(bool enable) 328 + { 329 + } 330 + 331 + public bool IsTestGroup() 332 + { 333 + throw new NotImplementedException(); 334 + } 335 + 336 + public GameObject gameObject { get; private set; } 337 + public string Name { get { return ""; } } 338 + 339 + public ITestComponent GetTestGroup() 340 + { 341 + return null; 342 + } 343 + 344 + public bool IsExceptionExpected(string exceptionType) 345 + { 346 + throw new NotImplementedException(); 347 + } 348 + 349 + public bool ShouldSucceedOnException() 350 + { 351 + throw new NotImplementedException(); 352 + } 353 + 354 + public double GetTimeout() 355 + { 356 + throw new NotImplementedException(); 357 + } 358 + 359 + public bool IsIgnored() 360 + { 361 + throw new NotImplementedException(); 362 + } 363 + 364 + public bool ShouldSucceedOnAssertions() 365 + { 366 + throw new NotImplementedException(); 367 + } 368 + 369 + public bool IsExludedOnThisPlatform() 370 + { 371 + throw new NotImplementedException(); 372 + } 373 + } 374 + 375 + public static IEnumerable<Type> GetTypesWithHelpAttribute(string sceneName) 376 + { 377 + #if !UNITY_METRO 378 + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) 379 + { 380 + Type[] types = null; 381 + 382 + try 383 + { 384 + types = assembly.GetTypes(); 385 + } 386 + catch (ReflectionTypeLoadException ex) 387 + { 388 + Debug.LogError("Failed to load types from: " + assembly.FullName); 389 + foreach (Exception loadEx in ex.LoaderExceptions) 390 + Debug.LogException(loadEx); 391 + } 392 + 393 + if (types == null) 394 + continue; 395 + 396 + foreach (Type type in types) 397 + { 398 + var attributes = type.GetCustomAttributes(typeof(IntegrationTest.DynamicTestAttribute), true); 399 + if (attributes.Length == 1) 400 + { 401 + var a = attributes.Single() as IntegrationTest.DynamicTestAttribute; 402 + if (a.IncludeOnScene(sceneName)) yield return type; 403 + } 404 + } 405 + } 406 + #else // if !UNITY_METRO 407 + yield break; 408 + #endif // if !UNITY_METRO 409 + } 410 + } 411 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestComponent.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: b1dba0b27b0864740a8720e920aa88c0 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+141
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + [Serializable] 8 + public class TestResult : ITestResult, IComparable<TestResult> 9 + { 10 + private readonly GameObject m_Go; 11 + private string m_Name; 12 + public ResultType resultType = ResultType.NotRun; 13 + public double duration; 14 + public string messages; 15 + public string stacktrace; 16 + public string id; 17 + public bool dynamicTest; 18 + 19 + public TestComponent TestComponent; 20 + 21 + public GameObject GameObject 22 + { 23 + get { return m_Go; } 24 + } 25 + 26 + public TestResult(TestComponent testComponent) 27 + { 28 + TestComponent = testComponent; 29 + m_Go = testComponent.gameObject; 30 + id = testComponent.gameObject.GetInstanceID().ToString(); 31 + dynamicTest = testComponent.dynamic; 32 + 33 + if (m_Go != null) m_Name = m_Go.name; 34 + 35 + if (dynamicTest) 36 + id = testComponent.dynamicTypeName; 37 + } 38 + 39 + public void Update(TestResult oldResult) 40 + { 41 + resultType = oldResult.resultType; 42 + duration = oldResult.duration; 43 + messages = oldResult.messages; 44 + stacktrace = oldResult.stacktrace; 45 + } 46 + 47 + public enum ResultType 48 + { 49 + Success, 50 + Failed, 51 + Timeout, 52 + NotRun, 53 + FailedException, 54 + Ignored 55 + } 56 + 57 + public void Reset() 58 + { 59 + resultType = ResultType.NotRun; 60 + duration = 0f; 61 + messages = ""; 62 + stacktrace = ""; 63 + } 64 + 65 + #region ITestResult implementation 66 + public TestResultState ResultState { 67 + get 68 + { 69 + switch (resultType) 70 + { 71 + case ResultType.Success: return TestResultState.Success; 72 + case ResultType.Failed: return TestResultState.Failure; 73 + case ResultType.FailedException: return TestResultState.Error; 74 + case ResultType.Ignored: return TestResultState.Ignored; 75 + case ResultType.NotRun: return TestResultState.Skipped; 76 + case ResultType.Timeout: return TestResultState.Cancelled; 77 + default: throw new Exception(); 78 + } 79 + } 80 + } 81 + public string Message { get { return messages; } } 82 + public string Logs { get { return null; } } 83 + public bool Executed { get { return resultType != ResultType.NotRun; } } 84 + public string Name { get { if (m_Go != null) m_Name = m_Go.name; return m_Name; } } 85 + public string Id { get { return id; } } 86 + public bool IsSuccess { get { return resultType == ResultType.Success; } } 87 + public bool IsTimeout { get { return resultType == ResultType.Timeout; } } 88 + public double Duration { get { return duration; } } 89 + public string StackTrace { get { return stacktrace; } } 90 + public string FullName { 91 + get 92 + { 93 + var fullName = Name; 94 + if (m_Go != null) 95 + { 96 + var tempGo = m_Go.transform.parent; 97 + while (tempGo != null) 98 + { 99 + fullName = tempGo.name + "." + fullName; 100 + tempGo = tempGo.transform.parent; 101 + } 102 + } 103 + return fullName; 104 + } 105 + } 106 + 107 + public bool IsIgnored { get { return resultType == ResultType.Ignored; } } 108 + public bool IsFailure 109 + { 110 + get 111 + { 112 + return resultType == ResultType.Failed 113 + || resultType == ResultType.FailedException 114 + || resultType == ResultType.Timeout; 115 + } 116 + } 117 + #endregion 118 + 119 + #region IComparable, GetHashCode and Equals implementation 120 + public override int GetHashCode() 121 + { 122 + return id.GetHashCode(); 123 + } 124 + 125 + public int CompareTo(TestResult other) 126 + { 127 + var result = Name.CompareTo(other.Name); 128 + if (result == 0) 129 + result = m_Go.GetInstanceID().CompareTo(other.m_Go.GetInstanceID()); 130 + return result; 131 + } 132 + 133 + public override bool Equals(object obj) 134 + { 135 + if (obj is TestResult) 136 + return GetHashCode() == obj.GetHashCode(); 137 + return base.Equals(obj); 138 + } 139 + #endregion 140 + } 141 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResult.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 68740a702763aaa4594e8319a05ae0d3 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+83
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using System.Linq; 4 + using UnityEngine; 5 + 6 + public class TestResultRenderer 7 + { 8 + private static class Styles 9 + { 10 + public static readonly GUIStyle SucceedLabelStyle; 11 + public static readonly GUIStyle FailedLabelStyle; 12 + public static readonly GUIStyle FailedMessagesStyle; 13 + 14 + static Styles() 15 + { 16 + SucceedLabelStyle = new GUIStyle("label"); 17 + SucceedLabelStyle.normal.textColor = Color.green; 18 + SucceedLabelStyle.fontSize = 48; 19 + 20 + FailedLabelStyle = new GUIStyle("label"); 21 + FailedLabelStyle.normal.textColor = Color.red; 22 + FailedLabelStyle.fontSize = 32; 23 + 24 + FailedMessagesStyle = new GUIStyle("label"); 25 + FailedMessagesStyle.wordWrap = false; 26 + FailedMessagesStyle.richText = true; 27 + } 28 + } 29 + private readonly Dictionary<string, List<ITestResult>> m_TestCollection = new Dictionary<string, List<ITestResult>>(); 30 + 31 + private bool m_ShowResults; 32 + Vector2 m_ScrollPosition; 33 + private int m_FailureCount; 34 + 35 + public void ShowResults() 36 + { 37 + m_ShowResults = true; 38 + Cursor.visible = true; 39 + } 40 + 41 + public void AddResults(string sceneName, ITestResult result) 42 + { 43 + if (!m_TestCollection.ContainsKey(sceneName)) 44 + m_TestCollection.Add(sceneName, new List<ITestResult>()); 45 + m_TestCollection[sceneName].Add(result); 46 + if (result.Executed && !result.IsSuccess) 47 + m_FailureCount++; 48 + } 49 + 50 + public void Draw() 51 + { 52 + if (!m_ShowResults) return; 53 + if (m_TestCollection.Count == 0) 54 + { 55 + GUILayout.Label("All test succeeded", Styles.SucceedLabelStyle, GUILayout.Width(600)); 56 + } 57 + else 58 + { 59 + int count = m_TestCollection.Sum (testGroup => testGroup.Value.Count); 60 + GUILayout.Label(count + " tests failed!", Styles.FailedLabelStyle); 61 + 62 + m_ScrollPosition = GUILayout.BeginScrollView(m_ScrollPosition, GUILayout.ExpandWidth(true)); 63 + var text = ""; 64 + foreach (var testGroup in m_TestCollection) 65 + { 66 + text += "<b><size=18>" + testGroup.Key + "</size></b>\n"; 67 + text += string.Join("\n", testGroup.Value 68 + .Where(result => !result.IsSuccess) 69 + .Select(result => result.Name + " " + result.ResultState + "\n" + result.Message) 70 + .ToArray()); 71 + } 72 + GUILayout.TextArea(text, Styles.FailedMessagesStyle); 73 + GUILayout.EndScrollView(); 74 + } 75 + if (GUILayout.Button("Close")) 76 + Application.Quit(); 77 + } 78 + 79 + public int FailureCount() 80 + { 81 + return m_FailureCount; 82 + } 83 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestResultRenderer.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 7ae9d3b4b57cae343b7ff360f9deb628 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+422
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs
··· 1 + // #define IMITATE_BATCH_MODE //uncomment if you want to imitate batch mode behaviour in non-batch mode mode run 2 + 3 + using System; 4 + using System.Collections; 5 + using System.Collections.Generic; 6 + using System.Linq; 7 + using System.Reflection; 8 + using UnityEngine; 9 + using UnityTest.IntegrationTestRunner; 10 + using System.IO; 11 + 12 + namespace UnityTest 13 + { 14 + [Serializable] 15 + public class TestRunner : MonoBehaviour 16 + { 17 + static private int TestSceneNumber = 0; 18 + static private readonly TestResultRenderer k_ResultRenderer = new TestResultRenderer(); 19 + 20 + public TestComponent currentTest; 21 + private List<TestResult> m_ResultList = new List<TestResult>(); 22 + private List<TestComponent> m_TestComponents; 23 + 24 + public bool isInitializedByRunner 25 + { 26 + get 27 + { 28 + #if !IMITATE_BATCH_MODE 29 + if (Application.isEditor && !IsBatchMode()) 30 + return true; 31 + #endif 32 + return false; 33 + } 34 + } 35 + 36 + private double m_StartTime; 37 + private bool m_ReadyToRun; 38 + 39 + private string m_TestMessages; 40 + private string m_Stacktrace; 41 + private TestState m_TestState = TestState.Running; 42 + 43 + private TestRunnerConfigurator m_Configurator; 44 + 45 + public TestRunnerCallbackList TestRunnerCallback = new TestRunnerCallbackList(); 46 + private IntegrationTestsProvider m_TestsProvider; 47 + 48 + private const string k_Prefix = "IntegrationTest"; 49 + private const string k_StartedMessage = k_Prefix + " Started"; 50 + private const string k_FinishedMessage = k_Prefix + " Finished"; 51 + private const string k_TimeoutMessage = k_Prefix + " Timeout"; 52 + private const string k_FailedMessage = k_Prefix + " Failed"; 53 + private const string k_FailedExceptionMessage = k_Prefix + " Failed with exception"; 54 + private const string k_IgnoredMessage = k_Prefix + " Ignored"; 55 + private const string k_InterruptedMessage = k_Prefix + " Run interrupted"; 56 + 57 + 58 + public void Awake() 59 + { 60 + m_Configurator = new TestRunnerConfigurator(); 61 + if (isInitializedByRunner) return; 62 + TestComponent.DisableAllTests(); 63 + } 64 + 65 + public void Start() 66 + { 67 + if (isInitializedByRunner) return; 68 + 69 + if (m_Configurator.sendResultsOverNetwork) 70 + { 71 + var nrs = m_Configurator.ResolveNetworkConnection(); 72 + if (nrs != null) 73 + TestRunnerCallback.Add(nrs); 74 + } 75 + 76 + TestComponent.DestroyAllDynamicTests(); 77 + var dynamicTestTypes = TestComponent.GetTypesWithHelpAttribute(Application.loadedLevelName); 78 + foreach (var dynamicTestType in dynamicTestTypes) 79 + TestComponent.CreateDynamicTest(dynamicTestType); 80 + 81 + var tests = TestComponent.FindAllTestsOnScene(); 82 + 83 + InitRunner(tests, dynamicTestTypes.Select(type => type.AssemblyQualifiedName).ToList()); 84 + } 85 + 86 + public void InitRunner(List<TestComponent> tests, List<string> dynamicTestsToRun) 87 + { 88 + Application.logMessageReceived += LogHandler; 89 + 90 + // Init dynamic tests 91 + foreach (var typeName in dynamicTestsToRun) 92 + { 93 + var t = Type.GetType(typeName); 94 + if (t == null) continue; 95 + var scriptComponents = Resources.FindObjectsOfTypeAll(t) as MonoBehaviour[]; 96 + if (scriptComponents.Length == 0) 97 + { 98 + Debug.LogWarning(t + " not found. Skipping."); 99 + continue; 100 + } 101 + if (scriptComponents.Length > 1) Debug.LogWarning("Multiple GameObjects refer to " + typeName); 102 + tests.Add(scriptComponents.First().GetComponent<TestComponent>()); 103 + } 104 + // create test structure 105 + m_TestComponents = ParseListForGroups(tests).ToList(); 106 + // create results for tests 107 + m_ResultList = m_TestComponents.Select(component => new TestResult(component)).ToList(); 108 + // init test provider 109 + m_TestsProvider = new IntegrationTestsProvider(m_ResultList.Select(result => result.TestComponent as ITestComponent)); 110 + m_ReadyToRun = true; 111 + } 112 + 113 + private static IEnumerable<TestComponent> ParseListForGroups(IEnumerable<TestComponent> tests) 114 + { 115 + var results = new HashSet<TestComponent>(); 116 + foreach (var testResult in tests) 117 + { 118 + if (testResult.IsTestGroup()) 119 + { 120 + var childrenTestResult = testResult.gameObject.GetComponentsInChildren(typeof(TestComponent), true) 121 + .Where(t => t != testResult) 122 + .Cast<TestComponent>() 123 + .ToArray(); 124 + foreach (var result in childrenTestResult) 125 + { 126 + if (!result.IsTestGroup()) 127 + results.Add(result); 128 + } 129 + continue; 130 + } 131 + results.Add(testResult); 132 + } 133 + return results; 134 + } 135 + 136 + public void Update() 137 + { 138 + if (m_ReadyToRun && Time.frameCount > 1) 139 + { 140 + m_ReadyToRun = false; 141 + StartCoroutine("StateMachine"); 142 + } 143 + } 144 + 145 + public void OnDestroy() 146 + { 147 + if (currentTest != null) 148 + { 149 + var testResult = m_ResultList.Single(result => result.TestComponent == currentTest); 150 + testResult.messages += "Test run interrupted (crash?)"; 151 + LogMessage(k_InterruptedMessage); 152 + FinishTest(TestResult.ResultType.Failed); 153 + } 154 + if (currentTest != null || (m_TestsProvider != null && m_TestsProvider.AnyTestsLeft())) 155 + { 156 + var remainingTests = m_TestsProvider.GetRemainingTests(); 157 + TestRunnerCallback.TestRunInterrupted(remainingTests.ToList()); 158 + } 159 + Application.logMessageReceived -= LogHandler; 160 + } 161 + 162 + private void LogHandler(string condition, string stacktrace, LogType type) 163 + { 164 + if (!condition.StartsWith(k_StartedMessage) && !condition.StartsWith(k_FinishedMessage)) 165 + { 166 + var msg = condition; 167 + if (msg.StartsWith(k_Prefix)) msg = msg.Substring(k_Prefix.Length + 1); 168 + if (currentTest != null && msg.EndsWith("(" + currentTest.name + ')')) msg = msg.Substring(0, msg.LastIndexOf('(')); 169 + m_TestMessages += msg + "\n"; 170 + } 171 + switch (type) 172 + { 173 + case LogType.Exception: 174 + { 175 + var exceptionType = condition.Substring(0, condition.IndexOf(':')); 176 + if (currentTest != null && currentTest.IsExceptionExpected(exceptionType)) 177 + { 178 + m_TestMessages += exceptionType + " was expected\n"; 179 + if (currentTest.ShouldSucceedOnException()) 180 + { 181 + m_TestState = TestState.Success; 182 + } 183 + } 184 + else 185 + { 186 + m_TestState = TestState.Exception; 187 + m_Stacktrace = stacktrace; 188 + } 189 + } 190 + break; 191 + case LogType.Assert: 192 + case LogType.Error: 193 + m_TestState = TestState.Failure; 194 + m_Stacktrace = stacktrace; 195 + break; 196 + case LogType.Log: 197 + if (m_TestState == TestState.Running && condition.StartsWith(IntegrationTest.passMessage)) 198 + { 199 + m_TestState = TestState.Success; 200 + } 201 + if (condition.StartsWith(IntegrationTest.failMessage)) 202 + { 203 + m_TestState = TestState.Failure; 204 + } 205 + break; 206 + } 207 + } 208 + 209 + public IEnumerator StateMachine() 210 + { 211 + TestRunnerCallback.RunStarted(Application.platform.ToString(), m_TestComponents); 212 + while (true) 213 + { 214 + if (!m_TestsProvider.AnyTestsLeft() && currentTest == null) 215 + { 216 + FinishTestRun(); 217 + yield break; 218 + } 219 + if (currentTest == null) 220 + { 221 + StartNewTest(); 222 + } 223 + if (currentTest != null) 224 + { 225 + if (m_TestState == TestState.Running) 226 + { 227 + if(currentTest.ShouldSucceedOnAssertions()) 228 + { 229 + var assertionsToCheck = currentTest.gameObject.GetComponentsInChildren<AssertionComponent>().Where(a => a.enabled).ToArray(); 230 + if (assertionsToCheck.Any () && assertionsToCheck.All(a => a.checksPerformed > 0)) 231 + { 232 + IntegrationTest.Pass(currentTest.gameObject); 233 + m_TestState = TestState.Success; 234 + } 235 + } 236 + if (currentTest != null && Time.time > m_StartTime + currentTest.GetTimeout()) 237 + { 238 + m_TestState = TestState.Timeout; 239 + } 240 + } 241 + 242 + switch (m_TestState) 243 + { 244 + case TestState.Success: 245 + LogMessage(k_FinishedMessage); 246 + FinishTest(TestResult.ResultType.Success); 247 + break; 248 + case TestState.Failure: 249 + LogMessage(k_FailedMessage); 250 + FinishTest(TestResult.ResultType.Failed); 251 + break; 252 + case TestState.Exception: 253 + LogMessage(k_FailedExceptionMessage); 254 + FinishTest(TestResult.ResultType.FailedException); 255 + break; 256 + case TestState.Timeout: 257 + LogMessage(k_TimeoutMessage); 258 + FinishTest(TestResult.ResultType.Timeout); 259 + break; 260 + case TestState.Ignored: 261 + LogMessage(k_IgnoredMessage); 262 + FinishTest(TestResult.ResultType.Ignored); 263 + break; 264 + } 265 + } 266 + yield return null; 267 + } 268 + } 269 + 270 + private void LogMessage(string message) 271 + { 272 + if (currentTest != null) 273 + Debug.Log(message + " (" + currentTest.Name + ")", currentTest.gameObject); 274 + else 275 + Debug.Log(message); 276 + } 277 + 278 + private void FinishTestRun() 279 + { 280 + PrintResultToLog(); 281 + TestRunnerCallback.RunFinished(m_ResultList); 282 + LoadNextLevelOrQuit(); 283 + } 284 + 285 + private void PrintResultToLog() 286 + { 287 + var resultString = ""; 288 + resultString += "Passed: " + m_ResultList.Count(t => t.IsSuccess); 289 + if (m_ResultList.Any(result => result.IsFailure)) 290 + { 291 + resultString += " Failed: " + m_ResultList.Count(t => t.IsFailure); 292 + Debug.Log("Failed tests: " + string.Join(", ", m_ResultList.Where(t => t.IsFailure).Select(result => result.Name).ToArray())); 293 + } 294 + if (m_ResultList.Any(result => result.IsIgnored)) 295 + { 296 + resultString += " Ignored: " + m_ResultList.Count(t => t.IsIgnored); 297 + Debug.Log("Ignored tests: " + string.Join(", ", 298 + m_ResultList.Where(t => t.IsIgnored).Select(result => result.Name).ToArray())); 299 + } 300 + Debug.Log(resultString); 301 + } 302 + 303 + private void LoadNextLevelOrQuit() 304 + { 305 + if (isInitializedByRunner) return; 306 + 307 + 308 + TestSceneNumber += 1; 309 + string testScene = m_Configurator.GetIntegrationTestScenes (TestSceneNumber); 310 + 311 + if (testScene != null) 312 + Application.LoadLevel(Path.GetFileNameWithoutExtension(testScene)); 313 + else 314 + { 315 + TestRunnerCallback.AllScenesFinished(); 316 + k_ResultRenderer.ShowResults(); 317 + if (m_Configurator.isBatchRun && m_Configurator.sendResultsOverNetwork) 318 + Application.Quit(); 319 + } 320 + } 321 + 322 + public void OnGUI() 323 + { 324 + k_ResultRenderer.Draw(); 325 + } 326 + 327 + private void StartNewTest() 328 + { 329 + m_TestMessages = ""; 330 + m_Stacktrace = ""; 331 + m_TestState = TestState.Running; 332 + 333 + m_StartTime = Time.time; 334 + currentTest = m_TestsProvider.GetNextTest() as TestComponent; 335 + 336 + var testResult = m_ResultList.Single(result => result.TestComponent == currentTest); 337 + 338 + if (currentTest != null && currentTest.IsExludedOnThisPlatform()) 339 + { 340 + m_TestState = TestState.Ignored; 341 + Debug.Log(currentTest.gameObject.name + " is excluded on this platform"); 342 + } 343 + 344 + // don't ignore test if user initiated it from the runner and it's the only test that is being run 345 + if (currentTest != null 346 + && (currentTest.IsIgnored() 347 + && !(isInitializedByRunner && m_ResultList.Count == 1))) 348 + m_TestState = TestState.Ignored; 349 + 350 + LogMessage(k_StartedMessage); 351 + TestRunnerCallback.TestStarted(testResult); 352 + } 353 + 354 + private void FinishTest(TestResult.ResultType result) 355 + { 356 + m_TestsProvider.FinishTest(currentTest); 357 + var testResult = m_ResultList.Single(t => t.GameObject == currentTest.gameObject); 358 + testResult.resultType = result; 359 + testResult.duration = Time.time - m_StartTime; 360 + testResult.messages = m_TestMessages; 361 + testResult.stacktrace = m_Stacktrace; 362 + TestRunnerCallback.TestFinished(testResult); 363 + currentTest = null; 364 + if (!testResult.IsSuccess 365 + && testResult.Executed 366 + && !testResult.IsIgnored) k_ResultRenderer.AddResults(Application.loadedLevelName, testResult); 367 + } 368 + 369 + #region Test Runner Helpers 370 + 371 + public static TestRunner GetTestRunner() 372 + { 373 + TestRunner testRunnerComponent = null; 374 + var testRunnerComponents = Resources.FindObjectsOfTypeAll(typeof(TestRunner)); 375 + 376 + if (testRunnerComponents.Count() > 1) 377 + foreach (var t in testRunnerComponents) DestroyImmediate(((TestRunner)t).gameObject); 378 + else if (!testRunnerComponents.Any()) 379 + testRunnerComponent = Create().GetComponent<TestRunner>(); 380 + else 381 + testRunnerComponent = testRunnerComponents.Single() as TestRunner; 382 + 383 + return testRunnerComponent; 384 + } 385 + 386 + private static GameObject Create() 387 + { 388 + var runner = new GameObject("TestRunner"); 389 + runner.AddComponent<TestRunner>(); 390 + Debug.Log("Created Test Runner"); 391 + return runner; 392 + } 393 + 394 + private static bool IsBatchMode() 395 + { 396 + #if !UNITY_METRO 397 + const string internalEditorUtilityClassName = "UnityEditorInternal.InternalEditorUtility, UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"; 398 + 399 + var t = Type.GetType(internalEditorUtilityClassName, false); 400 + if (t == null) return false; 401 + 402 + const string inBatchModeProperty = "inBatchMode"; 403 + var prop = t.GetProperty(inBatchModeProperty); 404 + return (bool)prop.GetValue(null, null); 405 + #else // if !UNITY_METRO 406 + return false; 407 + #endif // if !UNITY_METRO 408 + } 409 + 410 + #endregion 411 + 412 + enum TestState 413 + { 414 + Running, 415 + Success, 416 + Failure, 417 + Exception, 418 + Timeout, 419 + Ignored 420 + } 421 + } 422 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunner.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 5c3afc1c624179749bcdecf7b0224902 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+69
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest.IntegrationTestRunner 6 + { 7 + public class TestRunnerCallbackList : ITestRunnerCallback 8 + { 9 + private readonly List<ITestRunnerCallback> m_CallbackList = new List<ITestRunnerCallback>(); 10 + 11 + public void Add(ITestRunnerCallback callback) 12 + { 13 + m_CallbackList.Add(callback); 14 + } 15 + 16 + public void Remove(ITestRunnerCallback callback) 17 + { 18 + m_CallbackList.Remove(callback); 19 + } 20 + 21 + public void RunStarted(string platform, List<TestComponent> testsToRun) 22 + { 23 + foreach (var unitTestRunnerCallback in m_CallbackList) 24 + { 25 + unitTestRunnerCallback.RunStarted(platform, testsToRun); 26 + } 27 + } 28 + 29 + public void RunFinished(List<TestResult> testResults) 30 + { 31 + foreach (var unitTestRunnerCallback in m_CallbackList) 32 + { 33 + unitTestRunnerCallback.RunFinished(testResults); 34 + } 35 + } 36 + 37 + public void AllScenesFinished() 38 + { 39 + foreach (var unitTestRunnerCallback in m_CallbackList) 40 + { 41 + unitTestRunnerCallback.AllScenesFinished(); 42 + } 43 + } 44 + 45 + public void TestStarted(TestResult test) 46 + { 47 + foreach (var unitTestRunnerCallback in m_CallbackList) 48 + { 49 + unitTestRunnerCallback.TestStarted(test); 50 + } 51 + } 52 + 53 + public void TestFinished(TestResult test) 54 + { 55 + foreach (var unitTestRunnerCallback in m_CallbackList) 56 + { 57 + unitTestRunnerCallback.TestFinished(test); 58 + } 59 + } 60 + 61 + public void TestRunInterrupted(List<ITestComponent> testsNotRun) 62 + { 63 + foreach (var unitTestRunnerCallback in m_CallbackList) 64 + { 65 + unitTestRunnerCallback.TestRunInterrupted(testsNotRun); 66 + } 67 + } 68 + } 69 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerCallbackList.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 7729da83f7c08d244b5788c870a93780 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+197
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerConfigurator.cs
··· 1 + #if !UNITY_METRO && !UNITY_WEBPLAYER && (UNITY_PRO_LICENSE || !(UNITY_ANDROID || UNITY_IPHONE)) 2 + #define UTT_SOCKETS_SUPPORTED 3 + #endif 4 + using System; 5 + using System.Collections.Generic; 6 + using System.IO; 7 + using System.Linq; 8 + using System.Threading; 9 + using UnityEngine; 10 + using UnityTest.IntegrationTestRunner; 11 + #if UTT_SOCKETS_SUPPORTED 12 + using System.Net; 13 + using System.Net.Sockets; 14 + using System.Net.NetworkInformation; 15 + #endif 16 + 17 + #if UNITY_EDITOR 18 + using UnityEditorInternal; 19 + #endif 20 + 21 + namespace UnityTest 22 + { 23 + public class TestRunnerConfigurator 24 + { 25 + public static string integrationTestsNetwork = "networkconfig.txt"; 26 + public static string batchRunFileMarker = "batchrun.txt"; 27 + public static string testScenesToRun = "testscenes.txt"; 28 + 29 + public bool isBatchRun { get; private set; } 30 + 31 + public bool sendResultsOverNetwork { get; private set; } 32 + 33 + #if UTT_SOCKETS_SUPPORTED 34 + private readonly List<IPEndPoint> m_IPEndPointList = new List<IPEndPoint>(); 35 + #endif 36 + 37 + public TestRunnerConfigurator() 38 + { 39 + CheckForBatchMode(); 40 + CheckForSendingResultsOverNetwork(); 41 + } 42 + 43 + public string GetIntegrationTestScenes(int testSceneNum) 44 + { 45 + string text; 46 + if (Application.isEditor) 47 + text = GetTextFromTempFile(testScenesToRun); 48 + else 49 + text = GetTextFromTextAsset(testScenesToRun); 50 + 51 + List<string> sceneList = new List<string>(); 52 + foreach (var line in text.Split(new[] {'\n'}, StringSplitOptions.RemoveEmptyEntries)) 53 + { 54 + sceneList.Add(line.ToString()); 55 + } 56 + 57 + if (testSceneNum < sceneList.Count) 58 + return sceneList.ElementAt(testSceneNum); 59 + else 60 + return null; 61 + } 62 + 63 + private void CheckForSendingResultsOverNetwork() 64 + { 65 + #if UTT_SOCKETS_SUPPORTED 66 + string text; 67 + if (Application.isEditor) 68 + text = GetTextFromTempFile(integrationTestsNetwork); 69 + else 70 + text = GetTextFromTextAsset(integrationTestsNetwork); 71 + 72 + if (text == null) return; 73 + 74 + sendResultsOverNetwork = true; 75 + 76 + m_IPEndPointList.Clear(); 77 + 78 + foreach (var line in text.Split(new[] {'\n'}, StringSplitOptions.RemoveEmptyEntries)) 79 + { 80 + var idx = line.IndexOf(':'); 81 + if (idx == -1) throw new Exception(line); 82 + var ip = line.Substring(0, idx); 83 + var port = line.Substring(idx + 1); 84 + m_IPEndPointList.Add(new IPEndPoint(IPAddress.Parse(ip), Int32.Parse(port))); 85 + } 86 + #endif // if UTT_SOCKETS_SUPPORTED 87 + } 88 + 89 + private static string GetTextFromTextAsset(string fileName) 90 + { 91 + var nameWithoutExtension = fileName.Substring(0, fileName.LastIndexOf('.')); 92 + var resultpathFile = Resources.Load(nameWithoutExtension) as TextAsset; 93 + return resultpathFile != null ? resultpathFile.text : null; 94 + } 95 + 96 + private static string GetTextFromTempFile(string fileName) 97 + { 98 + string text = null; 99 + try 100 + { 101 + #if UNITY_EDITOR && !UNITY_WEBPLAYER 102 + text = File.ReadAllText(Path.Combine("Temp", fileName)); 103 + #endif 104 + } 105 + catch 106 + { 107 + return null; 108 + } 109 + return text; 110 + } 111 + 112 + private void CheckForBatchMode() 113 + { 114 + #if IMITATE_BATCH_MODE 115 + isBatchRun = true; 116 + #elif UNITY_EDITOR 117 + if (Application.isEditor && InternalEditorUtility.inBatchMode) 118 + isBatchRun = true; 119 + #else 120 + if (GetTextFromTextAsset(batchRunFileMarker) != null) isBatchRun = true; 121 + #endif 122 + } 123 + 124 + public static List<string> GetAvailableNetworkIPs() 125 + { 126 + #if UTT_SOCKETS_SUPPORTED 127 + if (!NetworkInterface.GetIsNetworkAvailable()) 128 + return new List<String>{IPAddress.Loopback.ToString()}; 129 + 130 + var ipList = new List<UnicastIPAddressInformation>(); 131 + var allIpsList = new List<UnicastIPAddressInformation>(); 132 + 133 + foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces()) 134 + { 135 + if (netInterface.NetworkInterfaceType != NetworkInterfaceType.Wireless80211 && 136 + netInterface.NetworkInterfaceType != NetworkInterfaceType.Ethernet) 137 + continue; 138 + 139 + var ipAdresses = netInterface.GetIPProperties().UnicastAddresses 140 + .Where(a => a.Address.AddressFamily == AddressFamily.InterNetwork); 141 + allIpsList.AddRange(ipAdresses); 142 + 143 + if (netInterface.OperationalStatus != OperationalStatus.Up) continue; 144 + 145 + ipList.AddRange(ipAdresses); 146 + } 147 + 148 + //On Mac 10.10 all interfaces return OperationalStatus.Unknown, thus this workaround 149 + if(!ipList.Any()) return allIpsList.Select(i => i.Address.ToString()).ToList(); 150 + 151 + // sort ip list by their masks to predict which ip belongs to lan network 152 + ipList.Sort((ip1, ip2) => 153 + { 154 + var mask1 = BitConverter.ToInt32(ip1.IPv4Mask.GetAddressBytes().Reverse().ToArray(), 0); 155 + var mask2 = BitConverter.ToInt32(ip2.IPv4Mask.GetAddressBytes().Reverse().ToArray(), 0); 156 + return mask2.CompareTo(mask1); 157 + }); 158 + if (ipList.Count == 0) 159 + return new List<String> { IPAddress.Loopback.ToString() }; 160 + return ipList.Select(i => i.Address.ToString()).ToList(); 161 + #else 162 + return new List<string>(); 163 + #endif // if UTT_SOCKETS_SUPPORTED 164 + } 165 + 166 + public ITestRunnerCallback ResolveNetworkConnection() 167 + { 168 + #if UTT_SOCKETS_SUPPORTED 169 + var nrsList = m_IPEndPointList.Select(ipEndPoint => new NetworkResultSender(ipEndPoint.Address.ToString(), ipEndPoint.Port)).ToList(); 170 + 171 + var timeout = TimeSpan.FromSeconds(30); 172 + DateTime startTime = DateTime.Now; 173 + while ((DateTime.Now - startTime) < timeout) 174 + { 175 + foreach (var networkResultSender in nrsList) 176 + { 177 + try 178 + { 179 + if (!networkResultSender.Ping()) continue; 180 + } 181 + catch (Exception e) 182 + { 183 + Debug.LogException(e); 184 + sendResultsOverNetwork = false; 185 + return null; 186 + } 187 + return networkResultSender; 188 + } 189 + Thread.Sleep(500); 190 + } 191 + Debug.LogError("Couldn't connect to the server: " + string.Join(", ", m_IPEndPointList.Select(ipep => ipep.Address + ":" + ipep.Port).ToArray())); 192 + sendResultsOverNetwork = false; 193 + #endif // if UTT_SOCKETS_SUPPORTED 194 + return null; 195 + } 196 + } 197 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestRunner/TestRunnerConfigurator.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 05aae864572254e478ed2f0489cdd335 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
+5
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets.meta
··· 1 + fileFormatVersion: 2 2 + guid: 1d1ccbd729921544dbd71f7e80c405b6 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+204
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace UnityTest 6 + { 7 + public class CallTesting : MonoBehaviour 8 + { 9 + public enum Functions 10 + { 11 + CallAfterSeconds, 12 + CallAfterFrames, 13 + Start, 14 + Update, 15 + FixedUpdate, 16 + LateUpdate, 17 + OnDestroy, 18 + OnEnable, 19 + OnDisable, 20 + OnControllerColliderHit, 21 + OnParticleCollision, 22 + OnJointBreak, 23 + OnBecameInvisible, 24 + OnBecameVisible, 25 + OnTriggerEnter, 26 + OnTriggerExit, 27 + OnTriggerStay, 28 + OnCollisionEnter, 29 + OnCollisionExit, 30 + OnCollisionStay, 31 + OnTriggerEnter2D, 32 + OnTriggerExit2D, 33 + OnTriggerStay2D, 34 + OnCollisionEnter2D, 35 + OnCollisionExit2D, 36 + OnCollisionStay2D, 37 + } 38 + 39 + public enum Method 40 + { 41 + Pass, 42 + Fail 43 + } 44 + 45 + public int afterFrames = 0; 46 + public float afterSeconds = 0.0f; 47 + public Functions callOnMethod = Functions.Start; 48 + 49 + public Method methodToCall; 50 + private int m_StartFrame; 51 + private float m_StartTime; 52 + 53 + private void TryToCallTesting(Functions invokingMethod) 54 + { 55 + if (invokingMethod == callOnMethod) 56 + { 57 + if (methodToCall == Method.Pass) 58 + IntegrationTest.Pass(gameObject); 59 + else 60 + IntegrationTest.Fail(gameObject); 61 + 62 + afterFrames = 0; 63 + afterSeconds = 0.0f; 64 + m_StartTime = float.PositiveInfinity; 65 + m_StartFrame = int.MinValue; 66 + } 67 + } 68 + 69 + public void Start() 70 + { 71 + m_StartTime = Time.time; 72 + m_StartFrame = afterFrames; 73 + TryToCallTesting(Functions.Start); 74 + } 75 + 76 + public void Update() 77 + { 78 + TryToCallTesting(Functions.Update); 79 + CallAfterSeconds(); 80 + CallAfterFrames(); 81 + } 82 + 83 + private void CallAfterFrames() 84 + { 85 + if (afterFrames > 0 && (m_StartFrame + afterFrames) <= Time.frameCount) 86 + TryToCallTesting(Functions.CallAfterFrames); 87 + } 88 + 89 + private void CallAfterSeconds() 90 + { 91 + if ((m_StartTime + afterSeconds) <= Time.time) 92 + TryToCallTesting(Functions.CallAfterSeconds); 93 + } 94 + 95 + public void OnDisable() 96 + { 97 + TryToCallTesting(Functions.OnDisable); 98 + } 99 + 100 + public void OnEnable() 101 + { 102 + TryToCallTesting(Functions.OnEnable); 103 + } 104 + 105 + public void OnDestroy() 106 + { 107 + TryToCallTesting(Functions.OnDestroy); 108 + } 109 + 110 + public void FixedUpdate() 111 + { 112 + TryToCallTesting(Functions.FixedUpdate); 113 + } 114 + 115 + public void LateUpdate() 116 + { 117 + TryToCallTesting(Functions.LateUpdate); 118 + } 119 + 120 + public void OnControllerColliderHit() 121 + { 122 + TryToCallTesting(Functions.OnControllerColliderHit); 123 + } 124 + 125 + public void OnParticleCollision() 126 + { 127 + TryToCallTesting(Functions.OnParticleCollision); 128 + } 129 + 130 + public void OnJointBreak() 131 + { 132 + TryToCallTesting(Functions.OnJointBreak); 133 + } 134 + 135 + public void OnBecameInvisible() 136 + { 137 + TryToCallTesting(Functions.OnBecameInvisible); 138 + } 139 + 140 + public void OnBecameVisible() 141 + { 142 + TryToCallTesting(Functions.OnBecameVisible); 143 + } 144 + 145 + public void OnTriggerEnter() 146 + { 147 + TryToCallTesting(Functions.OnTriggerEnter); 148 + } 149 + 150 + public void OnTriggerExit() 151 + { 152 + TryToCallTesting(Functions.OnTriggerExit); 153 + } 154 + 155 + public void OnTriggerStay() 156 + { 157 + TryToCallTesting(Functions.OnTriggerStay); 158 + } 159 + public void OnCollisionEnter() 160 + { 161 + TryToCallTesting(Functions.OnCollisionEnter); 162 + } 163 + 164 + public void OnCollisionExit() 165 + { 166 + TryToCallTesting(Functions.OnCollisionExit); 167 + } 168 + 169 + public void OnCollisionStay() 170 + { 171 + TryToCallTesting(Functions.OnCollisionStay); 172 + } 173 + 174 + public void OnTriggerEnter2D() 175 + { 176 + TryToCallTesting(Functions.OnTriggerEnter2D); 177 + } 178 + 179 + public void OnTriggerExit2D() 180 + { 181 + TryToCallTesting(Functions.OnTriggerExit2D); 182 + } 183 + 184 + public void OnTriggerStay2D() 185 + { 186 + TryToCallTesting(Functions.OnTriggerStay2D); 187 + } 188 + 189 + public void OnCollisionEnter2D() 190 + { 191 + TryToCallTesting(Functions.OnCollisionEnter2D); 192 + } 193 + 194 + public void OnCollisionExit2D() 195 + { 196 + TryToCallTesting(Functions.OnCollisionExit2D); 197 + } 198 + 199 + public void OnCollisionStay2D() 200 + { 201 + TryToCallTesting(Functions.OnCollisionStay2D); 202 + } 203 + } 204 + }
+8
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CallTesting.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 0d545b1288d5fc74d8e6c961fb67ab18 3 + MonoImporter: 4 + serializedVersion: 2 5 + defaultReferences: [] 6 + executionOrder: 0 7 + icon: {instanceID: 0} 8 + userData:
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionFailure.prefab

This is a binary file and will not be displayed.

+4
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionFailure.prefab.meta
··· 1 + fileFormatVersion: 2 2 + guid: d5fc3c3488db1e74689f1fc67c33944a 3 + NativeFormatImporter: 4 + userData:
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionSuccess.prefab

This is a binary file and will not be displayed.

+4
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeCollisionSuccess.prefab.meta
··· 1 + fileFormatVersion: 2 2 + guid: 1228dff762eab21488cfefd42792c37b 3 + NativeFormatImporter: 4 + userData:
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerFailure.prefab

This is a binary file and will not be displayed.

+4
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerFailure.prefab.meta
··· 1 + fileFormatVersion: 2 2 + guid: 616ddafe39e02da4081e56f7f763af3c 3 + NativeFormatImporter: 4 + userData:
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerSuccess.prefab

This is a binary file and will not be displayed.

+4
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/CubeTriggerSuccess.prefab.meta
··· 1 + fileFormatVersion: 2 2 + guid: d940e636fd44be84e9b7e8da46f700ef 3 + NativeFormatImporter: 4 + userData:
+5
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials.meta
··· 1 + fileFormatVersion: 2 2 + guid: 8d55f43641ba3c14eaa1156abc0edabd 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/green.mat

This is a binary file and will not be displayed.

+4
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/green.mat.meta
··· 1 + fileFormatVersion: 2 2 + guid: 43da3275cd08d41429f56675d70c58df 3 + NativeFormatImporter: 4 + userData:
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/red.mat

This is a binary file and will not be displayed.

+4
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/Materials/red.mat.meta
··· 1 + fileFormatVersion: 2 2 + guid: 03f3b4747259a364b800508ac27e1c17 3 + NativeFormatImporter: 4 + userData:
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/green.png

This is a binary file and will not be displayed.

+53
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/green.png.meta
··· 1 + fileFormatVersion: 2 2 + guid: 928be703400f4eb48af2f94d55bf3f74 3 + TextureImporter: 4 + serializedVersion: 2 5 + mipmaps: 6 + mipMapMode: 0 7 + enableMipMap: 1 8 + linearTexture: 0 9 + correctGamma: 0 10 + fadeOut: 0 11 + borderMipMap: 0 12 + mipMapFadeDistanceStart: 1 13 + mipMapFadeDistanceEnd: 3 14 + bumpmap: 15 + convertToNormalMap: 0 16 + externalNormalMap: 0 17 + heightScale: .25 18 + normalMapFilter: 0 19 + isReadable: 0 20 + grayScaleToAlpha: 0 21 + generateCubemap: 0 22 + seamlessCubemap: 0 23 + textureFormat: -1 24 + maxTextureSize: 1024 25 + textureSettings: 26 + filterMode: -1 27 + aniso: -1 28 + mipBias: -1 29 + wrapMode: -1 30 + nPOTScale: 1 31 + lightmap: 0 32 + compressionQuality: 50 33 + spriteMode: 0 34 + autoDetectMinSpriteSize: 4 35 + gridPadding: 0 36 + gridOffsetX: 0 37 + gridOffsetY: 0 38 + gridSizeX: 64 39 + gridSizeY: 64 40 + spriteExtrude: 1 41 + alignment: 0 42 + spritePivot: {x: .5, y: .5} 43 + spriteAtlasHint: 0 44 + spritePixelsToUnits: 100 45 + generateSpritePolygon: 0 46 + spritePolygonAlphaCutoff: 254 47 + spritePolygonDetail: .5 48 + alphaIsTransparency: 0 49 + textureType: -1 50 + buildTargetSettings: [] 51 + spriteSheet: 52 + spriteFrames: [] 53 + userData:
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/red.png

This is a binary file and will not be displayed.

+53
Assets/UnityTestTools/IntegrationTestsFramework/TestingAssets/red.png.meta
··· 1 + fileFormatVersion: 2 2 + guid: 591632297e74ba34fa4c65d1265d370a 3 + TextureImporter: 4 + serializedVersion: 2 5 + mipmaps: 6 + mipMapMode: 0 7 + enableMipMap: 1 8 + linearTexture: 0 9 + correctGamma: 0 10 + fadeOut: 0 11 + borderMipMap: 0 12 + mipMapFadeDistanceStart: 1 13 + mipMapFadeDistanceEnd: 3 14 + bumpmap: 15 + convertToNormalMap: 0 16 + externalNormalMap: 0 17 + heightScale: .25 18 + normalMapFilter: 0 19 + isReadable: 0 20 + grayScaleToAlpha: 0 21 + generateCubemap: 0 22 + seamlessCubemap: 0 23 + textureFormat: -1 24 + maxTextureSize: 1024 25 + textureSettings: 26 + filterMode: -1 27 + aniso: -1 28 + mipBias: -1 29 + wrapMode: -1 30 + nPOTScale: 1 31 + lightmap: 0 32 + compressionQuality: 50 33 + spriteMode: 0 34 + autoDetectMinSpriteSize: 4 35 + gridPadding: 0 36 + gridOffsetX: 0 37 + gridOffsetY: 0 38 + gridSizeX: 64 39 + gridSizeY: 64 40 + spriteExtrude: 1 41 + alignment: 0 42 + spritePivot: {x: .5, y: .5} 43 + spriteAtlasHint: 0 44 + spritePixelsToUnits: 100 45 + generateSpritePolygon: 0 46 + spritePolygonAlphaCutoff: 254 47 + spritePolygonDetail: .5 48 + alphaIsTransparency: 0 49 + textureType: -1 50 + buildTargetSettings: [] 51 + spriteSheet: 52 + spriteFrames: [] 53 + userData:
+83
Assets/UnityTestTools/LICENSE.txt
··· 1 + This software is provided 'as-is', without any express or implied warranty. 2 + 3 + 4 + THE UNITY TEST TOOLS CONTAIN THE FOLLOWING THIRD PARTY LIBRARIES: 5 + NSubstitute Copyright (c) 2009 Anthony Egerton (nsubstitute@delfish.com) and David Tchepak (dave@davesquared.net). All rights reserved. 6 + NUnit Portions Copyright � 2002-2009 Charlie Poole or Copyright � 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright � 2000-2002 Philip A. Craig 7 + Cecil Copyright (c) 2008 - 2011, Jb Evain 8 + 9 + 10 + 11 + NSubstitute is open source software, licensed under the BSD License. The modifications made by Unity are available on github. 12 + 13 + Copyright (c) 2009 Anthony Egerton (nsubstitute@delfish.com) and David Tchepak (dave@davesquared.net) 14 + All rights reserved. 15 + 16 + Redistribution and use in source and binary forms, with or without modification, 17 + are permitted provided that the following conditions are met: 18 + 19 + * Redistributions of source code must retain the above copyright notice, 20 + this list of conditions and the following disclaimer. 21 + * Redistributions in binary form must reproduce the above copyright notice, 22 + this list of conditions and the following disclaimer in the documentation 23 + and/or other materials provided with the distribution. 24 + * Neither the names of the copyright holders nor the names of 25 + contributors may be used to endorse or promote products derived from this 26 + software without specific prior written permission. 27 + 28 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 29 + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 30 + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 32 + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 34 + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 36 + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 37 + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 + 39 + [ http://www.opensource.org/licenses/bsd-license.php ] 40 + 41 + 42 + 43 + NUnit is provided 'as-is', without any express or implied warranty. The modifications made by Unity are available on github. 44 + 45 + Copyright � 2002-2013 Charlie Poole 46 + Copyright � 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov 47 + Copyright � 2000-2002 Philip A. Craig 48 + 49 + This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. 50 + 51 + Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 52 + 53 + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required. 54 + 55 + Portions Copyright � 2002-2013 Charlie Poole or Copyright � 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright � 2000-2002 Philip A. Craig 56 + 57 + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 58 + 59 + 3. This notice may not be removed or altered from any source distribution. 60 + 61 + 62 + 63 + Cecil is licensed under the MIT/X11. 64 + 65 + Copyright (c) 2008 - 2011, Jb Evain 66 + 67 + Permission is hereby granted, free of charge, to any person obtaining a copy 68 + of this software and associated documentation files (the "Software"), to deal 69 + in the Software without restriction, including without limitation the rights 70 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 71 + copies of the Software, and to permit persons to whom the Software is 72 + furnished to do so, subject to the following conditions: 73 + 74 + The above copyright notice and this permission notice shall be included in 75 + all copies or substantial portions of the Software. 76 + 77 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 78 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 79 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 80 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 81 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 82 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 83 + THE SOFTWARE.
+4
Assets/UnityTestTools/LICENSE.txt.meta
··· 1 + fileFormatVersion: 2 2 + guid: 0d5b4501bf773f349ad95ec34491dc61 3 + TextScriptImporter: 4 + userData:
+5
Assets/UnityTestTools/UnitTesting.meta
··· 1 + fileFormatVersion: 2 2 + guid: 9a87f1db904f1e948a2385ab9961e3aa 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
+4
Assets/UnityTestTools/UnitTesting/Editor.meta
··· 1 + fileFormatVersion: 2 2 + guid: 59b47eb3fc62eb44cb73a329a1e6b6cb 3 + DefaultImporter: 4 + userData:
+5
Assets/UnityTestTools/UnitTesting/Editor/NSubstitute.meta
··· 1 + fileFormatVersion: 2 2 + guid: 92b38897656771f409e9235955975754 3 + folderAsset: yes 4 + DefaultImporter: 5 + userData:
Assets/UnityTestTools/UnitTesting/Editor/NSubstitute/NSubstitute.dll

This is a binary file and will not be displayed.

+7
Assets/UnityTestTools/UnitTesting/Editor/NSubstitute/NSubstitute.dll.meta
··· 1 + fileFormatVersion: 2 2 + guid: 3c5e1afc6e0d68849ae6639aff58cfc7 3 + MonoAssemblyImporter: 4 + serializedVersion: 1 5 + iconMap: {} 6 + executionOrder: {} 7 + userData:
+212
Assets/UnityTestTools/changelog.txt
··· 1 + Version 1.5.7 2 + 3 + - Updated tools for Unity 5.3 4 + 5 + Version 1.5.6 6 + 7 + - Updated Mono.Cecil.dll and Mono.Cecil.Mdb.dll libraries 8 + 9 + Version 1.5.5 10 + 11 + - Unit Tests Runner rendering improvments 12 + - Platform runner can include auxiliary scenes 13 + - other improvments and bugfixes 14 + 15 + Version 1.5.4 16 + 17 + - APIs updates 18 + 19 + Version 1.5.3 20 + 21 + - Bug fixes 22 + 23 + Version 1.5.2 24 + 25 + - Bug fixes 26 + - Minor improvments 27 + 28 + Version 1.5.1 29 + 30 + - removed redundant and not applicable options 31 + - fixed 5.0 related bugs 32 + 33 + Version 1.5.0 34 + 35 + - Unity 5 related compatibility changes 36 + 37 + Version 1.4.6 38 + 39 + - Bug fixes 40 + - Minor improvments 41 + 42 + Version 1.4.5 43 + 44 + - Added "Pause on test failure" option for integration tests 45 + - bugfixes and code refactorization 46 + - fixed UI bug where test details were not refreshed is the label was focused 47 + 48 + Version 1.4.4 49 + 50 + - Minimal supported Unity version is now 4.3 51 + - UI changes 52 + - code refactoring 53 + 54 + Version 1.4.3 55 + 56 + - Remove reference to Resources.LoadAssetAtPath from runtime code 57 + 58 + Version 1.4.2 59 + 60 + (assertion component) 61 + - fixed string comparer bug that prevented updating the value 62 + 63 + (unit tests) 64 + - unit test runner will log to stdout now 65 + - fixes issues with opening tests in IDEs 66 + 67 + (integration tests) 68 + - transform component is now visible for integration tests components 69 + - added better support for mac's keyboard 70 + - fixed 'succeed on assertion' for code generated assertion 71 + 72 + (other) 73 + - minor bugfixes 74 + - general improvments 75 + 76 + Version 1.4.1 77 + 78 + - Fixed platform compilation issues 79 + - Fixed typos in labels 80 + - Removed docs and left a link to online docs 81 + - Added Unity version and target platform to result files 82 + - Other bugfixes 83 + 84 + Version 1.4 85 + 86 + (integration tests) 87 + - Platform runner will send the results back to the editor via TCP now 88 + - Added naming convention for running tests in batch mode 89 + - It's possible to cancel the run in the editor in between the tests now 90 + - Added message filtering for integration tests results 91 + - Added check for RegisterLogCallback in case something else overrides it 92 + - Error messages will now fail integration tests 93 + - Fixed dynamic integration tests not being properly reset 94 + - Fixed platform runner for BlackBerry platform 95 + 96 + (assertion component) 97 + - fixed the component editor 98 + 99 + (common) 100 + - Made settings to be saved per project 101 + - Fixed resolving icons when there are more UnityTestTools folders in the project 102 + - Fixed process return code when running in batch mode 103 + 104 + Version 1.3.2 105 + 106 + - Fixed integration tests performance issues 107 + 108 + Version 1.3.1 109 + 110 + - Updated Japanese docs 111 + 112 + Version 1.3 113 + 114 + Fixes: 115 + (unit tests) 116 + - nUnit will no longer change the Environment.CurrentDirectory when running tests 117 + - fixed issues with asserting GameObject == null 118 + (integration tests) 119 + - fix the issue with passing or failing test in first frame 120 + - fixed bug where ignored tests were still run in ITF 121 + (assertion component) 122 + - fixed resolving properties to include derived types 123 + 124 + Improvements: 125 + (unit tests) 126 + - refactored result renderer 127 + - reenabled Random attribute 128 + - added Category filter 129 + - NSubstitute updated to version 1.7.2 130 + - result now will be dimmed after recompilation 131 + - running tests in background will now work without having the window focused 132 + - all assemblies in the project referencing 'nunit.framework' will now be included in the test list 133 + (integration tests) 134 + - updated platform exclusion mechanism 135 + - refactored result renderer 136 + - the runner should work even if the runner window is not focused 137 + - added possibility to create integration tests from code 138 + - the runner will now always run in background (if the window is not focused) 139 + (assertion component) 140 + - added API for creating assertions from code 141 + - added new example 142 + (common) 143 + - GUI improvements 144 + - you no longer need to change the path to icons when moving the tools to another directory 145 + - made test details/results resizeable and scrollable 146 + - added character escape for generated result XML 147 + 148 + Version 1.2.1 149 + - Fixed Unit Test Batch runner 150 + 151 + Version 1.2 152 + Fixes: 153 + - Windows Store related compilation issues 154 + - other 155 + Improvements: 156 + (unit tests) 157 + - unit test runner can run in background now without having the runner window open 158 + - unit test batch runner can take a result file path as a parameter 159 + - changed undo system for unit test runner and UnityUnitTest base class 160 + - execution time in now visible in test details 161 + - fixed a bug with tests that inherit from a base test class 162 + (integration tests) 163 + - added hierarchical structure for integration tests 164 + - added Player runner to automate running integration tests on platforms 165 + - Integration tests batch runner can take a result directory as a parameter 166 + - Integration tests batch runner can run tests on platforms 167 + - results are rendered in a player 168 + (assertion component) 169 + - changed default failure messages 170 + - it's possible to override failure action on comparer failure 171 + - added code stripper for assertions. 172 + - vast performance improvement 173 + - fixed bugs 174 + Other: 175 + - "Hide in hierarchy" option was removed from integration test runner 176 + - "Focus on selection" option was removed from integration test runner 177 + - "Hide test runner" option was removed from integration test runner 178 + - result files for unit tests and integration tests are now not generated when running tests from the editor 179 + - UI improvements 180 + - removed UnityScript and Boo examples 181 + - WP8 compatibility fixes 182 + 183 + Version 1.1.1 184 + Other: 185 + - Documentation in Japanese was added 186 + 187 + Version 1.1 188 + Fixes: 189 + - fixed display error that happened when unit test class inherited from another TestFixture class 190 + - fixed false positive result when "Succeed on assertions" was checked and no assertions were present in the test 191 + - fixed XmlResultWriter to be generate XML file compatible with XSD scheme 192 + - XmlResultWriter result writer was rewritten to remove XML libraries dependency 193 + - Fixed an issue with a check that should be executed once after a specified frame in OnUpdate. 194 + - added missing file UnityUnitTest.cs 195 + Improvements: 196 + - Added Japanese translation of the documentation 197 + - ErrorPause value will be reverted to previous state after test run finishes 198 + - Assertion Component will not copy reference to a GameObject if the GameObject is the same as the component is attached to. Instead, it will set the reference to the new GameObject. 199 + - Integration tests batch runner can now run multiple scenes 200 + - Unit test runner will now include tests written in UnityScript and Boo 201 + - Unit tests will not run automatically if the compilation failes 202 + - Added scene auto-save option to the Unit Test Runner 203 + Other: 204 + - changed icons 205 + - restructured project files 206 + - moved XmlResultWriter to Common folder 207 + - added UnityScript and Boo unit tests examples 208 + - added more unit tests examples 209 + - Test runners visual adjustments 210 + 211 + Version 1.0 212 + - Initial release
+4
Assets/UnityTestTools/changelog.txt.meta
··· 1 + fileFormatVersion: 2 2 + guid: 29b770d9107643740b69cb98b00430aa 3 + TextScriptImporter: 4 + userData:
+9
Assets/src.meta
··· 1 + fileFormatVersion: 2 2 + guid: 6fd631af58144044db65aa529d0b975f 3 + folderAsset: yes 4 + timeCreated: 1494703233 5 + licenseType: Pro 6 + DefaultImporter: 7 + userData: 8 + assetBundleName: 9 + assetBundleVariant:
+36
Assets/src/Danmaku.cs
··· 1 + using System.Collections; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace DanmakU { 6 + 7 + public struct Danmaku { 8 + public Vector2 Position; 9 + public float Rotation; 10 + public float Speed; 11 + public float AngularVelocity; 12 + 13 + public void Move(float deltaTime) { 14 + Rotation += AngularVelocity * deltaTime; 15 + Position += Speed * MathUtils.GetDirection(Rotation) * deltaTime; 16 + } 17 + 18 + public static implicit operator Danmaku(DanmakuInitialState state) { 19 + return new Danmaku { 20 + Position = state.Position, 21 + Rotation = state.Rotation.GetValue(), 22 + Speed = state.Rotation.GetValue(), 23 + AngularVelocity = state.AngularVelocity.GetValue() 24 + }; 25 + } 26 + 27 + } 28 + 29 + public struct DanmakuInitialState { 30 + public Vector2 Position; 31 + public Range Rotation; 32 + public Range Speed; 33 + public Range AngularVelocity; 34 + } 35 + 36 + }
+12
Assets/src/Danmaku.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 64d644a2ee664864095a8a90004273f1 3 + timeCreated: 1494706584 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+9
Assets/src/Fireables.meta
··· 1 + fileFormatVersion: 2 2 + guid: 5efa0b97e411c5e459c833d631ba88be 3 + folderAsset: yes 4 + timeCreated: 1494711374 5 + licenseType: Pro 6 + DefaultImporter: 7 + userData: 8 + assetBundleName: 9 + assetBundleVariant:
+9
Assets/src/Fireables/Modifiers.meta
··· 1 + fileFormatVersion: 2 2 + guid: f270328fdbf18f849ad426f8aa598f21 3 + folderAsset: yes 4 + timeCreated: 1494712852 5 + licenseType: Pro 6 + DefaultImporter: 7 + userData: 8 + assetBundleName: 9 + assetBundleVariant:
+22
Assets/src/Fireables/Modifiers/RandomSubemitterFireable.cs
··· 1 + using System.Collections.Generic; 2 + using UnityEngine; 3 + 4 + namespace DanmakU { 5 + 6 + public class RandomSubemitterFireable : IFireable { 7 + 8 + public List<IFireable> Subemitters { get; set;} 9 + 10 + public RandomSubemitterFireable(IEnumerable<IFireable> subemitters) { 11 + Subemitters = new List<IFireable>(subemitters); 12 + } 13 + 14 + public void Fire(DanmakuInitialState state) { 15 + var subemitter = Subemitters[Mathf.FloorToInt(Random.value * Subemitters.Count)]; 16 + if (subemitter != null) 17 + subemitter.Fire(state); 18 + } 19 + 20 + } 21 + 22 + }
+12
Assets/src/Fireables/Modifiers/RandomSubemitterFireable.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 283af073fa5e3e440ad1f3f70fa6c051 3 + timeCreated: 1494712852 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+21
Assets/src/Fireables/PrefabFireable.cs
··· 1 + using UnityEngine; 2 + 3 + namespace DanmakU { 4 + 5 + public class PrefabFireable : IFireable { 6 + 7 + public GameObject Prefab { get; set; } 8 + 9 + public PrefabFireable(GameObject prefab) { 10 + Prefab = prefab; 11 + } 12 + 13 + public void Fire(DanmakuInitialState state) { 14 + var instance = Object.Instantiate(Prefab) as GameObject; 15 + instance.transform.position = state.Position; 16 + instance.transform.Rotate(new Vector3(0, 0f, state.Rotation * Mathf.Rad2Deg)); 17 + } 18 + 19 + } 20 + 21 + }
+12
Assets/src/Fireables/PrefabFireable.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 08e7bcb89a5fc3749b1f205b80f43b36 3 + timeCreated: 1494712852 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+9
Assets/src/Fireables/Shapes.meta
··· 1 + fileFormatVersion: 2 2 + guid: edaff96068a81b04bbab385df327bdca 3 + folderAsset: yes 4 + timeCreated: 1494712852 5 + licenseType: Pro 6 + DefaultImporter: 7 + userData: 8 + assetBundleName: 9 + assetBundleVariant:
+51
Assets/src/Fireables/Shapes/Arc.cs
··· 1 + using System; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace DanmakU { 6 + 7 + [Serializable] 8 + public class Arc : ShapeFireable { 9 + [SerializeField] 10 + Range _count; 11 + [SerializeField] 12 + Range _arcLength; 13 + [SerializeField] 14 + Range _radius; 15 + public Range Count { 16 + get { return _count;} 17 + set { _count = value; } 18 + } 19 + public Range ArcLength { 20 + get { return _arcLength;} 21 + set { _arcLength = value; } 22 + } 23 + public Range Radius { 24 + get { return _radius;} 25 + set { _radius = value; } 26 + } 27 + 28 + public Arc(Range count, Range arcLength, Range radius) { 29 + Count = count; 30 + ArcLength = arcLength; 31 + Radius = radius; 32 + } 33 + 34 + protected override IEnumerable<DanmakuInitialState> GetSubemissions(DanmakuInitialState state) { 35 + float radius = Radius.GetValue(); 36 + int count = Mathf.RoundToInt(Count.GetValue()); 37 + float arcLength = ArcLength.GetValue(); 38 + var rotation = state.Rotation.GetValue(); 39 + var start = rotation - arcLength / 2; 40 + for (int i = 0; i < count; i++) { 41 + var currentState = state; 42 + var angle = start + i * (arcLength / count); 43 + state.Position = state.Position + 44 + (radius * MathUtils.GetDirection(angle)); 45 + state.Rotation = angle; 46 + yield return currentState; 47 + } 48 + } 49 + } 50 + 51 + }
+12
Assets/src/Fireables/Shapes/Arc.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: c9f29a8b5af046446b20336a12d910e7 3 + timeCreated: 1494712852 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+44
Assets/src/Fireables/Shapes/Circle.cs
··· 1 + using System; 2 + using System.Collections; 3 + using System.Collections.Generic; 4 + using UnityEngine; 5 + 6 + namespace DanmakU { 7 + 8 + [Serializable] 9 + public class Circle : ShapeFireable { 10 + [SerializeField] 11 + Range _count; 12 + [SerializeField] 13 + Range _radius; 14 + public Range Count { 15 + get { return _count;} 16 + set { _count = value; } 17 + } 18 + public Range Radius { 19 + get { return _radius;} 20 + set { _radius = value; } 21 + } 22 + 23 + public Circle(Range count, Range radius) { 24 + Count = count; 25 + Radius = radius; 26 + } 27 + 28 + protected override IEnumerable<DanmakuInitialState> GetSubemissions(DanmakuInitialState state) { 29 + float radius = Radius.GetValue(); 30 + int count = Mathf.RoundToInt(Count.GetValue()); 31 + var rotation = state.Rotation.GetValue(); 32 + for (int i = 0; i < count; i++) { 33 + var currentState = state; 34 + var angle = rotation + i * (MathUtils.TwoPI / count); 35 + state.Position = state.Position + 36 + (radius * MathUtils.GetDirection(angle)); 37 + state.Rotation = rotation; 38 + yield return currentState; 39 + } 40 + } 41 + } 42 + 43 + } 44 +
+12
Assets/src/Fireables/Shapes/Circle.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 969e74872e452904c8cc7c3cf10c9b2d 3 + timeCreated: 1494712852 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+44
Assets/src/Fireables/Shapes/Ring.cs
··· 1 + using System; 2 + using System.Collections; 3 + using System.Collections.Generic; 4 + using UnityEngine; 5 + 6 + namespace DanmakU { 7 + 8 + [Serializable] 9 + public class Ring : ShapeFireable { 10 + [SerializeField] 11 + Range _count; 12 + [SerializeField] 13 + Range _radius; 14 + public Range Count { 15 + get { return _count;} 16 + set { _count = value; } 17 + } 18 + public Range Radius { 19 + get { return _radius;} 20 + set { _radius = value; } 21 + } 22 + 23 + public Ring(Range count, Range radius) { 24 + Count = count; 25 + Radius = radius; 26 + } 27 + 28 + protected override IEnumerable<DanmakuInitialState> GetSubemissions(DanmakuInitialState state) { 29 + float radius = Radius.GetValue(); 30 + int count = Mathf.RoundToInt(Count.GetValue()); 31 + var rotation = state.Rotation.GetValue(); 32 + for (int i = 0; i < count; i++) { 33 + var currentState = state; 34 + var angle = rotation + i * (MathUtils.TwoPI / count); 35 + currentState.Position = state.Position + 36 + (radius * MathUtils.GetDirection(angle)); 37 + currentState.Rotation = angle; 38 + yield return currentState; 39 + } 40 + } 41 + } 42 + 43 + } 44 +
+12
Assets/src/Fireables/Shapes/Ring.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 65a5b92e765e0284193112235d1e7ac2 3 + timeCreated: 1494712852 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+22
Assets/src/Fireables/Shapes/ShapeFireable.cs
··· 1 + using System; 2 + using System.Collections; 3 + using System.Collections.Generic; 4 + using UnityEngine; 5 + 6 + namespace DanmakU { 7 + 8 + public abstract class ShapeFireable : Fireable { 9 + 10 + protected abstract IEnumerable<DanmakuInitialState> GetSubemissions(DanmakuInitialState state); 11 + public override void Fire(DanmakuInitialState state) { 12 + var subemissions = GetSubemissions(state); 13 + if (subemissions == null || Subemitter == null) 14 + return; 15 + foreach (DanmakuInitialState sub in subemissions) 16 + Subemitter.Fire(sub); 17 + } 18 + 19 + } 20 + 21 + } 22 +
+12
Assets/src/Fireables/Shapes/ShapeFireable.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: c39792ed37676c84dba32e3059810c5f 3 + timeCreated: 1494712852 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+27
Assets/src/IFireable.cs
··· 1 + using System; 2 + using System.Collections; 3 + using System.Collections.Generic; 4 + using UnityEngine; 5 + 6 + namespace DanmakU { 7 + 8 + public interface IFireable { 9 + void Fire(DanmakuInitialState state); 10 + } 11 + 12 + public abstract class Fireable : IFireable { 13 + 14 + IFireable _subemitter; 15 + public IFireable Subemitter { get; set; } 16 + 17 + public abstract void Fire(DanmakuInitialState state); 18 + 19 + protected void Subfire(DanmakuInitialState state) { 20 + if (Subemitter == null) 21 + return; 22 + Subemitter.Fire(state); 23 + } 24 + 25 + } 26 + 27 + }
+12
Assets/src/IFireable.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 1b8360c64a67366478f339d5242bac16 3 + timeCreated: 1494703242 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+37
Assets/src/IFireableExtensions.cs
··· 1 + using System; 2 + using System.Collections; 3 + using System.Collections.Generic; 4 + using UnityEngine; 5 + 6 + namespace DanmakU { 7 + 8 + public static class FireableExtensions { 9 + 10 + static Fireable GetLowestChild(Fireable fireable) { 11 + var last = fireable; 12 + while (fireable != null) { 13 + last = fireable; 14 + fireable = fireable.Subemitter as Fireable; 15 + } 16 + return last; 17 + } 18 + 19 + public static Fireable Of(this Fireable fireable, IFireable subemitter) { 20 + if (fireable == null) 21 + throw new ArgumentNullException("fireable"); 22 + var lowest = GetLowestChild(fireable); 23 + lowest.Subemitter = subemitter; 24 + return fireable; 25 + } 26 + 27 + public static Fireable Of(this Fireable fireable, IEnumerable<IFireable> subemitters) { 28 + return fireable.Of(new RandomSubemitterFireable(subemitters)); 29 + } 30 + 31 + public static Fireable Of(this Fireable fireable, params IFireable[] subemitters) { 32 + return fireable.Of(new RandomSubemitterFireable(subemitters)); 33 + } 34 + 35 + } 36 + 37 + }
+12
Assets/src/IFireableExtensions.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 1d160920be3034d449d579b265a713fc 3 + timeCreated: 1494705986 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+35
Assets/src/MathUtils.cs
··· 1 + using System.Collections; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace DanmakU { 6 + 7 + public static class MathUtils { 8 + 9 + // Approximately 0.5 degrees in radians 10 + const float _accuracy = 0.00872665f; 11 + public const float TwoPI = Mathf.PI * 2; 12 + const float Deg2Rad = Mathf.PI / 180f; 13 + static Vector2[] _directions; 14 + 15 + static MathUtils() { 16 + _directions = new Vector2[Mathf.CeilToInt(TwoPI / _accuracy)]; 17 + for (var i = 0; i < _directions.Length; i++) { 18 + var angle = _accuracy * i; 19 + _directions[i] = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); 20 + } 21 + } 22 + 23 + // Quickly creates a direction vector without needing to call trig functions 24 + public static Vector2 GetDirection(float radians) { 25 + var index = Mathf.RoundToInt(radians / _accuracy); 26 + return _directions[index % _directions.Length]; 27 + } 28 + 29 + public static Vector2 GetDirectionDegress(float degrees) { 30 + return GetDirection(degrees * Deg2Rad); 31 + } 32 + 33 + } 34 + 35 + }
+12
Assets/src/MathUtils.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: 287e427a9753d1e4f80e8d89a52b8541 3 + timeCreated: 1494706520 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+58
Assets/src/Range.cs
··· 1 + using System; 2 + using System.Collections; 3 + using System.Collections.Generic; 4 + using UnityEngine; 5 + 6 + namespace DanmakU { 7 + 8 + [Serializable] 9 + public struct Range { 10 + [SerializeField] 11 + 12 + public float Min; 13 + public float Max; 14 + 15 + public Range(float val) : this(val, val) { 16 + } 17 + 18 + public Range(float min, float max) { 19 + if (min > max) { 20 + Min = max; 21 + Max = min; 22 + } else { 23 + Max = max; 24 + Min = min; 25 + } 26 + } 27 + 28 + public float GetValue() { 29 + return UnityEngine.Random.value * (Max - Min) + Min; 30 + } 31 + 32 + public static implicit operator float(Range range) { 33 + return range.GetValue(); 34 + } 35 + 36 + public static implicit operator Range(float val) { 37 + return new Range(val); 38 + } 39 + 40 + public static Range operator +(Range lhs, Range rhs) { 41 + return new Range(lhs.Min + rhs.Min, lhs.Max + rhs.Max); 42 + } 43 + 44 + public static Range operator -(Range lhs, Range rhs) { 45 + return new Range(lhs.Min - rhs.Min, lhs.Max - rhs.Max); 46 + } 47 + 48 + public static Range operator *(Range lhs, float rhs) { 49 + return new Range(lhs.Min * rhs, lhs.Max * rhs); 50 + } 51 + 52 + public static Range operator /(Range lhs, float rhs) { 53 + return new Range(lhs.Min / rhs, lhs.Max / rhs); 54 + } 55 + 56 + } 57 + 58 + }
+12
Assets/src/Range.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: de3ee301995740b419d1ed54b018c4ec 3 + timeCreated: 1494706589 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
+9
Assets/test.meta
··· 1 + fileFormatVersion: 2 2 + guid: 8712f879d7e2b874f9ba881d8c976daa 3 + folderAsset: yes 4 + timeCreated: 1494712869 5 + licenseType: Pro 6 + DefaultImporter: 7 + userData: 8 + assetBundleName: 9 + assetBundleVariant:
Assets/test/Capsule.prefab

This is a binary file and will not be displayed.

+9
Assets/test/Capsule.prefab.meta
··· 1 + fileFormatVersion: 2 2 + guid: a67f73c274bbb2f40ab2f0549c8798cf 3 + timeCreated: 1494713043 4 + licenseType: Pro 5 + NativeFormatImporter: 6 + mainObjectFileID: 100100000 7 + userData: 8 + assetBundleName: 9 + assetBundleVariant:
+24
Assets/test/TestScript.cs
··· 1 + using System.Collections; 2 + using System.Collections.Generic; 3 + using UnityEngine; 4 + 5 + namespace DanmakU { 6 + 7 + public class TestScript : MonoBehaviour { 8 + 9 + [SerializeField] 10 + Circle circle; 11 + [SerializeField] 12 + Ring ring; 13 + [SerializeField] 14 + GameObject prefab; 15 + 16 + // Use this for initialization 17 + void Start () { 18 + var fireable = ring.Of(circle).Of(new PrefabFireable(prefab)); 19 + fireable.Fire(new DanmakuInitialState()); 20 + } 21 + 22 + } 23 + 24 + }
+12
Assets/test/TestScript.cs.meta
··· 1 + fileFormatVersion: 2 2 + guid: cf8c58d0c42c9ee429f50b4d37fc4e12 3 + timeCreated: 1494712877 4 + licenseType: Pro 5 + MonoImporter: 6 + serializedVersion: 2 7 + defaultReferences: [] 8 + executionOrder: 0 9 + icon: {instanceID: 0} 10 + userData: 11 + assetBundleName: 12 + assetBundleVariant:
ProjectSettings/AudioManager.asset

This is a binary file and will not be displayed.

ProjectSettings/ClusterInputManager.asset

This is a binary file and will not be displayed.

ProjectSettings/DynamicsManager.asset

This is a binary file and will not be displayed.

ProjectSettings/EditorBuildSettings.asset

This is a binary file and will not be displayed.

ProjectSettings/EditorSettings.asset

This is a binary file and will not be displayed.

ProjectSettings/GraphicsSettings.asset

This is a binary file and will not be displayed.

ProjectSettings/InputManager.asset

This is a binary file and will not be displayed.

ProjectSettings/NavMeshAreas.asset

This is a binary file and will not be displayed.

ProjectSettings/NetworkManager.asset

This is a binary file and will not be displayed.

ProjectSettings/Physics2DSettings.asset

This is a binary file and will not be displayed.

ProjectSettings/ProjectSettings.asset

This is a binary file and will not be displayed.

+1
ProjectSettings/ProjectVersion.txt
··· 1 + m_EditorVersion: 5.6.0f3
ProjectSettings/QualitySettings.asset

This is a binary file and will not be displayed.

ProjectSettings/TagManager.asset

This is a binary file and will not be displayed.

ProjectSettings/TimeManager.asset

This is a binary file and will not be displayed.

ProjectSettings/UnityConnectSettings.asset

This is a binary file and will not be displayed.