public void MarkTestRailsTestCase(bool isSuccess, params int[] testCaseIds) { if (!IsFailing) { AutomationReport.MarkTestRailsTestCase(isSuccess ? "Passed" : "Failed", testCaseIds); } }
/// <summary> /// Return list of most recent logs. Stores a maximum of 25 most recent logs. /// </summary> /// <returns>The latest logs.</returns> /// <param name="numberOfMostRecentLogsToReturn">Number of most recent logs to return.</param> public static string ReturnLatestLogs(int numberOfMostRecentLogsToReturn) { List<Log> returnList = new List<Log>(); if(Logs.Count <= numberOfMostRecentLogsToReturn) { returnList = Logs; } else { for(int i = 1; i <= numberOfMostRecentLogsToReturn; i++) { if(i < 0) { break; } Log thisLog = Logs[Logs.Count - i]; if(!string.IsNullOrEmpty(thisLog.message)) { returnList.Add(thisLog); } else { Logs.RemoveAt(Logs.Count - i); i--; } } } StringBuilder logString = new StringBuilder(); for(int i = 0; i < returnList.Count; i++) { logString.AppendLine(string.Format("(LOG ENTRY) MESSAGE: {0} ** STACKTRACE: {1} ** TYPE: {2}", returnList[i].message, returnList[i].stackTrace, returnList[i].type.ToString())); } if(logString.Length > MAX_LOG_RETURN_LENGTH) { return AutomationReport.EncodeCharactersForJson(logString.ToString().Substring(0, MAX_LOG_RETURN_LENGTH)).Replace(AutomationMaster.DELIMITER.ToString(), "%7C"); //Encode AutomationMaster.DELIMITER character or errors will occur in data parsing in server. } else { return AutomationReport.EncodeCharactersForJson(logString.ToString()).Replace(AutomationMaster.DELIMITER.ToString(), "%7C"); //Encode AutomationMaster.DELIMITER character or errors will occur in data parsing in server. } }
public void Add(AutoConsole.Log error) { GameException ex = new GameException(); ex.ScreenshotName = string.Format("EXCEPTION_{0}", Reported.Count); AutomationMaster.StaticSelfComponent.TakeScreenshotAsync(false, ex.ScreenshotName); ex.TimeStamp = System.DateTime.UtcNow.ToLongDateString(); ex.TestExecutionTime = System.DateTime.UtcNow.Subtract(AutomationMaster.CurrentTestContext.StartTime).TotalSeconds.ToString(); ex.CurrentRunningTest = AutomationMaster.CurrentTestContext.TestName; ex.Error = AutomationReport.EncodeCharactersForJson(error.message); ex.ErrorDetails = AutomationReport.EncodeCharactersForJson(error.stackTrace); ex.Occurrences = 1; for (int r = 0; r < Reported.Count; r++) { if (Reported[r].Error == ex.Error && Reported[r].ErrorDetails == ex.ErrorDetails) { Reported[r].Occurrences++; return; } } _reported.Add(ex); }
public void Add(AutoConsole.Log error) { GameException ex = new GameException(); ex.ScreenshotName = string.Format("EXCEPTION_{0}", Reported.Count); ex.TimeStamp = System.DateTime.UtcNow.ToLongDateString(); ex.TestExecutionTime = System.DateTime.UtcNow.Subtract(AutomationMaster.CurrentTestContext.StartTime).TotalSeconds.ToString(); ex.CurrentRunningTest = AutomationMaster.CurrentTestContext.TestName; ex.Error = AutomationReport.EncodeCharactersForJson(error.message).Replace(AutomationMaster.DELIMITER.ToString(), "%7C"); //Encode AutomationMaster.DELIMITER character or errors will occur in data parsing in server. ex.ErrorDetails = AutomationReport.EncodeCharactersForJson(error.stackTrace).Replace(AutomationMaster.DELIMITER.ToString(), "%7C"); //Encode AutomationMaster.DELIMITER character or errors will occur in data parsing in server. ex.Occurrences = 1; for (int r = 0; r < Reported.Count; r++) { if (Reported[r].Error == ex.Error && Reported[r].ErrorDetails == ex.ErrorDetails) { Reported[r].Occurrences++; return; } } AutomationMaster.StaticSelfComponent.TakeScreenshotAsync(false, ex.ScreenshotName); //Only take a screenshot if it is not a duplicate. Spammed errors would lead to spammed screenshots. _reported.Add(ex); }
public override void Render() { _newBuddyName = AutomationReport.GetMostRecentBuddy(); //Display last-used Buddy by default. //Tell test runner to not/ignore BuddySystem tests in the current test run. if (Application.isPlaying) { if (_ignoreBuddyTests != AutomationMaster.IgnoreAllBuddyTests) { if (!AutomationMaster.LockIgnoreBuddyTestsFlag) { AutomationMaster.IgnoreAllBuddyTests = _ignoreBuddyTests; } } } GUIStyle buddyWindowLabel = new GUIStyle(GUI.skin.label); buddyWindowLabel.fontStyle = FontStyle.Bold; buddyWindowLabel.padding = Nexus.BaseRectOffset; GUIStyle sl = new GUIStyle(GUI.skin.label); sl.padding = new RectOffset(15, 0, 0, 0); EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.LabelField("- Set Buddy Info -", buddyWindowLabel); EditorGUILayout.Space(); EditorGUILayout.Space(); sl.normal.textColor = Swat.WindowDefaultTextColor; if (_isBuddySet && !string.IsNullOrEmpty(BuddyHandler.BuddyName)) { EditorGUILayout.LabelField(string.Format("Current Buddy is {0}", BuddyHandler.BuddyName), sl); EditorGUILayout.Space(); } sl.fixedWidth = 125; if (!_buddyHistory.Any() && DateTime.Now.Subtract(_lastBuddyRetrieval).TotalSeconds > _redrawRateSeconds) { _buddyHistory = AutomationReport.GetBuddyHistory(); _lastBuddyRetrieval = DateTime.Now; } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Ignore Buddy Tests? ", sl); _ignoreBuddyTests = EditorGUILayout.Toggle(_ignoreBuddyTests); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); if (_buddyHistory.Any()) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Use Known Buddy? ", sl); _chooseBuddyFromHistory = EditorGUILayout.Toggle(_chooseBuddyFromHistory); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Is Primary? ", sl); _isPrimaryBuddy = EditorGUILayout.Toggle(_isPrimaryBuddy); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); if (!_chooseBuddyFromHistory || !_buddyHistory.Any()) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Buddy Name: ", sl); _newBuddyName = EditorGUILayout.TextField(_newBuddyName); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); } GUIStyle buddies = new GUIStyle(EditorStyles.popup); buddies.margin = new RectOffset(15, 0, 0, 0); if (_chooseBuddyFromHistory) { if (_buddyHistory.Any()) { buddies.fixedHeight = 15; _buddySelection = EditorGUILayout.Popup(_buddySelection, _buddyHistory.ToArray(), buddies, new GUILayoutOption[] { GUILayout.Height(50), GUILayout.MaxWidth(250) }); } } buddies = new GUIStyle(GUI.skin.button); buddies.margin = new RectOffset(15, 0, 0, 0); buddies.fixedHeight = 25; if (GUILayout.Button("Set Buddy", buddies, new GUILayoutOption[] { GUILayout.Width(75), GUILayout.Height(25) })) { _isBuddySet = true; AutomationMaster.Arbiter.SendCommunication(string.Format("{{\"manual_set_buddy_{0}\":\"{1}\"}}", _isPrimaryBuddy ? "primary" : "secondary", _chooseBuddyFromHistory && _buddyHistory.Any() ? _buddyHistory[_buddySelection] : _newBuddyName)); } EditorGUILayout.Space(); }
public void AddTestCaseAssertionOnFailure(string newAssertion) { //Add test case assertion before the last failed assertion. Assertions.AddAt(Assertions.Count - 2, AutomationReport.EncodeCharactersForJson(newAssertion)); }
public void AddAssertion(string newAssertion) { Assertions.Add(AutomationReport.EncodeCharactersForJson(newAssertion)); }
protected IEnumerator Unifier(bool b, bool inverse, string message, FailureContext newFailureContext, params int[] testRailsId) { //If test was already marked as a failure, and test has flag indicating that it should continue despite failure, ignore. if (!AutomationMaster.CurrentTestContext.IsSuccess || ((AutomationMaster.TryContinueOnFailure || MideExecution_MarkTestToTryContinueAfterFail) && IsFailing)) { UnitTestStepFailure = isSoft = isTry = quiet = false; //Reset the UnitTestStepFailure, Soft, Try, and Quiet flags. yield break; } //Automatically label this assertion as quiet if the previous assertion is identical to this one. quiet = quiet ? true : AutomationMaster.CurrentTestContext.Assertions.Last() == message; _failureContext = newFailureContext; if ((!b && inverse) || (b && !inverse)) { if (isTry && !quiet) { AutomationMaster.CurrentTestContext.AddAssertion(string.Format("**TRY_SUCCESS**{0}", message)); UnitTestStepFailure = isSoft = isTry = quiet = false; //Reset the UnitTestStepFailure, Soft, Try, and Quiet flags. yield break; } ConcurrentFailures = 0; AutomationMaster.CurrentTestContext.IsSuccess = true; if (!string.IsNullOrEmpty(message) && !isTry && !quiet) { AutomationMaster.CurrentTestContext.AddAssertion(message); } } else { //TODO: UnitTestStepFailure - Determine if an assertion has failed within the context of a TestObject "steps" method. If so, set this to true. Used to disabled certain TestRunner reactive logic, such as screenshots. if (isTry) { if (!quiet) { AutomationMaster.CurrentTestContext.AddAssertion(string.Format("**TRY_FAIL**{0}", message)); } UnitTestStepFailure = isSoft = isTry = quiet = false; //Reset the UnitTestStepFailure, Soft, Try, and Quiet flags. yield break; } IsFailing = true; bool recordLogDetails = newFailureContext != FailureContext.Skipped; SetReflectedTestData(); string recentLogs = AutomationReport.EncodeCharactersForJson(AutoConsole.ReturnLatestLogs(5)); if (newFailureContext == FailureContext.Skipped) { AutomationMaster.TestRunContext.Skipped.Add(AutomationMaster.CurrentTestContext.TestName); } else { AutomationMaster.TestRunContext.Failed.Add(AutomationMaster.CurrentTestContext.TestName, new string[] { message, recentLogs.ToString(), lineNumber }); } AutomationMaster.CurrentTestContext.IsSuccess = false; AutomationMaster.CurrentTestContext.AddAssertion(message); AutomationMaster.CurrentTestContext.ErrorDetails += string.Format("Error Message [{0}] : Test Line [{1}] : Debug Logs [{2}] ", message, string.Format("Line [{0}] Call [{1}]", lineNumber, lineCall), (recordLogDetails ? recentLogs : string.Format("#SKIPPED#{0}", message))); AutomationMaster.CurrentTestContext.ErrorDetails += string.Format(" FULL STACK: [{0}]", Environment.StackTrace.Replace(" at", string.Format(" {0} at", AutomationMaster.NEW_LINE_INDICATOR))); if (failureContext != FailureContext.Skipped) { //Take screenshot if a failure is not a "Skip" failure (In which case a test does not run at all, and there is no value in taking a screenshot as the current screen has no relevance to the reason it failed). yield return(StartCoroutine(AutomationMaster.StaticSelfComponent.TakeScreenshot())); screenshotRequestTime = DateTime.UtcNow; } //Handle errors occurring outside of the context of the current test's execution. Only certain contexts require additional handling over what is offered by default. switch (AutomationMaster.ExecutionContext) { case AutomationMaster.CurrentExecutionContext.SetUpClass: AutomationMaster.AutoSkips.Add(new KeyValuePair <string[], string>(new string[] { "class", AutomationMaster.CurrentTestContext.ClassName }, string.Format("FAILURE OCCURRED IN SETUPCLASS:", message))); break; case AutomationMaster.CurrentExecutionContext.SetUp: AutomationMaster.AutoSkips.Add(new KeyValuePair <string[], string>(new string[] { "test", AutomationMaster.CurrentTestContext.TestName }, string.Format("FAILURE OCCURRED IN SETUP:", message))); break; case AutomationMaster.CurrentExecutionContext.TearDownClass: yield return(StartCoroutine(Q.assert.Warn(string.Format("A failure occurred in the TearDownClass logic for the test \"{0}.{1}\". This fails the last-run test, and may cause other undesirable behavior for downstream test execution.", AutomationMaster.CurrentTestContext.ClassName, AutomationMaster.CurrentTestContext.TestName)))); //Will automatically handle the failure of this test. break; case AutomationMaster.CurrentExecutionContext.TearDown: //Will automatically handle the failure of this test. case AutomationMaster.CurrentExecutionContext.Test: //Will automatically handle the failure of this test. default: break; } if ((AutomationMaster.TryContinueOnFailure || MideExecution_MarkTestToTryContinueAfterFail) && ConcurrentFailures > 5) { AutomationMaster.OverrideContinueOnFailureAfterTooManyConcurrentFailures = true; } #if UNITY_EDITOR AutomationMaster.PauseEditorOnFailure(); #endif //Any FailureContext beyond TestMethod will not have an instantiated test method. if (!AutomationMaster.TryContinueOnFailure) { if ((!isSoft && AutomationMaster.OverrideContinueOnFailureAfterTooManyConcurrentFailures) || (!MideExecution_MarkTestToTryContinueAfterFail && (_failureContext == FailureContext.TestMethod || _failureContext == FailureContext.Default) && failureContext != FailureContext.Skipped)) { try { AutomationMaster.CurrentTestMethod.Stop(); //Kill current test, only if the currently queued test has been initialized. } catch { } yield return(new WaitForEndOfFrame()); //Allow all Coroutines to be stopped before returning control. In reality, the coroutine calling this will be stopped, so control will never be returned anyway. } } if (!isSoft && (AutomationMaster.TryContinueOnFailure || MideExecution_MarkTestToTryContinueAfterFail)) { ConcurrentFailures++; } } if (testRailsId.Length > 0) { AutomationReport.MarkTestRailsTestCase(AutomationMaster.CurrentTestContext.IsSuccess ? "Passed" : "Failed", testRailsId); } AutoConsole.PostMessage(string.Format("Assert [{0}] |{1}| {2}", AutomationMaster.CurrentTestContext.TestName, AutomationMaster.CurrentTestContext.IsSuccess ? "Success" : "Failure", message), MessageLevel.Verbose, ConsoleMessageType.TestRunnerUpdate); UnitTestStepFailure = isSoft = isTry = quiet = false; //Reset the UnitTestStepFailure, Soft, Try, and Quiet flags. yield return(null); }
/// <summary> /// While this client is in the Primary Buddy role, run Action tests, and await completion of Secondary Buddy's Reaction tests. /// </summary> /// <returns>The buddy test run.</returns> public IEnumerator PrimaryBuddyTestRun() { for (int b = 0; b < _buddies.Count; b++) { //Skip this method if it has already been handled. if (HandledBuddyTests.Contains(Buddies[b].Key.Key)) { continue; } SecondaryReactionsStarted = false; //Reset for next reaction. timeout = 180; time = 0; //Retrieve any BuddyCommands for this Action test, and send them to Buddy for execution. BuddyCommand command = _buddies[b].Key.Value.GetCustomAttributes(typeof(BuddyCommand), false).ToList().First() as BuddyCommand; if (command != null) { SendBuddyCommunication("buddy_primary_pretest_commands", string.Join("|", command.Commands.ToArray())); BuddyProcessingCommands = true; while (BuddyProcessingCommands && time <= timeout) { if (BuddyCommandExecutionFailure) { break; } //Every 50 seconds, report still waiting. if (time % 50 == 0) { AutoConsole.PostMessage(string.Format("Primary waiting for Secondary to complete pretest commands ({0}) seconds", time.ToString()), MessageLevel.Abridged); } yield return(StartCoroutine(Q.driver.WaitRealTime(5))); time += 5; } } string errorMessage = string.Empty; HandledBuddyTests.Add(_buddies[b].Key.Key); if (!AutomationMaster.Methods.KeyValListContainsKey(Buddies[b].Key.Key)) { AutomationMaster.Methods.Add(new KeyValuePair <string, MethodInfo>(Buddies[b].Key.Key, Buddies[b].Key.Value)); } if (!BuddyCommandExecutionFailure && time <= timeout) { //Launch Action test. yield return(StartCoroutine(Master.LaunchSingleTest(Buddies[b].Key, AutomationMaster.Methods.Count - 1))); } else { AutomationMaster.CurrentTestContext.TestInitialize(_buddies[b].Key.Value); if (BuddyCommandExecutionFailure) { errorMessage = string.Format("The Secondary Buddy of this client failed to successfully handle the command(s) {0} required by this Action test. Commands: {1}.", BuddyCommandFailure, string.Join("|", command.Commands.ToArray())); } else { errorMessage = "Timout occurred waiting for primary buddy to complete its pretest commands."; } yield return(StartCoroutine(Q.assert.Fail(errorMessage, FailureContext.TestMethod))); AutomationReport.AddToReport(false, 0, true); //Save results to test run's XML file. Master.ReportOnTest(); } ResendAllInfoForBuddyTests(); yield return(StartCoroutine(Q.driver.WaitRealTime(2f))); bool actionSuccessful = AutomationMaster.CurrentTestContext.IsSuccess; if (actionSuccessful) { SendBuddyCommunication("buddy_primary_test_complete", _buddies[b].Key.Value.Name); } else { SendBuddyCommunication("buddy_primary_test_failed", _buddies[b].Key.Value.Name); } //When the buddy has completed all reaction tests, we can then move on to the next. timeout = 300; time = 0; _waitingForBuddyToCompleteReactionTests = true; int resendCount = 4; while (_waitingForBuddyToCompleteReactionTests && time <= timeout) { //Check if buddy has declared that it is running its secondary tests. If not, resend the command once. if (resendCount > 0 && time > 10 && !SecondaryReactionsStarted) { resendCount--; if (actionSuccessful) { SendBuddyCommunication("buddy_primary_test_complete", _buddies[b].Key.Value.Name); } else { SendBuddyCommunication("buddy_primary_test_failed", _buddies[b].Key.Value.Name); } } //Every 50 seconds, report still waiting. if (time % 50 == 0) { AutoConsole.PostMessage(string.Format("Primary waiting for Secondary ({0}) seconds", time.ToString()), MessageLevel.Abridged); } yield return(StartCoroutine(Q.driver.WaitRealTime(5f))); time += 5; } //If we time out, stop the run and break out of execution. _isBuddySystemFailure = time >= timeout; if (_isBuddySystemFailure) { _failureReason = errorMessage; AutoConsole.PostMessage(_failureReason, MessageLevel.Abridged); break; } //Run all CounterReaction tests for this Action. List <KeyValuePair <string, MethodInfo> > counterReactions = _buddies.FindAll(x => x.Key.Value.Name == _buddies[b].Key.Value.Name).First().Value.FindAll(x => { BuddySystem bs = (BuddySystem)Attribute.GetCustomAttribute(x.Value, typeof(BuddySystem)); return(bs.buddy == Buddy.CounterReaction); }); for (int c = 0; c < counterReactions.Count; c++) { HandledBuddyTests.Add(counterReactions[c].Key); if (!AutomationMaster.Methods.KeyValListContainsKey(counterReactions[c].Key)) { AutomationMaster.Methods.Add(new KeyValuePair <string, MethodInfo>(counterReactions[c].Key, counterReactions[c].Value)); } yield return(StartCoroutine(Master.LaunchSingleTest(counterReactions[c], AutomationMaster.Methods.Count - 1, actionSuccessful ? TestStatus.Pass : TestStatus.Fail))); } } SendBuddyCommunication("buddy_primary_complete_action_tests", "0"); yield return(null); }
public IEnumerator RunBuddySystemTests() { //If a relationship has not yet been established, then cancel BuddySystem execution. This is not used if IgnoreAllBuddyTests flag set. BuddySystemHandlingStarted = true; _isBuddySystemFailure = string.IsNullOrEmpty(BuddyName); if (!AutomationMaster.IgnoreAllBuddyTests) { //If allowed, and Buddy is not yet set, then set Buddy to last-used Buddy. #if UNITY_EDITOR if (AutomationMaster.ConfigReader.GetBool("EDITOR_DEFAULT_BUDDY_TO_LAST")) { string mostRecentBuddy = AutomationReport.GetMostRecentBuddy(); if (!string.IsNullOrEmpty(mostRecentBuddy)) { BuddyName = mostRecentBuddy; } } #endif if (_isBuddySystemFailure) { _failureReason = "Buddy was not set before BuddySystem test execution started."; } if (!_isBuddySystemFailure) { AutoConsole.PostMessage("Establishing Connection With Buddy", MessageLevel.Abridged); do { if (RoleGridLock) { _isBuddySystemFailure = true; _failureReason = "This client and the associated Buddy client share the same role (primary/secondary). One must be a primary Buddy, and the other a secondary Buddy."; break; } SendBuddyCommunication("buddy_ready_for_tests", IsPrimary ? "primary" : "secondary"); yield return(StartCoroutine(Q.driver.WaitRealTime(5))); time += 5; } while((!_isBuddyReadyForBuddyTests || !HasBuddyAcknowledgedOurReadiness) && time <= timeout); AutoConsole.PostMessage(time > timeout ? "Buddy Connection Failure": "Buddy Connection Established", MessageLevel.Abridged); if (IsPrimary && !BuddyTestRequiredDetails.Any()) { //If this client is the Primary, and has not yet recieved its required information from the Secondary, request it. for (int limit = 30; limit >= 0; limit--) { if (!BuddyTestRequiredDetails.Any()) { break; } SendBuddyCommunication("buddy_requesting_required_details", "0"); yield return(StartCoroutine(Q.driver.WaitRealTime(1))); } } if (time >= timeout || (IsPrimary && !BuddyTestRequiredDetails.Any())) { _isBuddySystemFailure = true; _failureReason = "Timed out waiting for Buddy to be ready for multi-client testing."; } if (!_isBuddySystemFailure) { SendBasicBuddyDetails(); if (_isPrimary) { yield return(StartCoroutine(PrimaryBuddyTestRun())); if (!_isBuddySystemFailure) { ResetBuddySystemValues(); yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_switching_roles", "0"); timeout = 300; time = 0; while (!BuddyHasSuccessfullySwitchRoles && time <= timeout) { yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_primary_complete_action_tests", "0"); time += 5; } if (time > timeout) { _isBuddySystemFailure = true; _failureReason = "Timed out waiting for Buddy to switch roles from Secondary to Primary."; } else { AutoConsole.PostMessage("Switching Roles With Buddy", MessageLevel.Abridged); yield return(StartCoroutine(SecondaryBuddyTestRun())); } } } else { yield return(StartCoroutine(SecondaryBuddyTestRun())); if (!_isBuddySystemFailure) { ResetBuddySystemValues(); yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_switching_roles", "0"); timeout = 300; time = 0; while (!BuddyHasSuccessfullySwitchRoles && time <= timeout) { yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_secondary_tests_complete", "0"); time += 5; } if (time > timeout) { _isBuddySystemFailure = true; _failureReason = "Timed out waiting for Buddy to switch roles from Primary to Secondary."; } else { AutoConsole.PostMessage("Switching Roles With Buddy", MessageLevel.Abridged); yield return(StartCoroutine(PrimaryBuddyTestRun())); } } } SendBuddyCommunication("buddy_tearing_down", "0"); yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_tearing_down", "0"); } } } if (_isBuddySystemFailure || AutomationMaster.IgnoreAllBuddyTests) { //Fail all remaining tests. string errorMessage = string.Format("BuddySystem failure. Reason: {0} Skipping BuddySystem tests.", _failureReason); AutoConsole.PostMessage(errorMessage, MessageLevel.Abridged); for (int f = 0; f < _buddies.Count; f++) { if (!HandledBuddyTests.Contains(_buddies[f].Key.Key)) { AutomationMaster.CurrentTestContext = new TestContext(); if (!AutomationMaster.Methods.KeyValListContainsKey(_buddies[f].Key.Key)) { AutomationMaster.Methods.Add(new KeyValuePair <string, MethodInfo>(_buddies[f].Key.Key, Buddies[f].Key.Value)); } } yield return(StartCoroutine(Master.LaunchSingleTest(_buddies[f].Key, AutomationMaster.Methods.Count - 1, AutomationMaster.IgnoreAllBuddyTests ? TestStatus.Ignore : TestStatus.Fail, errorMessage))); for (int fr = 0; fr < _buddies[f].Value.Count; fr++) { if (HandledBuddyTests.Contains(Buddies[f].Value[fr].Value.Name)) { continue; } AutomationMaster.CurrentTestContext = new TestContext(); if (!AutomationMaster.Methods.KeyValListContainsKey(_buddies[f].Value[fr].Key)) { AutomationMaster.Methods.Add(new KeyValuePair <string, MethodInfo>(_buddies[f].Value[fr].Key, Buddies[f].Value[fr].Value)); } yield return(StartCoroutine(Master.LaunchSingleTest(_buddies[f].Value[fr], AutomationMaster.Methods.Count - 1, AutomationMaster.IgnoreAllBuddyTests ? TestStatus.Ignore : TestStatus.Fail, errorMessage))); } } } HandledBuddyTests = new List <string>(); ResetBuddySystemValues(); yield return(null); }
public override void Render() { GUIStyle horizontal = new GUIStyle(); horizontal.margin = new RectOffset(10, 11, 0, 0); GUIStyle statusColor = new GUIStyle(GUI.skin.label); statusColor.margin = new RectOffset(0, 0, 3, 0); statusColor.normal.textColor = AutoConsole.Paused ? Color.red : Nexus.TextGreen; statusColor.fixedWidth = 125; statusColor.fontStyle = FontStyle.Bold; GUILayout.Space(15); EditorGUILayout.BeginHorizontal(horizontal); //For "Running" notification and FPS counter. if (Application.isPlaying && AutomationMaster.Busy) { EditorGUILayout.LabelField("Running Test(s)", statusColor); } else { AutomationMaster.Busy = false; EditorGUILayout.LabelField(string.Empty, statusColor); } if (Application.isPlaying) { if (renderPasses == FPS_SAMPLE_RATE && Application.isPlaying) { fpsSample = Math.Round(1 / Time.deltaTime, 0); renderPasses = 0; } GUIStyle fps = new GUIStyle(GUI.skin.label); fps.fontSize = 26; fps.padding = new RectOffset(0, 0, -8, 0); fps.normal.textColor = GetFpsColor(fpsSample); GUILayout.FlexibleSpace(); EditorGUILayout.LabelField(string.Format("FPS {0}", fpsSample), new GUILayoutOption[] { GUILayout.Width(50) }); EditorGUILayout.LabelField(string.Format("◈", fpsSample), fps, new GUILayoutOption[] { GUILayout.Width(35) }); GUILayout.Space(-18); renderPasses++; } EditorGUILayout.EndHorizontal(); //End for "Running" notification and FPS counter. GUIStyle scrollStatus = new GUIStyle(GUI.skin.button); scrollStatus.margin = new RectOffset(0, 0, 0, 0); scrollStatus.fontStyle = _autoScroll ? FontStyle.Bold : FontStyle.Normal; scrollStatus.normal.background = Swat.ToggleButtonBackgroundSelectedTexture; scrollStatus.normal.textColor = _pubsubMode ? Nexus.TextGreen : Swat.WindowDefaultTextColor; EditorGUILayout.Space(); GUILayout.BeginHorizontal(horizontal); EditorGUILayout.LabelField(string.Format("{0} - {1}", AutoConsole.Paused ? "Paused" : "Active", AutoConsole.FilterLevel == MessageLevel.Verbose ? "Verbose" : "Abridged"), statusColor); EditorGUILayout.Space(); GUILayout.Space(-100); Nexus.Self.Button("Pubsub", "Show received Pubsub messages.", new Nexus.SwatDelegate(delegate() { _pubsubMode = !_pubsubMode; }), scrollStatus, new GUILayoutOption[] { GUILayout.Width(75), GUILayout.Height(22) }); GUILayout.Space(0.65f); scrollStatus.normal.textColor = _autoScroll ? Nexus.TextGreen : Color.red; Nexus.Self.Button("Auto Scroll", "Remove all messages in the console.", new Nexus.SwatDelegate(delegate() { _autoScroll = !_autoScroll; }), scrollStatus, new GUILayoutOption[] { GUILayout.Width(75), GUILayout.Height(22) }); GUILayout.EndHorizontal(); EditorGUILayout.Space(); GUILayout.BeginHorizontal(horizontal); GUIStyle button = new GUIStyle(GUI.skin.button); button.margin = new RectOffset(0, 0, 0, 0); button.normal.textColor = Swat.ToggleButtonTextColor; button.normal.background = Swat.ToggleButtonBackgroundTexture; Nexus.Self.Button("Clear", "Remove all messages in the console.", new Nexus.SwatDelegate(delegate() { FileBroker.SaveUnboundFile(string.Format("{0}{1}{2}/console_before_start.txt", FileBroker.BASE_NON_UNITY_PATH, ConfigReader.GetString("EDITOR_RESOURCE_CONSOLE_LOG_DIRECTORY"), GameMaster.GAME_NAME), string.Empty); AutoConsole.messageListDisplayed = new List <AutoConsoleMessage>(); AutoConsole.messageListQueued = new List <AutoConsoleMessage>(); _selectedConsoleMessage = null; }), button, new GUILayoutOption[] { GUILayout.Width(60), GUILayout.Height(22) }); GUILayout.Space(0.5f); Nexus.Self.Button(AutoConsole.Paused ? "Resume" : "Pause", "Pause/Continue rendering of new messages in the console. Messages are still received and stored when paused, and will appear immediately when resuming.", new Nexus.SwatDelegate(delegate() { AutoConsole.Paused = !AutoConsole.Paused; }), button, new GUILayoutOption[] { GUILayout.Width(60), GUILayout.Height(22) }); EditorGUILayout.Space(); Nexus.Self.Button("Verbose", "Post ALL messages from the automation framework in the console.", new Nexus.SwatDelegate(delegate() { AutoConsole.FilterLevel = MessageLevel.Verbose; if (_autoScroll) { _scroll.y = 99999; _scroll.x = 0; } }), button, new GUILayoutOption[] { GUILayout.Width(75), GUILayout.Height(22) }); GUILayout.Space(0.65f); GUIStyle abridged = new GUIStyle(GUI.skin.button); abridged.margin = new RectOffset(0, 0, 0, 0); abridged.normal.textColor = Swat.ToggleButtonTextColor; abridged.normal.background = Swat.ToggleButtonBackgroundTexture; Nexus.Self.Button("Abridged", "Post only automation messages marked as high priority in the console.", new Nexus.SwatDelegate(delegate() { AutoConsole.FilterLevel = MessageLevel.Abridged; if (_autoScroll) { _scroll.y = 99999; _scroll.x = 0; } }), abridged, new GUILayoutOption[] { GUILayout.Width(75), GUILayout.Height(22) }); GUILayout.EndHorizontal(); float messageHeight = 15; GUIStyle consoleBox = new GUIStyle(GUI.skin.box); consoleBox.fixedHeight = Nexus.Self.position.height - (Application.isPlaying ? 125 : 105); consoleBox.fixedWidth = Nexus.Self.position.width - 20; consoleBox.margin = new RectOffset(10, 0, 0, 10); consoleBox.normal.background = Swat.TabButtonBackgroundTexture; GUILayout.BeginVertical(consoleBox); //Begin box border around console. _scroll = GUILayout.BeginScrollView(_scroll); GUIStyle messageBox = new GUIStyle(GUI.skin.box); messageBox.normal.background = Swat.TabButtonBackgroundSelectedTexture; messageBox.margin = new RectOffset(2, 2, 1, 1); GUIStyle messageBoxText = new GUIStyle(GUI.skin.label); messageBoxText.normal.textColor = Swat.WindowDefaultTextColor; messageBox.fixedWidth = consoleBox.fixedWidth - 10; messageBoxText.fixedWidth = messageBox.fixedWidth - 5; string lastConsoleMessage = string.Empty; int duplicateCount = 0; List <AutoConsoleMessage> consoleMessages = AutoConsole.messageListDisplayed; for (int m = 0; m < consoleMessages.Count; m++) { if ((_pubsubMode && consoleMessages[m].messageType != ConsoleMessageType.Pubsub) || (!_pubsubMode && consoleMessages[m].messageType == ConsoleMessageType.Pubsub)) { continue; } //If this is a new console message, and auto scroll is on, scroll down automatically. if (_autoScroll && m == _lastPassConsoleMessageCount) { _scroll.y = 99999; _scroll.x = 0; } //Render only messages of the requested filter level. if (_pubsubMode || (AutoConsole.FilterLevel == MessageLevel.Abridged && consoleMessages[m].level == MessageLevel.Abridged) || AutoConsole.FilterLevel == MessageLevel.Verbose) { messageBoxText.normal.textColor = AutoConsole.MessageColor(consoleMessages[m].messageType); GUILayout.BeginHorizontal(messageBox, new GUILayoutOption[] { GUILayout.MinWidth(225), GUILayout.MaxHeight(messageHeight) }); if (lastConsoleMessage == consoleMessages[m].message) { duplicateCount++; consoleMessages.RemoveAt(m - 1); } else { lastConsoleMessage = consoleMessages[m].message; duplicateCount = 0; } if (consoleMessages.Count > m) { if (GUILayout.Button(string.Format("{0} {1}", duplicateCount > 0 ?(duplicateCount + 1).ToString() : string.Empty, consoleMessages[m].message), messageBoxText)) { if (_selectedConsoleMessage == consoleMessages[m]) { //If the message has been double-clicked, open this test failure as a single-test, temporary report. if (DateTime.Now.Subtract(_lastConsoleMessageButtonClick).TotalSeconds < 0.75d && !string.IsNullOrEmpty(consoleMessages[m].testMethod)) { if (_consoleAbridgedReportTypes.Contains(consoleMessages[m].messageType)) { _selectedConsoleMessage = null; //Prevents details panel from appearing. We only want it to appear for a single click, not a double click. AutomationReport.BuildTemporaryReportForSingleConsoleFailure(consoleMessages[m].testMethod); System.Diagnostics.Process.Start(string.Format("{0}SingleTestAsReportTemp.html", FileBroker.RESOURCES_DIRECTORY)); OpenedTestReport = DateTime.UtcNow; } } else { ConsoleMessage.Pop(_selectedConsoleMessage.message, Enum.GetName(typeof(ConsoleMessageType), _selectedConsoleMessage.messageType), Enum.GetName(typeof(MessageLevel), _selectedConsoleMessage.level), _selectedConsoleMessage.timestamp.ToString()); _selectedConsoleMessage = null; } } _selectedConsoleMessage = consoleMessages[m]; _lastConsoleMessageButtonClick = DateTime.Now; } } GUILayout.EndHorizontal(); } } _lastPassConsoleMessageCount = consoleMessages.Count; GUILayout.EndScrollView(); GUILayout.EndVertical(); }