我有以下课程。出于测试目的,我想获得类Client的所有可能的排列。我知道这个数字可能非常大,但现在这不是我的问题。
客户:否(int),名称(字符串),地址(地址对象)
地址:街道(字符串),国家(字符串)等
对于int类型的属性,我总是尝试相同的三个值(-1,0,1),用于string(null,string.Empty,“Hello World”等)。对于基本类型,它运作良好。但是,对于类Address,这是不同的。
简而言之,我正在尝试编写一个足够通用的方法来获取任何Type(类等)并获得所有可能的排列(换句话说:public IEnumerable GetPermutations(Type myType))。在.NET Reflection的帮助下,此方法将循环所有可设置的属性。
有人知道该怎么做吗?
由于
答案 0 :(得分:4)
PEX测试框架做了一些事情。它试图提供方法参数的几种排列,以便涵盖潜在有用的测试用例。
答案 1 :(得分:2)
这是一个可以帮助你入门的课程,虽然我没有对它进行过多次测试。请注意,这仅适用于具有no-args构造函数的类,并且不适用于某些类型的递归类(例如,具有自己类型属性的类,例如树)。您还可能希望在静态构造函数中预先填充更多类。
public static class PermutationGenerator
{
private static class Permutation<T>
{
public static IEnumerable<T> Choices { get; set; }
}
static PermutationGenerator()
{
Permutation<int>.Choices = new List<int> { -1, 0, 1 }.AsReadOnly();
Permutation<string>.Choices = new List<string> { null, "", "Hello World" }.AsReadOnly();
}
public static IEnumerable<T> GetPermutations<T>()
{
if (Permutation<T>.Choices == null) {
var props = typeof(T).GetProperties().Where(p => p.CanWrite);
Permutation<T>.Choices = new List<T>(GeneratePermutations<T>(() => Activator.CreateInstance<T>(), props)).AsReadOnly();
}
return Permutation<T>.Choices;
}
private static IEnumerable GetPermutations(Type t) {
var method = typeof(PermutationGenerator).GetMethod("GetPermutations", new Type[] {}).MakeGenericMethod(t);
return (IEnumerable)(method.Invoke(null,new object[] {}));
}
private delegate T Generator<T>();
private static IEnumerable<T> GeneratePermutations<T>(Generator<T> generator, IEnumerable<PropertyInfo> props)
{
if (!props.Any())
{
yield return generator();
}
else
{
var prop = props.First();
var rest = props.Skip(1);
foreach (var propVal in GetPermutations(prop.PropertyType))
{
Generator<T> gen = () =>
{
var obj = generator();
prop.SetValue(obj, propVal, null);
return (T)obj;
};
foreach (var result in GeneratePermutations(gen, rest))
{
yield return result;
}
}
}
}
}
答案 2 :(得分:1)
大多数非平凡的动态分配对象 - 比如字符串 - 没有可用的有限数量的不同“排列”。该字符串可以是你想要的,直到你的RAM耗尽。
所以这真的是一个完全Sisyphean的任务,除非你对你正在寻找什么样的排列设置更严格的限制,否则没有任何意义继续下去。
答案 3 :(得分:1)
你可以看看PEX
http://research.microsoft.com/en-us/projects/pex/default.aspx
这是一个集成在Visual Studio中的白盒测试生成工具。
答案 4 :(得分:0)
正如许多人所说,产生所有排列对于非平凡的类来说在计算上是不可行的。我必须做的,并取得了巨大的成功,正在为特定范围的输入生成一个类的所有排列;即,给定一个具有属性A,B和C的类,我想生成A = 1,A = 2,B = 1,C = 3和C = 4的所有排列,导致:
A = 1,B = 1,C = 3
A = 2,B = 1,C = 3
A = 1,B = 1,C = 4
A = 2,B = 1,C = 4
这种事情可以通过递归算法或一些非常优雅的LINQ查询来完成。 here上有一个相当详尽的文章,但它的编程量很大,如果你对你的集合理论有所帮助,它真的会有所帮助。
答案 5 :(得分:-1)
这就像是要求在1小时内将中国长城搬到太空。它无法完成。
你需要知道什么定义了每种类型的每种排列,甚至是你没有创建的类型,这是不可能的。