comparethemarket / fettle Goto Github PK
View Code? Open in Web Editor NEWAn experimental mutation testing tool for C# code :bug::mag:
License: MIT License
An experimental mutation testing tool for C# code :bug::mag:
License: MIT License
As seen on issue_2 branch.
NullReferenceException thrown because there is no body associated with a method.
E.g. if tests are run via a custom runner exe, allow user to specify that Fettle runs this instead of using the NUnit API. This would need to be a full command-line to include any required arguments.
This feature would be incompatible with coverage-analysis. Perhaps this should be a warning? Or perhaps required that users also add the ---skipcoverageanalysis
option?
Note: this would also allow basic support for test frameworks other than NUnit. E.g. a user could specify that the XUnit test runner exe is run.
I try run fettle on unity3d testproject (based on nunit) and unity plugin.
fettle 0.1.0 from nuget
Analysing test coverageAn error ocurred that Fettle didn't expect.
System.AggregateException: Произошла одна или несколько ошибок. ---> System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта.
в Fettle.Core.CoverageAnalyser.InstrumentMethod(String methodId, MethodDeclarationSyntax methodNode, DocumentEditor documentEditor) в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 197
в Fettle.Core.CoverageAnalyser.d__9.MoveNext() в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 167
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в Fettle.Core.CoverageAnalyser.d__8.MoveNext() в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 128
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в Fettle.Core.CoverageAnalyser.d__7.MoveNext() в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 103
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в Fettle.Core.CoverageAnalyser.d__6.MoveNext() в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 53
--- Конец трассировки внутреннего стека исключений ---
в System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
в System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) в System.Threading.Tasks.Task
1.get_Result()
в Fettle.Console.Program.AnalyseCoverage(ICoverageAnalyser coverageAnalyser, IOutputWriter outputWriter, Config config) в c:\dev\fettle\src\Console\Program.cs:строка 113
в Fettle.Console.Program.InternalEntryPoint(String[] args, Func3 mutationTestRunnerFactory, Func
2 coverageAnalyserFactory, IOutputWriter outputWriter) в c:\dev\fettle\src\Console\Program.cs:строка 57
---> (Внутреннее исключение #0) System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта.
в Fettle.Core.CoverageAnalyser.InstrumentMethod(String methodId, MethodDeclarationSyntax methodNode, DocumentEditor documentEditor) в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 197
в Fettle.Core.CoverageAnalyser.d__9.MoveNext() в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 167
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в Fettle.Core.CoverageAnalyser.d__8.MoveNext() в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 128
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в Fettle.Core.CoverageAnalyser.d__7.MoveNext() в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 103
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в Fettle.Core.CoverageAnalyser.d__6.MoveNext() в c:\dev\fettle\src\Core\CoverageAnalyser.cs:строка 53<---
As an optimisation we could, after compiling mutated code, only run the tests that cover that piece of code. Right now we run all tests.
There doesn't seem to be an out-of-the-box (and free) way of telling which tests cover a given piece of code.
Rolling our own solution could involve:
To see which methods are hit, we could add hooks into the original source before compilation (using Roslyn) or use Microsoft's native profiler API to attach to the process and get events.
Negate the if statement itself.
E.g. if (isEnabled)
mutates to if (!isEnabled)
Currently these are already supported:
if (isEnabled == true)
=> if (isEnabled == false)
if (isEnabled && isOtherThing)
=> if (isEnabled || isOtherThing)
var x = isEnabled ? 1 : 0
=> var x = isEnabled ? 0 : 1
My Fettle config file was in the same folder as my solution file 'FettleTest.sln' and the first line in my config file was 'solution: FettleTest.sln'. This causes Path.GetFullPath(directoryName) to throw an ArugmentException because the directoryName was empty. A workaround is to use '.\FettleTest.sln' in the config file.
One way to solve this would be to check whether the directory name is empty before calling Path.GetFullPath and if so, to set the directory name to ".". This causes Path.GetFullPath to work normally.
Note that when this issue as fixed like this, at least two source locations need to be fixed. Namely Filtering.RelativeDocumentPath and MutationJobList.RunAll (between the 'for' and the 'foreach' statements).
I suggest to put this duplicated code in a shared location.
AppVeyor switched the "Visual Studio 2017" profile from MSBuild version 15.7 to 15.8. As soon as this happened, Fettle's CI started producing compiler warnings and test failures, failing the build.
For now, Fettle's CI settings have been modified to use the previous version and builds are green again, but this should be looked into.
Compile warnings:
Microsoft (R) Build Engine version 15.8.166+gd4e8d81a88 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(2110,5): warning MSB3277: Found conflicts between different versions of "System.Collections.Immutable" that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\projects\fettle\src\Core\Core.csproj]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(2110,5): warning MSB3277: Found conflicts between different versions of "System.Collections.Immutable" that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\projects\fettle\src\Console\Console.csproj]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(2110,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "dotMemory.Unit, Version=109.0.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. [C:\projects\fettle\src\Tests\Tests.csproj]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(2110,5): warning MSB3277: Found conflicts between different versions of "System.Collections.Immutable" that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed. [C:\projects\fettle\src\Tests\Tests.csproj]
Test failures:
Fettle.Tests.Console.EndToEnd.Happy_path.Console_executable_runs_and_outputs_info_about_surviving_mutants
Expected: 1
But was: 3
at Fettle.Tests.Console.EndToEnd.Happy_path.<>c__DisplayClass0_0.<Console_executable_runs_and_outputs_info_about_surviving_mutants>b__0() in C:\projects\fettle\src\Tests\Console\EndToEnd\Happy_path.cs:line 45
at NUnit.Framework.Assert.Multiple(TestDelegate testDelegate) in C:\src\nunit\nunit\src\NUnitFramework\framework\Assert.cs:line 333
at Fettle.Tests.Console.EndToEnd.Happy_path.Console_executable_runs_and_outputs_info_about_surviving_mutants() in C:\projects\fettle\src\Tests\Console\EndToEnd\Happy_path.cs:line 49
1-2) Failed : Fettle.Tests.Console.EndToEnd.Happy_path.Console_executable_runs_and_outputs_info_about_surviving_mutants
Expected: String containing "mutant(s) survived!"
But was: "Analysing test coverageAn error ocurred that Fettle didn't expect.
System.AggregateException: One or more errors occurred. ---> System.IO.FileLoadException: Could not load file or assembly 'System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
at Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create(IDictionary`2 properties)
at Fettle.Core.MSBuildWorkspaceFactory.Create() in C:\projects\fettle\src\Core\MSBuildWorkspaceFactory.cs:line 16
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 44
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()
at Fettle.Console.Program.AnalyseCoverage(ICoverageAnalyser coverageAnalyser, IOutputWriter outputWriter, Config config) in C:\projects\fettle\src\Console\Program.cs:line 109
at Fettle.Console.Program.InternalEntryPoint(String[] args, Func`3 mutationTestRunnerFactory, Func`2 coverageAnalyserFactory, IOutputWriter outputWriter) in C:\projects\fettle\src\Console\Program.cs:line 55
---> (Inner Exception #0) System.IO.FileLoadException: Could not load file or assembly 'System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
at Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create(IDictionary`2 properties)
at Fettle.Core.MSBuildWorkspaceFactory.Create() in C:\projects\fettle\src\Core\MSBuildWorkspaceFactory.cs:line 16
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 44
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
<---
"
at Fettle.Tests.Console.EndToEnd.Happy_path.<>c__DisplayClass0_0.<Console_executable_runs_and_outputs_info_about_surviving_mutants>b__0() in C:\projects\fettle\src\Tests\Console\EndToEnd\Happy_path.cs:line 47
at NUnit.Framework.Assert.Multiple(TestDelegate testDelegate) in C:\src\nunit\nunit\src\NUnitFramework\framework\Assert.cs:line 333
at Fettle.Tests.Console.EndToEnd.Happy_path.Console_executable_runs_and_outputs_info_about_surviving_mutants() in C:\projects\fettle\src\Tests\Console\EndToEnd\Happy_path.cs:line 49
1-3) Failed : Fettle.Tests.Console.EndToEnd.Happy_path.Console_executable_runs_and_outputs_info_about_surviving_mutants
Expected: String containing "PartiallyTestedNumberComparison.cs:7"
But was: "Analysing test coverageAn error ocurred that Fettle didn't expect.
System.AggregateException: One or more errors occurred. ---> System.IO.FileLoadException: Could not load file or assembly 'System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
at Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create(IDictionary`2 properties)
at Fettle.Core.MSBuildWorkspaceFactory.Create() in C:\projects\fettle\src\Core\MSBuildWorkspaceFactory.cs:line 16
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 44
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()
at Fettle.Console.Program.AnalyseCoverage(ICoverageAnalyser coverageAnalyser, IOutputWriter outputWriter, Config config) in C:\projects\fettle\src\Console\Program.cs:line 109
at Fettle.Console.Program.InternalEntryPoint(String[] args, Func`3 mutationTestRunnerFactory, Func`2 coverageAnalyserFactory, IOutputWriter outputWriter) in C:\projects\fettle\src\Console\Program.cs:line 55
---> (Inner Exception #0) System.IO.FileLoadException: Could not load file or assembly 'System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
at Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create(IDictionary`2 properties)
at Fettle.Core.MSBuildWorkspaceFactory.Create() in C:\projects\fettle\src\Core\MSBuildWorkspaceFactory.cs:line 16
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 44
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
<---
"
at Fettle.Tests.Console.EndToEnd.Happy_path.<>c__DisplayClass0_0.<Console_executable_runs_and_outputs_info_about_surviving_mutants>b__0() in C:\projects\fettle\src\Tests\Console\EndToEnd\Happy_path.cs:line 48
at NUnit.Framework.Assert.Multiple(TestDelegate testDelegate) in C:\src\nunit\nunit\src\NUnitFramework\framework\Assert.cs:line 333
at Fettle.Tests.Console.EndToEnd.Happy_path.Console_executable_runs_and_outputs_info_about_surviving_mutants() in C:\projects\fettle\src\Tests\Console\EndToEnd\Happy_path.cs:line 49
2) SetUp Error : Fettle.Tests.Core.Coverage.Happy_path
System.AggregateException : One or more errors occurred.
----> System.Exception : Failed to compile project HasSurvivingMutants.Implementation
warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
error CS5001: Program does not contain a static 'Main' method suitable for an entry point
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at Fettle.Tests.Core.Contexts.Coverage.When_analysing_coverage(Boolean catchExceptions) in C:\projects\fettle\src\Tests\Core\Contexts\Coverage.cs:line 104
--Exception
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileProject>d__7.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 0
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileMultipleProjects>d__6.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 100
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 55
3) SetUp Error : Fettle.Tests.Core.Coverage.Source_file_filters
System.AggregateException : One or more errors occurred.
----> System.Exception : Failed to compile project HasSurvivingMutants.Implementation
warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
error CS5001: Program does not contain a static 'Main' method suitable for an entry point
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at Fettle.Tests.Core.Contexts.Coverage.When_analysing_coverage(Boolean catchExceptions) in C:\projects\fettle\src\Tests\Core\Contexts\Coverage.cs:line 104
--Exception
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileProject>d__7.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 0
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileMultipleProjects>d__6.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 100
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 55
4) SetUp Error : Fettle.Tests.Core.Coverage.Tests_fail
System.AggregateException : One or more errors occurred.
----> System.Exception : Failed to compile project HasSurvivingMutants.Implementation
warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
error CS5001: Program does not contain a static 'Main' method suitable for an entry point
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at Fettle.Tests.Core.Contexts.Coverage.When_analysing_coverage(Boolean catchExceptions) in C:\projects\fettle\src\Tests\Core\Contexts\Coverage.cs:line 104
--Exception
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileProject>d__7.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 0
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileMultipleProjects>d__6.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 100
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 55
5) Error : Fettle.Tests.Core.Coverage_analysis.Then_only_tests_that_cover_members_are_run
Moq.MockException :
Expected invocation on the mock at least once, but was never performed: r => r.RunTests(It.IsAny<IEnumerable`1>(), It.Is<IEnumerable`1>(tn => tn.Contains<String>("example.test.one")))
Configured setups:
x => x.RunTests(It.IsAny<IEnumerable`1>(), It.IsAny<IEnumerable`1>())
No invocations performed.
at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable`1 setups, IEnumerable`1 actualCalls, Expression expression, Times times, Int32 callCount) in C:\projects\moq4\Source\Mock.cs:line 400
at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times) in C:\projects\moq4\Source\Mock.cs:line 385
at Moq.Mock.Verify[T,TResult](Mock`1 mock, Expression`1 expression, Times times, String failMessage) in C:\projects\moq4\Source\Mock.cs:line 321
at Fettle.Tests.Core.Coverage_analysis.Then_only_tests_that_cover_members_are_run() in C:\projects\fettle\src\Tests\Core\Coverage_analysis.cs:line 20
6) SetUp Error : Fettle.Tests.Core.EndToEnd.Happy_path
System.AggregateException : One or more errors occurred.
----> System.Exception : Failed to compile project HasSurvivingMutants.Implementation
warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
error CS5001: Program does not contain a static 'Main' method suitable for an entry point
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at Fettle.Tests.Core.Contexts.EndToEnd.When_mutation_testing_the_app() in C:\projects\fettle\src\Tests\Core\Contexts\EndToEnd.cs:line 34
--Exception
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileProject>d__7.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 0
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileMultipleProjects>d__6.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 100
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\projects\fettle\src\Core\CoverageAnalyser.cs:line 55
7) Failed : Fettle.Tests.Core.Events.Then_event_listener_is_called_when_events_occur
Expected: True
But was: False
at Fettle.Tests.Core.Events.Then_event_listener_is_called_when_events_occur() in C:\projects\fettle\src\Tests\Core\Events.cs:line 18
8) Failed : Fettle.Tests.Core.Filtering.Projects_are_filtered.Then_only_files_matching_filter_are_candidates_for_mutation
Expected: True
But was: False
at Fettle.Tests.Core.Filtering.Projects_are_filtered.Then_only_files_matching_filter_are_candidates_for_mutation() in C:\projects\fettle\src\Tests\Core\Filtering\Projects_are_filtered.cs:line 21
9) Failed : Fettle.Tests.Core.Filtering.Projects_are_filtered_with_multiple_filters.Then_only_files_matching_either_filter_are_candidates_for_mutation
Expected: True
But was: False
at Fettle.Tests.Core.Filtering.Projects_are_filtered_with_multiple_filters.Then_only_files_matching_either_filter_are_candidates_for_mutation() in C:\projects\fettle\src\Tests\Core\Filtering\Projects_are_filtered_with_multiple_filters.cs:line 21
10) Failed : Fettle.Tests.Core.Filtering.Projects_are_not_filtered.Then_all_files_are_candidates_for_mutation
Expected: True
But was: False
at Fettle.Tests.Core.Filtering.Projects_are_not_filtered.Then_all_files_are_candidates_for_mutation() in C:\projects\fettle\src\Tests\Core\Filtering\Projects_are_not_filtered.cs:line 21
11) Failed : Fettle.Tests.Core.Filtering.Source_files_are_filtered.Then_only_files_matching_filter_are_candidates_for_mutation
Expected: True
But was: False
at Fettle.Tests.Core.Filtering.Source_files_are_filtered.Then_only_files_matching_filter_are_candidates_for_mutation() in C:\projects\fettle\src\Tests\Core\Filtering\Source_files_are_filtered.cs:line 21
12) Failed : Fettle.Tests.Core.Filtering.Source_files_are_filtered_with_multiple_filters.Then_only_files_matching_either_filter_are_candidates_for_mutation
Expected: True
But was: False
at Fettle.Tests.Core.Filtering.Source_files_are_filtered_with_multiple_filters.Then_only_files_matching_either_filter_are_candidates_for_mutation() in C:\projects\fettle\src\Tests\Core\Filtering\Source_files_are_filtered_with_multiple_filters.cs:line 23
13) Failed : Fettle.Tests.Core.Filtering.Source_files_are_not_filtered.Then_all_files_are_candidates_for_mutation
Expected: True
But was: False
at Fettle.Tests.Core.Filtering.Source_files_are_not_filtered.Then_all_files_are_candidates_for_mutation() in C:\projects\fettle\src\Tests\Core\Filtering\Source_files_are_not_filtered.cs:line 21
14) Failed : Fettle.Tests.Core.Multiple_mutants_per_syntax_node.Then_only_one_surviving_mutant_is_returned_per_syntax_node
Expected: 1
But was: 0
at Fettle.Tests.Core.Multiple_mutants_per_syntax_node.Then_only_one_surviving_mutant_is_returned_per_syntax_node() in C:\projects\fettle\src\Tests\Core\Multiple_mutants_per_syntax_node.cs:line 20
15) Error : Fettle.Tests.Core.Mutants_survive.Then_the_location_of_the_surviving_mutant_is_returned
System.InvalidOperationException : Sequence contains no elements
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Fettle.Tests.Core.Mutants_survive.Then_the_location_of_the_surviving_mutant_is_returned() in C:\projects\fettle\src\Tests\Core\Mutants_survive.cs:line 25
16) Error : Fettle.Tests.Core.Mutants_survive.Then_the_relevant_post_mutation_source_code_is_returned
System.InvalidOperationException : Sequence contains no elements
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Fettle.Tests.Core.Mutants_survive.Then_the_relevant_post_mutation_source_code_is_returned() in C:\projects\fettle\src\Tests\Core\Mutants_survive.cs:line 39
17) Error : Fettle.Tests.Core.Mutants_survive.Then_the_relevant_pre_mutation_source_code_is_returned
System.InvalidOperationException : Sequence contains no elements
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Fettle.Tests.Core.Mutants_survive.Then_the_relevant_pre_mutation_source_code_is_returned() in C:\projects\fettle\src\Tests\Core\Mutants_survive.cs:line 33
18) Failed : Fettle.Tests.Core.Mutants_survive.Then_the_surviving_mutant_is_returned
Expected: 1
But was: 0
at Fettle.Tests.Core.Mutants_survive.Then_the_surviving_mutant_is_returned() in C:\projects\fettle\src\Tests\Core\Mutants_survive.cs:line 20
E.g.
public override string ToString() => thing;
NullReferenceException is thrown because the coverage analysis assumes all MethodDeclarationSyntax instances have a non-null Body. We should instead check for the other expression body property.
When a mutant survives on an statement that spans multiple lines, the output that's produced by Fettle will show the first line of the statement, but this doesn't necessarily show what was mutated.
For example, if the mutation of ||
survives in the code below:
return a == 1
|| a == 2
then the output will look something like this:
mutated from: return a == 1
mutated to: return a == 1
When errors occur that prevent Fettle from continuing (e.g. tests fail during coverage analysis, invalid test output) then a very concise error summary is presented to the user.
However the user would benefit from more detailed info, such as callstacks and/or full NUnit output.
Running fake outputs this:
The request was aborted: Could not create SSL/TLS secure channel. (Github - cached (temporarily ignore updates))
E.g. with the following code:
private int _thing;
public int Thing
{
set { _thing = value; }
}
In MemberDeclarationSyntaxExtensions.CanInstrumentProperty
, the call to accessors.Single(a => a.Kind() == SyntaxKind.GetAccessorDeclaration)
will throw an exception
Under certain circumstances the memory usage of Fettle increases by a very large amount during coverage analysis.
This has been noticed because of out-of-memory errors can sometimes occur, causing Fettle to exit.
We should capture a memory dump and investigate.
My suspicion is it's caused by the console output generated by the instrumented methods, in which case perhaps we can prevent a method from outputting if it's already done so for a given test.
Guard against invalid configuration given in the YAML file, fail with a helpful error message.
E.g.
E:\Code\DevelopmentDepartment\source\OMDCCQuotes\src\OMDCCQuotes>packages\Fettle.Console.0.4.1\tools\Fettle.Console.exe -c fettle.config.yml
Fettle v0.4.1
Test coverage analysis starting...
.....................
..An error ocurred that Fettle didn't expect.
System.AggregateException: 发生一个或多个错误。 ---> System.UnauthorizedAccessException: 对路径“AutoMapper.dll”的访问被拒绝。
在 System.IO.Directory.DeleteHelper(String fullPath, String userPath, Boolean recursive, Boolean throwOnTopLevelDirectoryNotFound, WIN32_FIND_DATA& data)
在 System.IO.Directory.Delete(String fullPath, String userPath, Boolean recursive, Boolean checkHost)
在 Fettle.Core.CoverageAnalyser.d__5.MoveNext() 位置 c:\dev\fettle\src\Core\CoverageAnalyser.cs:行号 87
--- 内部异常堆栈跟踪的结尾 ---
在 System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
在 System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) 在 System.Threading.Tasks.Task
1.get_Result()
在 Fettle.Console.Program.AnalyseCoverage(ICoverageAnalyser coverageAnalyser, IOutputWriter outputWriter, Config config) 位置 c:\dev\fettle\src\Console\Program.cs:行号 165
在 Fettle.Console.Program.InternalEntryPoint(String[] args, Func3 mutationTestRunnerFactory, Func
2 coverageAnalyserFactory, ISourceControlIntegration sourceControlIntegration, IOutputWriter outputWriter) 位置 c:\dev\fettle\src\Console\Program.cs:行号 88
---> (内部异常 #0) System.UnauthorizedAccessException: 对路径“AutoMapper.dll”的访问被拒绝。
在 System.IO.Directory.DeleteHelper(String fullPath, String userPath, Boolean recursive, Boolean throwOnTopLevelDirectoryNotFound, WIN32_FIND_DATA& data)
在 System.IO.Directory.Delete(String fullPath, String userPath, Boolean recursive, Boolean checkHost)
在 Fettle.Core.CoverageAnalyser.d__5.MoveNext() 位置 c:\dev\fettle\src\Core\CoverageAnalyser.cs:行号 87<---
When Fettle instruments code as part of coverage analysis, it converts expression-bodied methods from, for example, this:
public int Sum(int a, int b) => a + b;
to this:
public int Sum(int a, int b)
{
// (instrumentation logic goes here)
return a + b;
}
But the instrumentation code incorrectly assumes that all expression-bodied methods return a value. And so, when instrumenting something like this:
public void Log(string s) => Console.WriteLine(s);
it will wrongly convert to this, which doesn't compile:
public void Log(string s)
{
// (instrumentation logic goes here)
return Console.WriteLine(s);
}
Investigate what's required.
Known issues:
mono
branchMSBuildWorkspace
not availableKnown potential issues:
This affects coverage analysis and mutation testing.
When Fettle instruments or mutates assemblies they should still contain any embedded resources that the original had. Tests may rely on these existing, so Fettle can produce false positives or fail coverage analysis.
Fettle doesn't currently support ??, as in a = b ?? c.
Following discussions on Gitter (https://gitter.im/fettle-mutation-testing/Lobby), the proposal is to mutate the code as is, rather than expanding out ?? into its simpler underlying form and then mutating that. I.e the proposal is to mutate a = b ?? c
to a = c ?? b
In the alternative, a = b ?? c
could be re-written as if (b != null) { a = b; } else { a = c; }
which could then be mutated using existing rules for the !=
.
However, this has at least two problems:
The current proposal provides an answer to the two problems above, but does raise a general problem of which this is a specific instance.
The general problem is to do with re-writing or other magic done behind the scenes by the compiler or run-time. In this case it is the syntactic sugar to do with ??. With this proposal, mutating and re-writing are not commutative. We're accepting this in the interests of getting something done that's simple and useful, rather than aiming for theoretical purity.
If you start with a = b ?? c
you could mutate then re-write, or re-write then mutate. With this proposal they don't lead to the same result.
a = b ?? c
mutates to a = c ?? b
and then re-writes to if (c != null) {a = c;} else {a = b;}
a = b ?? c
re-writes to if (b != null) {a = b;} else {a = c;}
and then mutates to if (b == null) {a = b; } else {a = c;}
This is not an issue, but a wish for an exclude filter:
So far it is possible to include source files and folder and that works very well, but we typically have our tests in a subfolder named 'Test' within the source project. Of course we could create sourceFileFilters for all files and folders that contain sources and leave the 'Test' folder out, but if we add additional sources and sourcefolders, we do have to adapt the config file every time.
So it would be much nicer to be able to simply exclude the 'Test' folder.
The configuration file is validated just before performing mutation testing (top of MutationTestRunner.Run()
method).
This validation happens after coverage analysis takes place. So any errors in configuration that affect coverage analysis will not result in a friendly error message but a crash.
This line in CoverageAnalyser.cs
:
var firstChildNode = methodNode.Body.ChildNodes().FirstOrDefault();
...throws a NullReferenceException
when .Body
is null, causing Fettle to quit.
.Body
will be null when a method doesn't have a "normal" body. Fettle already handles this for expression-bodied methods and abstract methods, but not partial method declarations. E.g.
public abstract void Thing();
Support mutation of ++
to --
and vice versa
And the same for *=
, /=
and %=
Saw some code in the wild that was being tested via a TestCaseSource
and produced surviving mutants, but when the test was refactored to use a foreach
instead (i.e. testing the same things but via a normal [Test]
), the mutants no longer survived.
It seems that Fettle doesn't expect test suits to complete with a status of "Skipped" (expects "Passed" or "Failed"). A skipped status seems quite possible, so should be supported.
Perhaps an easier way to implement the logic (in NUnitRunResult.Parse) would be to look at the number of test failures (//test-run/failures
) instead of the overall result (//test-run/result
) which can be misleading? I.e. I've seen a result of "Skipped" even though some tests still ran.
Stacktrace:
...An error ocurred that Fettle didn't expect.
System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: Unexpected NUnit test run result: "Skipped"
at Fettle.Core.Internal.NUnit.NUnitRunResults.Parse(XmlNode rootNode) in C:\dev\fettle\src\Core\Internal\NUnit\NUnitRunResults.cs:line 33
at Fettle.Core.Internal.NUnit.NUnitTestEngine.RunTests(IEnumerable`1 testAssemblyFilePaths, IEnumerable`1 testMethodNames, ITestEventListener testEventListener) in C:\dev\fettle\src\Core\Internal\NUnit\NUnitTestEngine.cs:line 66
at Fettle.Core.Internal.NUnit.NUnitTestEngine.RunTests(IEnumerable`1 testAssemblyFilePaths, IEnumerable`1 testMethodNames) in C:\dev\fettle\src\Core\Internal\NUnit\NUnitTestEngine.cs:line 25
at Fettle.Core.Internal.NUnit.NUnitTestEngine.RunAllTests(IEnumerable`1 testAssemblyFilePaths) in C:\dev\fettle\src\Core\Internal\NUnit\NUnitTestEngine.cs:line 30
at Fettle.Core.Internal.MutationJob.<Run>d__16.MoveNext() in C:\dev\fettle\src\Core\Internal\MutationJob.cs:line 75
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Fettle.Core.Internal.MutationJobList.<RunAll>d__2.MoveNext() in C:\dev\fettle\src\Core\Internal\MutationJobList.cs:line 57
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Fettle.Core.MutationTestRunner.<Run>d__5.MoveNext() in C:\dev\fettle\src\Core\MutationTestRunner.cs:line 47
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()
at Fettle.Console.Program.InternalEntryPoint(String[] args, Func`3 mutationTestRunnerFactory, Func`2 coverageAnalyserFactory, IOutputWriter outputWriter) in C:\dev\fettle\src\Console\Program.cs:line 72
---> (Inner Exception #0) System.InvalidOperationException: Unexpected NUnit test run result: "Skipped"
at Fettle.Core.Internal.NUnit.NUnitRunResults.Parse(XmlNode rootNode) in C:\dev\fettle\src\Core\Internal\NUnit\NUnitRunResults.cs:line 33
at Fettle.Core.Internal.NUnit.NUnitTestEngine.RunTests(IEnumerable`1 testAssemblyFilePaths, IEnumerable`1 testMethodNames, ITestEventListener testEventListener) in C:\dev\fettle\src\Core\Internal\NUnit\NUnitTestEngine.cs:line 66
at Fettle.Core.Internal.NUnit.NUnitTestEngine.RunTests(IEnumerable`1 testAssemblyFilePaths, IEnumerable`1 testMethodNames) in C:\dev\fettle\src\Core\Internal\NUnit\NUnitTestEngine.cs:line 25
at Fettle.Core.Internal.NUnit.NUnitTestEngine.RunAllTests(IEnumerable`1 testAssemblyFilePaths) in C:\dev\fettle\src\Core\Internal\NUnit\NUnitTestEngine.cs:line 30
at Fettle.Core.Internal.MutationJob.<Run>d__16.MoveNext() in C:\dev\fettle\src\Core\Internal\MutationJob.cs:line 75
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Fettle.Core.Internal.MutationJobList.<RunAll>d__2.MoveNext() in C:\dev\fettle\src\Core\Internal\MutationJobList.cs:line 57
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Fettle.Core.MutationTestRunner.<Run>d__5.MoveNext() in C:\dev\fettle\src\Core\MutationTestRunner.cs:line 47<---
If a method is OK for test coverage but has no contents that can be mutated, it is silently omitted from all output, even verbose. Having a list of methods (and possibly properties) that couldn't be mutated would help users not have a false sense of security / nasty surprises when they discover that mutation isn't checking everything they thought it was.
Currently users have to compile locally and copy the binaries to their project.
Currently we ignore some of the errors that may occur when a .sln (solution) file is read by Roslyn.
We need to check the Diagnostics
property of the workspace and throw an exception/return an error to the user if it contains any items after loading the solution.
We should have:
Other things:
I have built successfully from the source code (also HasSurvivingMutants project), but when I tried running .\src\Console\bin\Debug\Fettle.Console.exe -c .\fettle.config.example.yml it doesn't work. The error messages are shown below. Anyone has ideas? Thanks ahead!
An error ocurred that Fettle didn't expect.
System.AggregateException: One or more errors occurred. ---> System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.RuntimeAssembly.get_DefinedTypes()
at System.Composition.Hosting.ContainerConfiguration.<>c.b__16_0(Assembly a)
at System.Linq.Enumerable.d__172.MoveNext() at System.Composition.TypedParts.TypedPartExportDescriptorProvider..ctor(IEnumerable
1 types, AttributedModelProvider attributeContext)
at System.Composition.Hosting.ContainerConfiguration.CreateContainer()
at Microsoft.CodeAnalysis.Host.Mef.MefHostServices.Create(IEnumerable1 assemblies) at Microsoft.CodeAnalysis.Host.Mef.DesktopMefHostServices.get_DefaultServices() at Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create(IDictionary
2 properties)
at Fettle.Core.MSBuildWorkspaceFactory.Create() in fettle\src\Core\Internal\MSBuildWorkspaceFactory.cs:line 16
at Fettle.Core.Config.d__33.MoveNext() in fettle\src\Core\Config.cs:line 66
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Fettle.Core.Config.<HasAnyMutatableDocuments>d__34.MoveNext() in fettle\src\Core\Config.cs:line 73 --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task
1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task1.get_Result() at Fettle.Console.Program.Run(String[] args, ITestRunnerFactory testRunnerFactory, Func
4 mutationTestRunnerFactory, Func2 coverageAnalyserFactory, ISourceControlIntegration sourceControlIntegration, IOutputWriter outputWriter) in fettle\src\Console\Program.cs:line 100 ---> (Inner Exception #0) System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module) at System.Reflection.RuntimeAssembly.get_DefinedTypes() at System.Composition.Hosting.ContainerConfiguration.<>c.<WithAssemblies>b__16_0(Assembly a) at System.Linq.Enumerable.<SelectManyIterator>d__17
2.MoveNext()
at System.Composition.TypedParts.TypedPartExportDescriptorProvider..ctor(IEnumerable1 types, AttributedModelProvider attributeContext) at System.Composition.Hosting.ContainerConfiguration.CreateContainer() at Microsoft.CodeAnalysis.Host.Mef.MefHostServices.Create(IEnumerable
1 assemblies)
at Microsoft.CodeAnalysis.Host.Mef.DesktopMefHostServices.get_DefaultServices()
at Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create(IDictionary2 properties) at Fettle.Core.MSBuildWorkspaceFactory.Create() in fettle\src\Core\Internal\MSBuildWorkspaceFactory.cs:line 16 at Fettle.Core.Config.<FindMutatableDocuments>d__33.MoveNext() in fettle\src\Core\Config.cs:line 66 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()
at Fettle.Core.Config.d__34.MoveNext() in fettle\src\Core\Config.cs:line 73<---
Looks like we wait indefinitely for tests to complete after mutation.
But they could hang and/or mutation could introduce a hang.
So we should time out after some period.
When timed out should this result in a different kind of result which is neither pass or fail? E.g. "timed out" instead of "no mutant survived" or "a mutant survived"?
Constructors are not included in coverage analysis or mutation testing by Fettle.
Code that needs to change:
MemberDeclarationSyntaxExtensions.CanInstrument
method:if (memberDeclaration is MethodDeclarationSyntax methodDeclaration)
{
return CanInstrumentMethod(methodDeclaration);
}
else if (memberDeclaration is PropertyDeclarationSyntax propertyDeclaration)
{
return CanInstrumentProperty(propertyDeclaration);
}
Need to handle memberDeclaration
being of type ConstructorDeclarationSyntax
.
SyntaxNodeExtensions.NameOfContainingMember
method:if (node is NamespaceDeclarationSyntax @namespace) foundNamespace = @namespace;
else if (node is ClassDeclarationSyntax @class) foundClass = @class;
else if (node is MethodDeclarationSyntax method) foundMethod = method;
else if (node is PropertyDeclarationSyntax property) foundProperty = property;
Need to handle node
being of type ConstructorDeclarationSyntax
The current filtering behaviour is affected by an apparent bug in the glob library.
To get around this we could:
As part of coverage analysis and probably during mutation testing too.
If the explicit attribute is on a method, then it is correctly ignored.
But if it's on a class, then it is not ignored and the test(s) are run.
This is caused by the NUnitExploreResults.Parse
method only looks at test-case
elements in isolation. Instead, it should discard test-case
s whose ancestor test-suite
s' runstate
is not runnable
.
E.g. via a command line switch.
Default behaviour is to only mutate covered code. If users aren't keeping an eye on their coverage metrics, they may never spot code that is completely uncovered. Running fettle over their code base could give them a false sense of security.
Disabling the analysis would also allow a work-around for the OOM issue (#20).
This is Raghav's idea
Work out which files changed in the most recent commit, and only mutate those.
This feels like it could make running Fettle an "every CI build" thing.
There is a core dump if you try to use a struct that has a mutatable constructor such as
public struct MyStruct
{
int minAllowed, maxAllowed;
public MyStruct(int min, int max)
{
if (min > max) {throw new Exception("oh dear");}
minAllowed = min;
maxAllowed = max;
}
}
The core dump happens in NUnitCoverageCollector::onTestComplete. The member in memberIdsToNames that matches the key has a null value.
The cause of the null value is SyntaxNodeExtensions::NameOfContainingMember. It starts with the parameter list for the struct's constructor, goes up a level and correctly finds a match for MemberDeclarationSyntax (because ConstructorDeclarationSyntax = grand-child of MemberDeclarationSyntax). It goes up another level and fails. It finds StructDeclarationSyntax rather than ClassDeclarationSyntax and they are peers rather than parent/child, so there is no match. As the class hasn't been found, the method returns null, which is fed into memberIdsToNames.
If this sublcass:
public class Thingy
{
public bool IsThing => true;
}
...is added to the PartiallyTestedNumberComparison
class in the examples, then when coverage analysis is performed a crash occurs within Roslyn:
System.AggregateException: One or more errors occurred. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.CodeAnalysis.CSharp.CSharpExtensions.Kind(SyntaxNode node)
at Microsoft.CodeAnalysis.CSharp.CodeGeneration.CSharpSyntaxGenerator.GetDeclarationKind(SyntaxNode declaration)
at Microsoft.CodeAnalysis.CSharp.CodeGeneration.CSharpSyntaxGenerator.AsNodeLike(SyntaxNode existingNode, SyntaxNode newNode)
at Microsoft.CodeAnalysis.CSharp.CodeGeneration.CSharpSyntaxGenerator.ReplaceNode(SyntaxNode root, SyntaxNode declaration, SyntaxNode newDeclaration)
at Microsoft.CodeAnalysis.Editing.SyntaxEditor.ReplaceChange.Apply(SyntaxNode root, SyntaxGenerator generator)
at Microsoft.CodeAnalysis.Editing.SyntaxEditor.GetChangedRoot()
at Microsoft.CodeAnalysis.Editing.DocumentEditor.GetChangedDocument()
at Fettle.Core.Internal.Instrumentation.<InstrumentDocument>d__1.MoveNext() in C:\dev\fettle\src\Core\Internal\Instrumentation.cs:line 45
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileProject>d__7.MoveNext() in C:\dev\fettle\src\Core\CoverageAnalyser.cs:line 121
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileMultipleProjects>d__6.MoveNext() in C:\dev\fettle\src\Core\CoverageAnalyser.cs:line 97
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\dev\fettle\src\Core\CoverageAnalyser.cs:line 48
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()
at Fettle.Console.Program.AnalyseCoverage(ICoverageAnalyser coverageAnalyser, IOutputWriter outputWriter, Config config) in C:\dev\fettle\src\Console\Program.cs:line 123
at Fettle.Console.Program.InternalEntryPoint(String[] args, Func`3 mutationTestRunnerFactory, Func`2 coverageAnalyserFactory, IOutputWriter outputWriter) in C:\dev\fettle\src\Console\Program.cs:line 71
---> (Inner Exception #0) System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.CodeAnalysis.CSharp.CSharpExtensions.Kind(SyntaxNode node)
at Microsoft.CodeAnalysis.CSharp.CodeGeneration.CSharpSyntaxGenerator.GetDeclarationKind(SyntaxNode declaration)
at Microsoft.CodeAnalysis.CSharp.CodeGeneration.CSharpSyntaxGenerator.AsNodeLike(SyntaxNode existingNode, SyntaxNode newNode)
at Microsoft.CodeAnalysis.CSharp.CodeGeneration.CSharpSyntaxGenerator.ReplaceNode(SyntaxNode root, SyntaxNode declaration, SyntaxNode newDeclaration)
at Microsoft.CodeAnalysis.Editing.SyntaxEditor.ReplaceChange.Apply(SyntaxNode root, SyntaxGenerator generator)
at Microsoft.CodeAnalysis.Editing.SyntaxEditor.GetChangedRoot()
at Microsoft.CodeAnalysis.Editing.DocumentEditor.GetChangedDocument()
at Fettle.Core.Internal.Instrumentation.<InstrumentDocument>d__1.MoveNext() in C:\dev\fettle\src\Core\Internal\Instrumentation.cs:line 45
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileProject>d__7.MoveNext() in C:\dev\fettle\src\Core\CoverageAnalyser.cs:line 121
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Fettle.Core.CoverageAnalyser.<InstrumentThenCompileMultipleProjects>d__6.MoveNext() in C:\dev\fettle\src\Core\CoverageAnalyser.cs:line 97
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Fettle.Core.CoverageAnalyser.<AnalyseCoverage>d__5.MoveNext() in C:\dev\fettle\src\Core\CoverageAnalyser.cs:line 48<---
When trying to understand behaviour it would be useful to have more info about what Fettle is doing.
The idea is that a user would enable diagnostics logging via a command-line option (like with quiet mode). Outputting to the console directly (instead of a file) should be fine initially.
Things to log might include:
Coverage analysis and mutation testing analysis both iterate over methods, looking for syntax nodes to mutate.
This ignores, for example, expressions within properties or field initialisation.
E.g.
public class Thing
{
private int a = 5 * 100; // is not mutated
private int b;
public int C1 => a + b; // is not mutated
public int C2 { get { return a + b; } } // is not mutated
public int D()
{
return a + b; // is mutated
}
}
Note that Fettle does support expression-bodied methods (support added in #18).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.