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);
        }
示例#3
0
 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;
                }
            }
        }
示例#5
0
        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)));
 }