public static TestCase GetVSTestCaseFromMSpecTestCase(string source, MSpecTestCase mspecTestCase, bool disableFullTestNames, Uri testRunnerUri) { VisualStudioTestIdentifier vsTest = mspecTestCase.ToVisualStudioTestIdentifier(); TestCase testCase = new TestCase(vsTest.FullyQualifiedName, testRunnerUri, source) { DisplayName = disableFullTestNames ? mspecTestCase.SpecificationDisplayName : $"{mspecTestCase.ContextDisplayName} it {mspecTestCase.SpecificationDisplayName}", CodeFilePath = mspecTestCase.CodeFilePath, LineNumber = mspecTestCase.LineNumber }; Trait classTrait = new Trait(Strings.TRAIT_CLASS, mspecTestCase.ClassName); Trait subjectTrait = new Trait(Strings.TRAIT_SUBJECT, string.IsNullOrEmpty(mspecTestCase.Subject) ? Strings.TRAIT_SUBJECT_NOSUBJECT : mspecTestCase.Subject); testCase.Traits.Add(classTrait); testCase.Traits.Add(subjectTrait); if (mspecTestCase.Tags != null) { foreach (var tag in mspecTestCase.Tags) { if (!string.IsNullOrEmpty(tag)) { Trait tagTrait = new Trait(Strings.TRAIT_TAG, tag); testCase.Traits.Add(tagTrait); } } } Debug.WriteLine($"TestCase {testCase.FullyQualifiedName}"); return(testCase); }
public IEnumerable<MSpecTestCase> DiscoverSpecs(string assemblyFilePath) { if (!this.AssemblyContainsMSpecReference(assemblyFilePath) || !this.SourceDirectoryContainsMSpec(assemblyFilePath)) return new List<MSpecTestCase>(); assemblyFilePath = Path.GetFullPath(assemblyFilePath); if (!File.Exists(assemblyFilePath)) { throw new ArgumentException("Could not find file: " + assemblyFilePath); } this.AssemblyFilename = assemblyFilePath; // make sure that cecil looks in the assembly path for mspec (+ related assemblies) first this.AssemblyResolver = new ScopedAssemblyResolver(Path.GetDirectoryName(assemblyFilePath)); this.ReaderParameters = new ReaderParameters() { ReadSymbols = true, AssemblyResolver = AssemblyResolver }; List<MSpecTestCase> list = new List<MSpecTestCase>(); List<IDelegateFieldScanner> fieldScanners = new List<IDelegateFieldScanner>(); fieldScanners.Add(new ItDelegateFieldScanner()); fieldScanners.Add(new CustomDelegateFieldScanner()); // statically inspect the types in the assembly using mono.cecil var assembly = AssemblyDefinition.ReadAssembly(this.AssemblyFilename, this.ReaderParameters); foreach (TypeDefinition type in GetNestedTypes(assembly.MainModule.Types)) { // if a type is an It delegate generate some test case info for it foreach (FieldDefinition fieldDefinition in type.Fields.Where(x => !x.Name.Contains("__Cached"))) { foreach (IDelegateFieldScanner scanner in fieldScanners) { if (scanner.ProcessFieldDefinition(fieldDefinition)) { string typeName = NormalizeCecilTypeName(type.Name); string typeFullName = NormalizeCecilTypeName(type.FullName); MSpecTestCase testCase = new MSpecTestCase() { ClassName = typeName, ContextFullType = typeFullName, SpecificationName = fieldDefinition.Name, ContextDisplayName = GetContextDisplayName(type), SpecificationDisplayName = fieldDefinition.Name.Replace("_", " "), }; // get the source code location for the It delegate from the PDB file using mono.cecil.pdb this.UpdateTestCaseWithLocation(type, testCase); list.Add(testCase); break; } } } } return list.Select(x => x); }
private void PopulateBehaviorField(MSpecTestCase testCase, BehaviorSpecification specification) { if (behaviorProperty?.GetValue(specification) is FieldInfo field) { testCase.BehaviorFieldName = field.Name; testCase.BehaviorFieldType = field.FieldType.GenericTypeArguments.FirstOrDefault()?.FullName; } }
private void UpdateTestCaseWithLocation(TypeDefinition type, MSpecTestCase testCase) { if (!type.HasMethods) { return; } string fieldFullName = testCase.SpecificationName.Replace(" ", "_"); MethodDefinition methodDefinition = type.Methods.Where(x => x.IsConstructor && x.Parameters.Count == 0 && x.Name.EndsWith(".ctor")).SingleOrDefault(); if (methodDefinition.HasBody) { // check if there is a subject attribute if (type.HasCustomAttributes) { List <CustomAttribute> list = type.CustomAttributes.Where(x => x.AttributeType.FullName == "Machine.Specifications.SubjectAttribute").ToList(); if (list.Count > 0 && list[0].ConstructorArguments.Count > 0) { testCase.Subject = Enumerable.First <CustomAttributeArgument>((IEnumerable <CustomAttributeArgument>)list[0].ConstructorArguments).Value.ToString(); } List <CustomAttribute> tagsList = type.CustomAttributes.Where(x => x.AttributeType.FullName == "Machine.Specifications.TagsAttribute").ToList(); if (tagsList.Count > 0 && tagsList[0].ConstructorArguments.Count > 0) { List <string> tags = new List <string>(); tags.Add(tagsList[0].ConstructorArguments[0].Value.ToString()); if (tagsList[0].ConstructorArguments.Count == 2) { foreach (CustomAttributeArgument additionalTag in ((IEnumerable <CustomAttributeArgument>)tagsList[0].ConstructorArguments[1].Value)) { tags.Add(additionalTag.Value.ToString()); } } testCase.Tags = tags.ToArray(); } } // now find the source code location Instruction instruction = methodDefinition.Body.Instructions.Where(x => x.Operand != null && x.Operand.GetType().IsAssignableFrom(typeof(FieldDefinition)) && ((MemberReference)x.Operand).Name == fieldFullName).SingleOrDefault(); while (instruction != null) { if (instruction.SequencePoint != null && instruction.SequencePoint.StartLine != PdbHiddenLine) { testCase.CodeFilePath = instruction.SequencePoint.Document.Url; testCase.LineNumber = instruction.SequencePoint.StartLine; break; } instruction = instruction.Previous; } } }
private IEnumerable <MSpecTestCase> CreateTestCase(Context context, SourceCodeLocationFinder locationFinder) { foreach (Specification spec in context.Specifications.ToList()) { MSpecTestCase testCase = new MSpecTestCase(); testCase.ClassName = context.Type.Name; testCase.ContextFullType = context.Type.FullName; testCase.ContextDisplayName = GetContextDisplayName(context.Type); testCase.SpecificationName = spec.FieldInfo.Name; testCase.SpecificationDisplayName = spec.Name; string fieldDeclaringType; if (spec.FieldInfo.DeclaringType.GetTypeInfo().IsGenericType&& !spec.FieldInfo.DeclaringType.GetTypeInfo().IsGenericTypeDefinition) { fieldDeclaringType = spec.FieldInfo.DeclaringType.GetGenericTypeDefinition().FullName; } else { fieldDeclaringType = spec.FieldInfo.DeclaringType.FullName; } SourceCodeLocationInfo locationInfo = locationFinder.GetFieldLocation(fieldDeclaringType, spec.FieldInfo.Name); if (locationInfo != null) { testCase.CodeFilePath = locationInfo.CodeFilePath; testCase.LineNumber = locationInfo.LineNumber; } if (spec is BehaviorSpecification behaviorSpec) { PopulateBehaviorField(testCase, behaviorSpec); } if (context.Tags != null) { testCase.Tags = context.Tags.Select(tag => tag.Name).ToArray(); } if (context.Subject != null) { testCase.Subject = context.Subject.FullConcern; } yield return(testCase); } }
private IEnumerable<MSpecTestCase> CreateTestCase(Context context, string assemblyPath) { SourceCodeLocationFinder locationFinder = new SourceCodeLocationFinder(assemblyPath); foreach (Specification spec in context.Specifications.ToList()) { MSpecTestCase testCase = new MSpecTestCase(); testCase.ClassName = context.Type.Name; testCase.ContextFullType = context.Type.FullName; testCase.ContextDisplayName = GetContextDisplayName(context.Type); testCase.SpecificationName = spec.FieldInfo.Name; testCase.SpecificationDisplayName = spec.Name; string fieldDeclaringType; if (spec.FieldInfo.DeclaringType.IsGenericType && !spec.FieldInfo.DeclaringType.IsGenericTypeDefinition) fieldDeclaringType = spec.FieldInfo.DeclaringType.GetGenericTypeDefinition().FullName; else fieldDeclaringType = spec.FieldInfo.DeclaringType.FullName; SourceCodeLocationInfo locationInfo = locationFinder.GetFieldLocation(fieldDeclaringType, spec.FieldInfo.Name); if (locationInfo != null) { testCase.CodeFilePath = locationInfo.CodeFilePath; testCase.LineNumber = locationInfo.LineNumber; } if (context.Tags != null) testCase.Tags = context.Tags.Select(tag => tag.Name).ToArray(); if (context.Subject != null) testCase.Subject = context.Subject.FullConcern; yield return testCase; } }
public static TestCase GetVSTestCaseFromMSpecTestCase(string source, MSpecTestCase mspecTestCase, bool disableFullTestNames, Uri testRunnerUri, Func <string, string, dynamic> traitCreator) { VisualStudioTestIdentifier vsTest = mspecTestCase.ToVisualStudioTestIdentifier(); TestCase testCase = new TestCase(vsTest.FullyQualifiedName, testRunnerUri, source) { DisplayName = disableFullTestNames ? mspecTestCase.SpecificationDisplayName : $"{mspecTestCase.ContextDisplayName} it {mspecTestCase.SpecificationDisplayName}", CodeFilePath = mspecTestCase.CodeFilePath, LineNumber = mspecTestCase.LineNumber }; if (MSpecTestAdapter.UseTraits) { dynamic dynTestCase = testCase; dynamic classTrait = traitCreator(Strings.TRAIT_CLASS, mspecTestCase.ClassName); dynamic subjectTrait = traitCreator(Strings.TRAIT_SUBJECT, string.IsNullOrEmpty(mspecTestCase.Subject) ? Strings.TRAIT_SUBJECT_NOSUBJECT : mspecTestCase.Subject); dynTestCase.Traits.Add(classTrait); dynTestCase.Traits.Add(subjectTrait); if (mspecTestCase.Tags != null) { foreach (var tag in mspecTestCase.Tags) { if (!string.IsNullOrEmpty(tag)) { dynamic tagTrait = traitCreator(Strings.TRAIT_TAG, tag); dynTestCase.Traits.Add(tagTrait); } } } } Debug.WriteLine(string.Format("TestCase {0}", (object)testCase.FullyQualifiedName)); return(testCase); }
private void UpdateTestCaseWithLocation(TypeDefinition type, MSpecTestCase testCase) { if (!type.HasMethods) { return; } string fieldFullName = testCase.SpecificationName.Replace(" ", "_"); MethodDefinition methodDefinition = type.Methods.Where(x => x.IsConstructor && x.Parameters.Count == 0 && x.Name.EndsWith(".ctor")).SingleOrDefault(); if (methodDefinition.HasBody) { // check if there is a subject attribute if (type.HasCustomAttributes) { List<CustomAttribute> list = type.CustomAttributes.Where(x => x.AttributeType.FullName == "Machine.Specifications.SubjectAttribute").ToList(); if (list.Count > 0 && list[0].ConstructorArguments.Count > 0) { testCase.Subject = Enumerable.First<CustomAttributeArgument>((IEnumerable<CustomAttributeArgument>)list[0].ConstructorArguments).Value.ToString(); } List<CustomAttribute> tagsList = type.CustomAttributes.Where(x => x.AttributeType.FullName == "Machine.Specifications.TagsAttribute").ToList(); if (tagsList.Count > 0 && tagsList[0].ConstructorArguments.Count > 0) { List<string> tags = new List<string>(); tags.Add(tagsList[0].ConstructorArguments[0].Value.ToString()); if (tagsList[0].ConstructorArguments.Count == 2) { foreach (CustomAttributeArgument additionalTag in ((IEnumerable<CustomAttributeArgument>)tagsList[0].ConstructorArguments[1].Value)) { tags.Add(additionalTag.Value.ToString()); } } testCase.Tags = tags.ToArray(); } } // now find the source code location Instruction instruction = methodDefinition.Body.Instructions.Where(x => x.Operand != null && x.Operand.GetType().IsAssignableFrom(typeof(FieldDefinition)) && ((MemberReference)x.Operand).Name == fieldFullName).SingleOrDefault(); while (instruction != null) { if (instruction.SequencePoint != null && instruction.SequencePoint.StartLine != PdbHiddenLine) { testCase.CodeFilePath = instruction.SequencePoint.Document.Url; testCase.LineNumber = instruction.SequencePoint.StartLine; break; } instruction = instruction.Previous; } } }
public IEnumerable <MSpecTestCase> DiscoverSpecs(string assemblyFilePath) { if (!this.AssemblyContainsMSpecReference(assemblyFilePath) || !this.SourceDirectoryContainsMSpec(assemblyFilePath)) { return(new List <MSpecTestCase>()); } assemblyFilePath = Path.GetFullPath(assemblyFilePath); if (!File.Exists(assemblyFilePath)) { throw new ArgumentException("Could not find file: " + assemblyFilePath); } this.AssemblyFilename = assemblyFilePath; // make sure that cecil looks in the assembly path for mspec (+ related assemblies) first this.AssemblyResolver = new ScopedAssemblyResolver(Path.GetDirectoryName(assemblyFilePath)); this.ReaderParameters = new ReaderParameters() { ReadSymbols = true, AssemblyResolver = AssemblyResolver }; List <MSpecTestCase> list = new List <MSpecTestCase>(); List <IDelegateFieldScanner> fieldScanners = new List <IDelegateFieldScanner>(); fieldScanners.Add(new ItDelegateFieldScanner()); fieldScanners.Add(new CustomDelegateFieldScanner()); // statically inspect the types in the assembly using mono.cecil var assembly = AssemblyDefinition.ReadAssembly(this.AssemblyFilename, this.ReaderParameters); foreach (TypeDefinition type in GetNestedTypes(assembly.MainModule.Types)) { // if a type is an It delegate generate some test case info for it foreach (FieldDefinition fieldDefinition in type.Fields.Where(x => !x.Name.Contains("__Cached"))) { foreach (IDelegateFieldScanner scanner in fieldScanners) { if (scanner.ProcessFieldDefinition(fieldDefinition)) { string typeName = NormalizeCecilTypeName(type.Name); string typeFullName = NormalizeCecilTypeName(type.FullName); MSpecTestCase testCase = new MSpecTestCase() { ClassName = typeName, ContextFullType = typeFullName, SpecificationName = fieldDefinition.Name, ContextDisplayName = GetContextDisplayName(type), SpecificationDisplayName = fieldDefinition.Name.Replace("_", " "), }; // get the source code location for the It delegate from the PDB file using mono.cecil.pdb this.UpdateTestCaseWithLocation(type, testCase); list.Add(testCase); break; } } } } return(list.Select(x => x)); }
public static VisualStudioTestIdentifier ToVisualStudioTestIdentifier(this MSpecTestCase specification) { return(new VisualStudioTestIdentifier(String.Format(CultureInfo.InvariantCulture, "{0}::{1}", specification.ContextFullType, specification.SpecificationName))); }