Esempio n. 1
0
        /// <summary>
        /// Determines if a method is a valid test method.
        /// </summary>
        /// <param name="testMethodInfo"> The reflected method. </param>
        /// <param name="logger"> Logs message for test engine. </param>
        /// <returns> Return true if a method is a valid test method. </returns>
        internal virtual bool IsValidTestMethod(MethodInfo testMethodInfo, IMUnitLogger logger)
        {
            if (!_reflectionWorker.HasAttributeIsOrDerivedFrom(testMethodInfo, typeof(TestMethodAttribute), false))
            {
                return(false);
            }

            // Generic method Definitions are not valid.
            if (testMethodInfo.IsGenericMethodDefinition)
            {
                var message = string.Format(CultureInfo.CurrentCulture, Errors.UTA_ErrorGenericTestMethod, testMethodInfo.DeclaringType.FullName, testMethodInfo.Name);
                logger?.RecordMessage(MessageLevel.Warning, message);
                return(false);
            }

            // Todo: Decide wheter parameter count matters.
            // The isGenericMethod check below id to verify that there are no closed generic methods slipping through.
            // Closed generic methods being GenericMethod<int> and open being GenericMethod<T>.
            var isValidTestMethod = testMethodInfo.IsPublic && !testMethodInfo.IsAbstract && !testMethodInfo.IsStatic &&
                                    !testMethodInfo.IsGenericMethod &&
                                    testMethodInfo.ReturnType == typeof(void);

            if (!isValidTestMethod)
            {
                var message = string.Format(CultureInfo.CurrentCulture, Errors.UTF_ErrorIncorrectTestMethodSignature, testMethodInfo.DeclaringType.FullName, testMethodInfo.Name);
                logger?.RecordMessage(MessageLevel.Error, message);
                return(false);
            }

            return(true);
        }
Esempio n. 2
0
        /// <summary>
        /// Gets an instance of <see cref="IMUnitLogger"/> that is specified in MUnit.config .
        /// </summary>
        /// <returns> Returns an implementation of <see cref="IMUnitLogger"/>. </returns>
        public static IMUnitLogger GetLogger()
        {
            if (_mLogger == null)
            {
                Assembly assembly = Assembly.LoadFrom(MUnitConfiguration.LoggerAssembly);
                if (Enum.TryParse <MessageLevel>(MUnitConfiguration.LoggerLevel, out MessageLevel messageLevel))
                {
                    _mLogger = (IMUnitLogger)Activator.CreateInstance(assembly.GetType(MUnitConfiguration.LoggerType), messageLevel);
                }
                else
                {
                    throw new InvalidDataException(
                              string.Format(
                                  System.Globalization.CultureInfo.InvariantCulture,
                                  Resources.Errors.UTA_CantParseLoggerLevel,
                                  MessageLevel.Information,
                                  MessageLevel.Warning,
                                  MessageLevel.Error,
                                  MessageLevel.Trace,
                                  MessageLevel.Debug));
                }
            }

            return(_mLogger);
        }
Esempio n. 3
0
        /// <summary>
        /// Check if the method is a valid preparation method.
        /// </summary>
        /// <param name="prepMethodInfo"> Method to be checked. </param>
        /// <param name="logger"> Logs information. </param>
        /// <returns> Return true if the method is a valid preparation method. </returns>
        internal bool IsValidPrepMethod(MethodInfo prepMethodInfo, IMUnitLogger logger)
        {
            if (!_reflectionWorker.HasAttributeDerivedFrom(prepMethodInfo, typeof(SupportingAttribute), false))
            {
                return(false);
            }

            bool isTestPrep = _reflectionWorker.HasAttributeIsOrDerivedFrom(prepMethodInfo, typeof(TestCleanupAttribute), false) ||
                              _reflectionWorker.HasAttributeIsOrDerivedFrom(prepMethodInfo, typeof(TestInitializeAttribute), false);

            var isValidTestMethod = prepMethodInfo.IsPublic &&
                                    !prepMethodInfo.IsAbstract &&
                                    (prepMethodInfo.IsStatic || isTestPrep) &&
                                    prepMethodInfo.GetParameters().Length == 0 &&
                                    prepMethodInfo.ReturnType == typeof(void);

            if (!isValidTestMethod)
            {
                string message = string.Format(
                    CultureInfo.CurrentCulture,
                    Errors.UTF_IncorrectPrepMethodSignature,
                    prepMethodInfo.DeclaringType.FullName,
                    prepMethodInfo.Name,
                    _reflectionWorker.GetAttributeAssignableTo(prepMethodInfo, typeof(SupportingAttribute), false).GetType().Name,
                    isTestPrep ? string.Empty : "static, ");

                logger?.RecordMessage(MessageLevel.Error, message);
                return(false);
            }

            return(isValidTestMethod);
        }
Esempio n. 4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TestCycleGraph"/> class.
        /// </summary>
        /// <param name="root">Where test cycle stats.</param>
        /// <param name="logger"> Logs information. </param>
        public TestCycleGraph(ITestCycle root, IMUnitLogger logger)
        {
            ThrowUtilities.NullArgument(root, nameof(root));

            _root = root;
            _testCycles.Add(root.ID, root);
            this.Logger = logger;
        }
Esempio n. 5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MUnitWire"/> class.
        /// </summary>
        /// <param name="testEngine"> Test engine supported by this transporter. </param>
        /// <param name="transporter"> Transporter used for IPC. </param>
        public MUnitWire(ITestEngine testEngine, ITransporter transporter)
        {
            ThrowUtilities.NullArgument(testEngine, nameof(testEngine));
            ThrowUtilities.NullArgument(transporter, nameof(transporter));

            _logger      = testEngine.Logger;
            _transporter = transporter;
            _testEngine  = testEngine;
        }
Esempio n. 6
0
        /// <inheritdoc/>
        public void RunTests(IEnumerable <string> sources, int testRunID, IMUnitLogger logger)
        {
            _testCycles = DiscoverTests(sources);
            foreach (ITestMethodContext context in _testCycles.TestContextLookup.Values)
            {
                context.SetActive(_testCycles);
            }

            _testCycles.Run(testRunID);
        }
Esempio n. 7
0
        /// <inheritdoc/>
        public void RunTests(IEnumerable <Guid> guids, int testRunID, IMUnitLogger logger)
        {
            ThrowUtilities.NullArgument(guids, nameof(guids));
            ThrowUtilities.NullArgument(logger, nameof(logger));

            foreach (Guid guid in guids)
            {
                _testCycles.TestContextLookup[guid].SetActive(_testCycles);
            }

            _testCycles.Run(testRunID);
        }
Esempio n. 8
0
        /// <summary>
        /// Determines if a type is a valid test class for this adapter.
        /// </summary>
        /// <param name="type">The reflected type.</param>
        /// <param name="logger">Used to record information.</param>
        /// <returns>Return true if it is a valid test class.</returns>
        internal virtual bool IsValidTestClass(Type type, IMUnitLogger logger)
        {
            if (type.IsClass && _reflectionWorker.GetAttributesHaveBase(type, typeof(TestClassAttribute), false) != null)
            {
                var isPublic = type.IsPublic || (type.IsNested && type.IsNestedPublic);

                // non-public class
                if (!isPublic)
                {
                    var warning = string.Format(CultureInfo.CurrentCulture, Errors.UTA_ErrorNonPublicTestClass, type.FullName);
                    logger?.RecordMessage(MessageLevel.Warning, warning);
                    return(false);
                }

                // Generic class
                if (type.IsGenericTypeDefinition && !type.IsAbstract)
                {
                    // In IDE generic classes that are not abstract are treated as not runnable. Keep consistence.
                    var warning = string.Format(CultureInfo.CurrentCulture, Errors.UTA_ErrorNonPublicTestClass, type.FullName);
                    logger?.RecordMessage(MessageLevel.Warning, warning);
                    return(false);
                }

                // Class is not valid if the testContext property is incorrect
                if (!this.HasCorrectTestContextSignature(type))
                {
                    var warning = string.Format(CultureInfo.CurrentCulture, Errors.UTA_ErrorInValidTestContextSignature, type.FullName);
                    logger?.RecordMessage(MessageLevel.Warning, warning);
                    return(false);
                }

                // Abstract test classes can be base classes for derived test classes.
                //   There is no way to see if there are derived test classes.
                //   Thus if a test class is abstract, just ignore all test methods from it
                //   (they will be visible in derived classes). No warnings (such as test method, deployment item,
                //   etc attribute is defined on the class) will be generated for this class:
                // What we do is:
                //   - report the class as "not valid" test class. This will cause to skip enumerating tests from it.
                //   - Do not generate warnings/do not create NOT RUNNABLE tests.
                if (type.IsAbstract)
                {
                    return(false);
                }

                return(true);
            }

            return(false);
        }
Esempio n. 9
0
        public void Initialize(IMUnitLogger logger, string path)
        {
            ThrowUtilities.NullArgument(logger, nameof(logger));

            try
            {
                if (path == null)
                {
                    path = Path.Combine(Path.GetDirectoryName(MUnitConfiguration.ConfigPath), "TestLog.txt");
                }

                logger.WriteToFile(path);
                _fileStream          = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.None);
                logger.MessageEvent += Logger_MessageEvent;
            }
            catch (Exception e)
            {
                logger.RecordMessage(MessageLevel.Error, e.ToString());
            }
        }
Esempio n. 10
0
        /// <inheritdoc/>
        public IList <SourcePackage> GetTypes(IEnumerable <string> sources, IMUnitLogger logger)
        {
            ThrowUtilities.NullArgument(sources, nameof(sources));
            ThrowUtilities.NullArgument(logger, nameof(logger));

            List <SourcePackage> packages = new List <SourcePackage>();

            foreach (string source in sources)
            {
                logger.RecordMessage(MessageLevel.Trace, "Loading tests from: " + Path.GetFullPath(source));

                if (File.Exists(source))
                {
                    string fileName = Path.GetFileName(source);
                    if (!ValidateExtension(fileName))
                    {
                        logger.RecordMessage(MessageLevel.Error, Errors.InvalidExtension);
                        continue;
                    }
                    else if (!TryLoaded(source, out Assembly assembly, logger))
                    {
                        logger.RecordMessage(MessageLevel.Error, Errors.FileNotLoaded);
                        continue;
                    }
                    else
                    {
                        if (packages.Find(package => package.FullName != assembly.FullName) == null)
                        {
                            packages.Add(new SourcePackage(Path.GetFullPath(source), assembly.FullName, assembly.GetTypes()));
                        }
                        else
                        {
                            logger.RecordMessage(MessageLevel.Warning, Errors.UTE_DuplicateAssembly);
                        }
                    }
                }
Esempio n. 11
0
        protected virtual void BuildCycleFromType(string source, Type type, TestCycleCollection testCycles, IMUnitLogger logger)
        {
            ThrowUtilities.NullArgument(type, nameof(type));
            ThrowUtilities.NullArgument(testCycles, nameof(testCycles));

            if (_reflectionHelper.IsValidTestClass(type, logger))
            {
                if (!testCycles.TryGetValue(HashUtilities.GuidForTestCycleID(source, type.Namespace), out _))
                {
                    TestCycle namespaceCycle = new TestCycle(source, type, TestCycleScope.Namespace);
                    testCycles.Add(namespaceCycle);
                }

                TestCycle classCycle = new TestCycle(source, type, TestCycleScope.Class);
                testCycles.Add(classCycle);

                DiscoverTests(source, type, testCycles, logger);
                DiscoverPreparationMethod(source, type, type, testCycles, logger);
            }
        }
Esempio n. 12
0
        protected virtual void BuildCycleFromAssembly(string source, ITestCycle root, IEnumerable <Type> types, TestCycleCollection testCycles, IMUnitLogger logger)
        {
            ThrowUtilities.NullArgument(root, nameof(root));
            ThrowUtilities.NullArgument(testCycles, nameof(testCycles));
            ThrowUtilities.NullArgument(types, nameof(types));

            TestCycle assemblyCycle = new TestCycle(source, types.First(), root.ID, TestCycleScope.Assembly);

            testCycles.Add(assemblyCycle);
            foreach (Type type in types)
            {
                BuildCycleFromType(source, type, testCycles, logger);
            }
        }
Esempio n. 13
0
        /// <inheritdoc/>
        public virtual TestCycleCollection BuildTestCycles(IList <SourcePackage> packages, IMUnitLogger logger)
        {
            ThrowUtilities.NullArgument(packages, nameof(packages));

            TestCycle           root       = new TestCycle(null, GetType(), TestCycleScope.AppDomain);
            TestCycleCollection testCycles = new TestCycleCollection(root, logger);

            logger?.RecordMessage(MessageLevel.Trace, string.Format(
                                      CultureInfo.InvariantCulture,
                                      "Create root test cycle with full name: {0} and parent ID: {1}",
                                      root.FullName,
                                      root.ParentID));

            foreach (SourcePackage package in packages)
            {
                BuildCycleFromAssembly(package.Source, root, package.Types, testCycles, logger);
            }

            return(testCycles);
        }
Esempio n. 14
0
        /// <summary>
        /// Discover tests from a type.
        /// </summary>
        /// <param name="source"> Full path to the assembly that contains <paramref name="type"/>.</param>
        /// <param name="type"> Discover tests in this type. </param>
        /// <param name="testCycles"> Test cycles for query. </param>
        /// <param name="logger"> Log information. </param>
        protected virtual void DiscoverTests(string source, Type type, TestCycleCollection testCycles, IMUnitLogger logger)
        {
            ThrowUtilities.NullArgument(type, nameof(type));
            ThrowUtilities.NullArgument(testCycles, nameof(testCycles));

            foreach (MethodInfo method in _reflectionWorker.GetDeclaredMethods(type))
            {
                if (_reflectionHelper.IsValidTestMethod(method, logger))
                {
                    TestMethodAttribute methodAttribute = _reflectionWorker.GetAttributesHaveBase(method, typeof(TestMethodAttribute), false).First() as TestMethodAttribute;
                    Guid testCycleID = HashUtilities.GuidForTestCycleID(source, _reflectionHelper.ResolveTestCycleFullName(type, methodAttribute.Scope));

                    if (!testCycles.TryGetValue(testCycleID, out ITestCycle testCycle))
                    {
                        testCycle = new TestCycle(source, type, TestCycleScope.Method)
                        {
                            DeclaringClass = type,
                        };
                        testCycles.Add(testCycle);
                    }

                    TestMethodContext context = new TestMethodContext(source, testCycle, method, type, logger);
                    if (_reflectionWorker.TryGetAttributeAssignableTo(method, typeof(IDataSource), false, out Attribute dataAttribute))
                    {
                        if (dataAttribute is IDataProvidingMethod dataProvidingMethod)
                        {
                            if (dataProvidingMethod.DeclaringType == null)
                            {
                                dataProvidingMethod.DeclaringType = type;
                            }
                        }

                        // TODO Report data method that has wrong signature.
                        context.DataSource = dataAttribute as IDataSource;
                    }

                    IExecutor executor = _reflectionWorker.GetAttributeAssignableTo(method, typeof(IExecutor), false) as IExecutor;
                    context.Executor = executor;

                    testCycle.TestMethodContexts.Add(context);
                    testCycles.TestContextLookup.Add(context.TestID, context);

                    logger?.RecordMessage(MessageLevel.Trace, string.Format(
                                              CultureInfo.CurrentCulture,
                                              Resources.Strings.FoundTestMethod,
                                              type.FullName,
                                              method.Name));
                }
            }
        }
Esempio n. 15
0
        /// <summary>
        /// Discover preparation methods in type.
        /// </summary>
        /// <param name="source"> Full path to the assembly that contains <paramref name="type"/>.</param>
        /// <param name="reference"> The type used for reference when retrieve test cycles. </param>
        /// <param name="type"> In which preparation methods are discovered. </param>
        /// <param name="testCycles"> Test cycles for query. </param>
        /// <param name="logger"> Log information. </param>
        protected virtual void DiscoverPreparationMethod(string source, Type reference, Type type, TestCycleCollection testCycles, IMUnitLogger logger)
        {
            if (type == null)
            {
                return;
            }

            ThrowUtilities.NullArgument(testCycles, nameof(testCycles));

            DiscoverPreparationMethod(source, reference, type.BaseType, testCycles, logger);

            foreach (MethodInfo method in _reflectionWorker.GetDeclaredMethods(type))
            {
                if (_reflectionHelper.IsValidPrepMethod(method, logger))
                {
                    IEnumerable <SupportingAttribute> preparations =
                        _reflectionWorker.GetDerivedAttributes(method, typeof(SupportingAttribute), false)
                        .OfType <SupportingAttribute>();

                    foreach (SupportingAttribute prep in preparations)
                    {
                        Guid testCycleID = HashUtilities.GuidForTestCycleID(source, _reflectionHelper.ResolveTestCycleFullName(reference, prep.Scope));
                        if (testCycles.TryGetValue(testCycleID, out ITestCycle cycle))
                        {
                            prep.Register(cycle, method);

                            logger?.RecordMessage(MessageLevel.Trace, string.Format(
                                                      CultureInfo.InvariantCulture,
                                                      "{0} prep method is registered to test cycle {1}",
                                                      prep.PreparationType,
                                                      cycle.FullName));
                        }
                        else
                        {
                            logger?.RecordMessage(MessageLevel.Error, string.Format(
                                                      CultureInfo.CurrentCulture,
                                                      Errors.UTE_TestCycleNotFoundForPrep,
                                                      method.Name));
                        }
                    }
                }
            }
        }
Esempio n. 16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TestCycleCollection"/> class.
 /// </summary>
 /// <param name="root">From which test starts.</param>
 /// <param name="logger"> Logs information. </param>
 public TestCycleCollection(ITestCycle root, IMUnitLogger logger)
     : base(root, logger)
 {
 }
Esempio n. 17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MUnitEngine"/> class.
 /// </summary>
 /// <param name="logger"> Logs events reported by engine. </param>
 public MUnitEngine(IMUnitLogger logger)
 {
     Logger = logger;
 }
Esempio n. 18
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TestMethodContext"/> class.
        /// </summary>
        /// <param name="source"> Source where the test is discovered. </param>
        /// <param name="parentCycle"> Test cycle that owns this context. </param>
        /// <param name="method"> Test method to run. </param>
        /// <param name="parentClass"> The class in which test method is declared. </param>
        /// <param name="logger"> Logs information. </param>
        internal TestMethodContext(string source, ITestCycle parentCycle, MethodInfo method, Type parentClass, IMUnitLogger logger)
        {
            Debug.Assert(method != null, "Test method should not be null.");
            Debug.Assert(parentClass != null, "Parent class should not be null.");

            this.Source             = source;
            this.MethodInfo         = method;
            this.DeclaringType      = parentClass;
            this.ParentCycle        = parentCycle;
            this.Logger             = logger;
            this.FullyQualifiedName = FrameworkSerive.RelfectionWoker.GetMethodFullName(method);
            this.TestID             = HashUtilities.GuidForTestCycleID(source, this.FullyQualifiedName);
        }