bright
bright

Reputation: 4811

Running Visual Studio 2008 C# (MSTest.exe based) unit tests in Mono

I'm using VS2008 to develop a project that I'm starting to test under Mono. There are a number of unit tests written using the VS unit test framework, is there a tool that will let me run these in Mono?

Thanks,

Upvotes: 4

Views: 2215

Answers (2)

Bartek Muszynski
Bartek Muszynski

Reputation: 411

I wrote the following code and it works well on Mono. The code does NOT have any dependence on the Visual Studio test duite DLL. Surprisingly, it runs a little faster on Mone (running on VirtualBox on my PC) than in Visual Studio.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace drvrapp {
    public class TestRunner {
        // assembly file (e.g. MyTestAssembly.dll) which should be in the same directory 
        public static void TestDll(string assemblyFile) {
            string symbolsFile = Path.GetFileNameWithoutExtension(assemblyFile) + ".pdb";

            byte[] assemblyBytes = File.ReadAllBytes(assemblyFile);
            byte[] symbolsBytes = File.ReadAllBytes(symbolsFile);

            Assembly assembly = Assembly.Load(assemblyBytes, symbolsBytes);

            foreach (Type type in assembly.GetTypes())
                if (HasAttribute(type, "TestClass"))
                    foreach (MethodInfo method in type.GetMethods())
                        if (HasAttribute(method, "TestMethod"))
                            RunTest(method);
        }

        private static void RunTest(MethodInfo method) {
            Console.WriteLine("------------------------------------------------------------------------------------------");
            Console.Write("Running {0}.{1}...", method.DeclaringType.Name, method.Name);

            if (HasAttribute(method, "Ignore")) {
                Console.WriteLine("IGNORED");
                return;
            }

            try {
                Type testType = method.DeclaringType;
                object typeClassInstance = Activator.CreateInstance(testType);

                RunInitializeOrCleanup(typeClassInstance, "TestInitialize");
                method.Invoke(typeClassInstance, null);
                RunInitializeOrCleanup(typeClassInstance, "TestCleanup");

                Console.WriteLine("PASSED");
            } catch (Exception e) {
                Console.WriteLine();
                Console.WriteLine(e);
            }
        }

        private static void RunInitializeOrCleanup(object instance, string attribute) {
            MethodInfo method = instance.GetType().GetMethods().SingleOrDefault(x => HasAttribute(x, attribute));
            if (method != null)
                method.Invoke(instance, null);
        }

        private static bool HasAttribute(MemberInfo info, string attributeName) {
            return info.GetCustomAttributes(false).Any(x => x.GetType().Name == attributeName + "Attribute");
        }
    }
}

Upvotes: 0

Preet Sangha
Preet Sangha

Reputation: 65516

Depending on the features that you're using it can be trivial or hard. You can use namespace/type aliasing to use another class library to do asserts, and the attributes. I've written console programs that run the tests manually - but of course I had access to the vs namespaces and assemblies.

For mono - my suggestion would be to use another testing system altogether as doing it yourself with system.reflection namepace to load the assembly, reflect the attributes and execute as you need to, will be tedious.

For example:

Pseudo code:

var assembly = loadAsembly(....)
foreach(type in assembly.types) {
 if(type is static class and had method with AssemblyInitialiseAttrubute)){
    InvokeTheMethod(method);
 }
}

foreach(type in assembly.types) {
 if(type is not class and had method with TestClass)){
    InvokeTheMethod(method);
 }
 foreach(method in type with ClassinitialiseAttribute)
}
... etc

Upvotes: 2

Related Questions