public IEnumerator Polling_HappensOncePerFrame() { using (var executor = new UnityTestInstructionExecutor(logErrors: false)) { var pollCount = 0; Responsibly .WaitForCondition("Never", () => { ++pollCount; return(false); }) .ExpectWithinSeconds(1) .ToYieldInstruction(executor); Assert.AreEqual(1, pollCount, "Should poll once synchronously"); yield return(null); Assert.AreEqual(2, pollCount, "Should poll once per frame"); yield return(null); Assert.AreEqual(3, pollCount, "Should poll once per frame"); } }
public IEnumerator ToYieldInstruction_Throws_WhenThrowOnErrorTrue() { this.coroutineRunner.StartCoroutine(this.CompleteAfterOneFrame()); var exception = new Exception("Test exception"); var yieldInstruction = Responsibly .WaitForCondition("may complete", () => this.mayComplete) .Select <object, int>(_ => throw exception) .ExpectWithinSeconds(1) .ToYieldInstruction(this.Executor, throwOnError: true); TestFailureException failureException; while (true) { try { yieldInstruction.MoveNext(); } catch (TestFailureException e) { failureException = e; break; } yield return(null); this.mayComplete = true; } Assert.AreEqual(exception, failureException.InnerException); }
public IEnumerator AssertIgnore_DoesNotCauseTestFailure() { using (var executor = new UnityTestInstructionExecutor()) { yield return(Responsibly .Do("Assert.Ignore", () => Assert.Ignore("Should not fail")) .ToYieldInstruction(executor)); } }
public void WaitForCoroutineMethod_ContainsCorrectDescription() { var instruction = Responsibly .WaitForCoroutineMethod(this.ThrowImmediately) .ExpectWithinSeconds(1) .ToYieldInstruction(this.Executor); Assert.IsTrue(instruction.CompletedWithError); StringAssert.Contains("ThrowImmediately (Coroutine)", instruction.Error.Message); }
public void Errors_AreNotLogged_WhenLogErrorsIsFalse() { using (var executor = new UnityTestInstructionExecutor(logErrors: false)) { var instruction = Responsibly .Do("Throw exception", () => throw new Exception()) .ToYieldInstruction(executor, throwOnError: false); Assert.IsTrue(instruction.CompletedWithError); // Should not fail the test with logged errors } }
public void WaitForCoroutine_ThrowsWithInvalidExecutor() { var nonUnityExecutor = new TestInstructionExecutor(new MockTestScheduler()); var instruction = Responsibly .WaitForCoroutineMethod(this.Forever) .ExpectWithinSeconds(1) .ToYieldInstruction(nonUnityExecutor); Assert.IsTrue(instruction.CompletedWithError); StringAssert.Contains(nameof(MonoBehaviour), instruction.Error.Message); }
public void Errors_AreLogged_WhenLogErrorsIsTrue() { using (var executor = new UnityTestInstructionExecutor(logErrors: true)) { var message = "Should be in log"; Responsibly .Do("Throw exception", () => throw new Exception(message)) .ToYieldInstruction(executor, throwOnError: false); // Should complete synchronously LogAssert.Expect(LogType.Error, new Regex(message)); } }
public IEnumerator WaitForCoroutine_CompletesWithError_WhenCoroutineThrows() { var instruction = Responsibly .WaitForCoroutine("Throw", this.ThrowAfterOneFrame) .ExpectWithinSeconds(1) .ToYieldInstruction(this.Executor, throwOnError: false); yield return(instruction); Assert.IsTrue(instruction.CompletedWithError); Assert.AreSame(this.testException, instruction.Error.InnerException); }
public void UnhandledErrorLog_IsLoggedAsWarning_WhenLogErrorsIsTrue() { using (var executor = new UnityTestInstructionExecutor(logErrors: true)) { var expected = "expected message"; Responsibly .Do("Throw exception", () => Debug.LogError(expected)) .ToYieldInstruction(executor, throwOnError: false); // Should complete synchronously LogAssert.Expect(LogType.Warning, new Regex(expected)); // The one from us } }
public void GlobalContext_IsIncludedInErrors() { var globalContextProvider = Substitute.For <IGlobalContextProvider>(); globalContextProvider.BuildGlobalContext(Arg.Do( (StateStringBuilder builder) => builder.AddDetails("Global details"))); using (var executor = new UnityTestInstructionExecutor(globalContextProvider: globalContextProvider)) { Responsibly .Do("Throw exception", () => throw new Exception()) .ToYieldInstruction(executor, throwOnError: false); // Should complete synchronously LogAssert.Expect(LogType.Error, new Regex("Global details")); } }
public void ContinueWith_PropagatesError_WhenContinuationThrows() { var task = Responsibly .Return(new object()) .ContinueWith <object, object>(_ => throw new Exception("Test exception")) .ToTask(this.Executor); var exception = GetFailureException(task); StateAssert.StringContainsInOrder(exception.Message) .Completed("Return") .Failed("...") .Details("Test exception"); }
public void LoggingError_CausesFailureSynchronously() { using (var executor = new UnityTestInstructionExecutor(logErrors: false)) { var yieldInstruction = Responsibly .WaitForCondition("Never", () => false) .ExpectWithinSeconds(1) .ToYieldInstruction(executor); Debug.LogError("Should fail the instruction"); Assert.IsTrue(yieldInstruction.CompletedWithError); } }
public IEnumerator ToYieldInstruction_CompletesAsExpected_WhenConstructedFromWait() { this.coroutineRunner.StartCoroutine(this.CompleteAfterOneFrame()); var yieldInstruction = Responsibly .WaitForCondition("may complete", () => this.mayComplete) .CreateState() .ToYieldInstruction(this.Executor); yield return(yieldInstruction); // Completes one frame "late", because of Update ordering Assert.AreEqual(this.completedOnFrame + 1, Time.frameCount); Assert.IsTrue(yieldInstruction.CompletedSuccessfully); }
public IEnumerator CompoundCoroutineWait_ContainsCorrectDescription() { var instruction = Responsibly .WaitForCoroutineMethod(this.CompleteAfterOneFrame) .AndThen(Responsibly.WaitForCoroutineMethod(this.ThrowImmediately)) .ExpectWithinSeconds(1) .ToYieldInstruction(this.Executor, throwOnError: false); yield return(instruction); Assert.IsTrue(instruction.CompletedWithError); Assert.That( instruction.Error.Message, Does.Match(@"\[✓\] CompleteAfterOneFrame.*\n.*\[!\] ThrowImmediately")); }
public IEnumerator WaitForCoroutine_CompletesWithCoroutine() { var startFrame = Time.frameCount; yield return(Responsibly .WaitForCoroutine("Coroutine", this.CompleteAfterOneFrame) .ExpectWithinSeconds(1) .ToYieldInstruction(this.Executor)); Assert.AreEqual( 1, Time.frameCount - startFrame, "Coroutine should complete after one frame"); Assert.IsTrue(this.coroutineCompleted); }
public void StateString_TruncatesExceptionAt100Chars() { var message = new string('x', 99) + "^~"; var state = Responsibly.Do( "Fail", () => throw new Exception(message)) .CreateState(); state.ToTask(this.Executor); // Complete task var stateString = state.ToString(); StateAssert.StringContainsInOrder(stateString) .Failed("Fail") .Details(@"xxxxxxx\^") .Nowhere("~"); }
public void StateString_ContainsOnlyFirstLineOfException_WhenMultiline() { var firstLine = "First line"; var secondLine = "Second line"; var state = Responsibly.Do( "Fail", () => throw new Exception($"{firstLine}\n{secondLine}")) .CreateState(); state.ToTask(this.Executor); // Complete task var stateString = state.ToString(); StateAssert.StringContainsInOrder(stateString) .Failed("Fail") .Details(firstLine) .Nowhere(secondLine); }
public void LoggingError_DoesNotFail_WhenUsingExpectLog() { using (var executor = new UnityTestInstructionExecutor(logErrors: false)) { var yieldInstruction = Responsibly .WaitForCondition("Never", () => false) .ExpectWithinSeconds(1) .ToYieldInstruction(executor); var message = "Should not fail the instruction"; executor.ExpectLog(LogType.Error, new Regex(message)); Debug.LogError(message); Assert.IsFalse(yieldInstruction.WasCanceled); Assert.IsFalse(yieldInstruction.CompletedSuccessfully); Assert.IsFalse(yieldInstruction.CompletedWithError); } }
public IEnumerator ToYieldInstruction_CompletesAsExpected() { this.coroutineRunner.StartCoroutine(this.CompleteAfterOneFrame()); var yieldInstruction = Responsibly .WaitForCondition("may complete", () => this.mayComplete) .ExpectWithinSeconds(1) .ToYieldInstruction(this.Executor); yield return(yieldInstruction); // Completes one frame after Assert.AreEqual(this.completedOnFrame + 1, Time.frameCount); object unused; Assert.IsFalse(yieldInstruction.WasCanceled); Assert.IsFalse(yieldInstruction.CompletedWithError); Assert.IsTrue(yieldInstruction.CompletedSuccessfully); Assert.IsNotNull(yieldInstruction.Result); Assert.Throws <InvalidOperationException>(() => unused = yieldInstruction.Error); }
public IEnumerator Polling_IsStopped_WhenDisposed() { var pollCount = 0; using (var executor = new UnityTestInstructionExecutor(logErrors: false)) { Responsibly .WaitForCondition("Never", () => { ++pollCount; return(false); }) .ExpectWithinSeconds(1) .ToYieldInstruction(executor); } Assert.AreEqual(1, pollCount, "Should poll once synchronously"); yield return(null); Assert.AreEqual(1, pollCount, "Should not poll after being disposed"); }
public IEnumerator WaitForCoroutine_CancelsCoroutine_WhenOperationCanceled() { using (var cancellationSource = new CancellationTokenSource()) { var instruction = Responsibly .WaitForCoroutine("Forever", this.Forever) .ExpectWithinSeconds(1) .ToYieldInstruction(this.Executor, throwOnError: false, cancellationSource.Token); Assert.IsTrue(this.coroutineRan); yield return(null); this.coroutineRan = false; cancellationSource.Cancel(); yield return(null); yield return(null); Assert.IsFalse(this.coroutineRan); Assert.IsTrue(instruction.WasCanceled); } }
public IEnumerator ToYieldInstruction_ErrorsAsExpected() { this.coroutineRunner.StartCoroutine(this.CompleteAfterOneFrame()); var exception = new Exception("Test exception"); var yieldInstruction = Responsibly .WaitForCondition("may complete", () => this.mayComplete) .Select <object, int>(_ => throw exception) .ExpectWithinSeconds(1) .ToYieldInstruction(this.Executor, false); yield return(yieldInstruction); // Completes one frame "late", because of Update ordering Assert.AreEqual(this.completedOnFrame + 1, Time.frameCount); object unused; Assert.IsFalse(yieldInstruction.WasCanceled); Assert.IsTrue(yieldInstruction.CompletedWithError); Assert.IsFalse(yieldInstruction.CompletedSuccessfully); Assert.Throws <InvalidOperationException>(() => unused = yieldInstruction.Result); Assert.AreSame(exception, yieldInstruction.Error.InnerException); }
public void Instruction_IsCanceled_WhenExternalResult([Values] bool error) { var polled = false; var unused = Responsibly .WaitForCondition("Fake condition", () => { polled = true; return(false); }) .ExpectWithinSeconds(1); if (error) { this.completionSource.SetException(new Exception()); } else { this.completionSource.SetResult(1); } this.AdvanceDefaultFrame(); Assert.IsFalse(polled); }