private TestRunResult BuildTestRunResult(IRunResults testResults, int expectedTests, bool compressAll = true) { var resultAsArray = testResults.TestResults.ToArray(); var testCases = resultAsArray.Select(t => t.TestCase.Id).Distinct(); var ranTestsCount = testCases.Count(); var timeout = !_aborted && ranTestsCount < expectedTests; var ranTests = (compressAll && ranTestsCount >= DiscoverTests().Count) ? (ITestGuids)TestsGuidList.EveryTest() : new WrappedGuidsEnumeration(testCases); var failedTests = resultAsArray.Where(tr => tr.Outcome == TestOutcome.Failed).Select(t => t.TestCase.Id); if (ranTests.IsEmpty && (testResults.TestsInTimeout == null || testResults.TestsInTimeout.Count == 0)) { _logger.LogTrace($"{RunnerId}: Initial Test session reports 0 result and 0 stuck tests."); } var duration = testResults.TestResults.Aggregate(new TimeSpan(), (span, result) => span.Add(result.Duration)); var message = string.Join(Environment.NewLine, resultAsArray.Where(tr => !string.IsNullOrWhiteSpace(tr.ErrorMessage)) .Select(tr => $"{tr.DisplayName}{Environment.NewLine}{Environment.NewLine}{tr.ErrorMessage}")); var failedTestsDescription = new WrappedGuidsEnumeration(failedTests); var timedOutTests = new WrappedGuidsEnumeration(testResults.TestsInTimeout?.Select(t => t.Id)); return(timeout ? TestRunResult.TimedOut(ranTests, failedTestsDescription, timedOutTests, message, duration) : new TestRunResult(ranTests, failedTestsDescription, timedOutTests, message, duration)); }
public TestRunResult TestMultipleMutants(ITimeoutValueCalculator timeoutCalc, IReadOnlyList <Mutant> mutants, TestUpdateHandler update) { var mutantTestsMap = new Dictionary <int, ITestGuids>(); var needAll = true; ICollection <Guid> testCases; int?timeOutMs = timeoutCalc?.DefaultTimeout; if (mutants != null) { // if we optimize the number of tests to run if (_options.OptimizationMode.HasFlag(OptimizationModes.CoverageBasedTest)) { needAll = false; foreach (var mutant in mutants) { ITestListDescription tests; if ((mutant.IsStaticValue && !_options.OptimizationMode.HasFlag(OptimizationModes.CaptureCoveragePerTest)) || mutant.MustRunAgainstAllTests) { tests = TestsGuidList.EveryTest(); needAll = true; } else { tests = mutant.CoveringTests; } mutantTestsMap.Add(mutant.Id, tests); } testCases = needAll ? null : mutants.SelectMany(m => m.CoveringTests.GetGuids()).ToList(); _logger.LogTrace($"{RunnerId}: Testing [{string.Join(',', mutants.Select(m => m.DisplayName))}] " + $"against {(testCases == null ? "all tests." : string.Join(", ", testCases))}."); if (testCases?.Count == 0) { return(new TestRunResult(TestsGuidList.NoTest(), TestsGuidList.NoTest(), TestsGuidList.NoTest(), "Mutants are not covered by any test!", TimeSpan.Zero)); } if (timeoutCalc != null && testCases != null) { // compute time out var duration = (int)testCases.Select(id => _vsTests[id].InitialRunTime.TotalMilliseconds).Sum(); timeOutMs = timeoutCalc.CalculateTimeoutValue(duration); } } else { if (mutants.Count > 1) { throw new GeneralStrykerException("Internal error: trying to test multiple mutants simultaneously without 'perTest' coverage analysis."); } mutantTestsMap.Add(mutants[0].Id, TestsGuidList.EveryTest()); testCases = null; } } else { testCases = null; } var numberTestCases = testCases == null ? 0 : testCases.Count; var expectedTests = needAll ? DiscoverTests().Count : numberTestCases; void HandleUpdate(IRunResults handler) { var handlerTestResults = handler.TestResults; if (mutants == null) { return; } var tests = handlerTestResults.Count == DiscoverTests().Count ? (ITestGuids)TestsGuidList.EveryTest() : new WrappedGuidsEnumeration(handlerTestResults.Select(t => t.TestCase.Id)); var failedTest = new WrappedGuidsEnumeration(handlerTestResults.Where(tr => tr.Outcome == TestOutcome.Failed) .Select(t => t.TestCase.Id)); var timedOutTest = new WrappedGuidsEnumeration(handler.TestsInTimeout?.Select(t => t.Id)); var remainingMutants = update?.Invoke(mutants, failedTest, tests, timedOutTest); if (handlerTestResults.Count >= expectedTests || remainingMutants != false || _aborted) { return; } // all mutants status have been resolved, we can stop _logger.LogDebug($"{RunnerId}: Each mutant's fate has been established, we can stop."); _vsTestConsole.CancelTestRun(); _aborted = true; } _logger.LogDebug("Using {0} ms as testrun timeout", timeOutMs.ToString() ?? "no"); var testResults = RunTestSession(mutantTestsMap, needAll, GenerateRunSettings(timeOutMs, mutants != null, false, mutantTestsMap), HandleUpdate); return(BuildTestRunResult(testResults, expectedTests)); }