4

我的单元测试框架由 TestFixtures、TestMethods 和 Actions 组成。Action是TestMethod内部额外的小容器,Actions来自我们公司内部编写的Dll。动作在这样的方法中使用:

[Test]
void TestMethod1()
{
    Run(new Sleep { Seconds = 10 } );
}

我必须编写一个应用程序,该应用程序从 DLL 收集有关夹具、测试和操作的所有信息。我发现了如何使用类型/方法属性通过反射来枚举测试装置和测试方法。

但我不知道如何枚举测试方法中的操作。

能否请你帮忙?完全可以使用反射吗?

更新: 查看接受的答案。真的很酷的图书馆。如果您对我如何为夹具、测试和操作创建实体模型以及以 MVVM 方式绑定到 TreeView 感兴趣,您也可以查看此处(WPF:以 MVVM 方式绑定 TreeView 分步教程)。

4

3 回答 3

3

是的。

反射会给你方法体,而不是你需要反汇编 IL 来读取方法体并获得你想要的任何信息。

var bytes = mi.GetMethodBody().GetILAsByteArray();

Cecil是一种可能的拆卸工具

查看Traverse ac# 方法并分析方法主体以获取更多链接。

于 2012-12-03T08:06:12.917 回答
0

与其使用反射,不如推出自己的方法来记录所有 Action 执行。

void ExecuteAction(Action action)
{
   //Log TestFixture, TestMethod, Action

   //Execute actual action
}

[Test]
void TestMethod1()
{
    ExecuteAction(Run(new Sleep { Seconds = 10 } ));
}

ExecuteAction 方法可以在基类或辅助类中

于 2012-12-03T08:09:16.953 回答
0

谢谢,阿列克谢列文科夫!最后,我找到了使用您的提示的解决方案。分享。您唯一应该做的事情 -> 从https://github.com/jbevain/mono.reflection下载并引用 Mono.Reflection.dll 。

using System;
using System.Linq;
using System.Reflection;
using MINT;
using MbUnit.Framework;
using Mono.Reflection;

namespace TestDll
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            const string DllPath = @"d:\SprinterAutomation\Actions.Tests\bin\x86\Debug\Actions.Tests.dll";
            Assembly assembly = Assembly.LoadFrom(DllPath);

            // enumerating Fixtures
            foreach (Type fixture in assembly.GetTypes().Where(t => t.GetCustomAttributes(typeof(TestFixtureAttribute), false).Length > 0)) 
            {
                Console.WriteLine(fixture.Name);
                // enumerating Test Methods
                foreach (var testMethod in fixture.GetMethods().Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Length > 0))
                {
                    Console.WriteLine("\t" + testMethod.Name);
                    // filtering Actions
                    var instructions = testMethod.GetInstructions().Where(
                        i => i.OpCode.Name.Equals("newobj") && ((ConstructorInfo)i.Operand).DeclaringType.IsSubclassOf(typeof(BaseAction)));

                    // enumerating Actions!
                    foreach (Instruction action in instructions)
                    {
                        var constructroInfo = action.Operand as ConstructorInfo;
                        Console.WriteLine("\t\t" + constructroInfo.DeclaringType.Name);
                    }
                }
            }

        }
    }
}
于 2012-12-03T14:12:22.150 回答