private Dictionary <string, ICollection <IMemberDefinition> > InstrumentAndSelect(IEnumerable <string> programModules, IEnumerable <string> testModules) { AnalyzerParameters analyzerParameters = new AnalyzerParameters(args.DependencyCollectionGranularity, !args.NoSmartChecksums); Analyzer analyzer = args.TestingFramework.GetAnalyzer(analyzerParameters); analysisStopwatch = new Stopwatch(); analysisStopwatch.Start(); Dictionary <string, ICollection <IMemberDefinition> > moduleToAffectedTests = analyzer.Analyze(testModules, programModules); analysisStopwatch.Stop(); ModuleDefinition dependencyMonitorModule = CILTransformer.GetModuleDefinition(CommonPaths.DependencyMonitorDLLPath); InstrumentatorParameters instrumentatorParameters = new InstrumentatorParameters(dependencyMonitorModule, args.TestingFramework, args.InstrumentationStrategy, args.InstrumentationArgumentsType, args.InstrumentAtMethodBeginning); Instrumentator instrumentator = new Instrumentator(instrumentatorParameters); foreach (var modulePath in testModules) { string destination = Path.Combine(Path.GetDirectoryName(modulePath), "DependencyMonitor.dll"); File.Copy(CommonPaths.DependencyMonitorDLLPath, destination, true); string configuration = Path.Combine(Path.GetDirectoryName(modulePath), Paths.DependencyMonitorConfigurationFileName); File.WriteAllText(configuration, Paths.OutputDirectory); } instrumentationStopwatch = new Stopwatch(); instrumentationStopwatch.Start(); bool instrument = false; foreach (var tests in moduleToAffectedTests.Values) { if (tests.Any()) { // instruments if there are some tests to be run instrument = true; break; } } if (instrument) { instrumentator.Instrument(moduleToAffectedTests, programModules); } instrumentationStopwatch.Stop(); return(moduleToAffectedTests); }
/// <summary> /// Detects and returns collection of Test Classes that are affected by recent program changes. /// It does so by comparing checksums of the old code revision with newly calculated checksums. /// Guarantees: There will be no duplicates in the returned collection. /// </summary> /// <param name="testModulePaths">List of paths to test modules (modules containing test cases).</param> /// <param name="programModulePaths">List of paths to program modules (modules containing program under test).</param> /// <returns>TypeDefinition of affected test classes.</returns> public Dictionary <string, ICollection <IMemberDefinition> > Analyze(IEnumerable <string> testModulePaths, IEnumerable <string> programModulePaths) { Dictionary <string, ICollection <IMemberDefinition> > moduleToAffectedTests = new Dictionary <string, ICollection <IMemberDefinition> >(); IEnumerable <string> allModules = Enumerable.Union(programModulePaths, testModulePaths); if (Instrumentator.AreInstrumented(allModules)) { // if modules are already instrumented that means nothing changed from the last run logger.Info("Modules already instrumented. Do not select any test for the run."); return(moduleToAffectedTests); } // read old checksums Dictionary <string, string> oldChecksums = LoadChecksums(); // compute new checksums Dictionary <string, string> newChecksums = ComputeChecksums(allModules); // store new checksums to a file StoreChecksums(newChecksums); // find all tests foreach (string testModulePath in testModulePaths) { IEnumerable <IMemberDefinition> tests = null; switch (parameters.DependencyCollectionGranularity) { case DependencyCollectionGranularity.Class: tests = FindAllTestClasses(testModulePath); break; case DependencyCollectionGranularity.Method: tests = FindAllTestMethods(testModulePath); break; default: throw new Exception("Unsupported Collection Granularity"); } // find tests that are affected by recent program changes ICollection <IMemberDefinition> affectedTests = FindAffectedTests(tests, oldChecksums, newChecksums); moduleToAffectedTests.Add(testModulePath, affectedTests); } return(moduleToAffectedTests); }