C# Excel中的单元测试数组
我想从Excel电子表格中的数据传递一个数组。注意,我不想对每一行运行一个测试,而是对整个列表运行一个测试 例如,类似以下内容:C# Excel中的单元测试数组,c#,.net,unit-testing,xunit.net,C#,.net,Unit Testing,Xunit.net,我想从Excel电子表格中的数据传递一个数组。注意,我不想对每一行运行一个测试,而是对整个列表运行一个测试 例如,类似以下内容: [Theory] [ExcelData("test.xls", "select * from [Sheet1$A1:A7]")] public void TestMyAverage(double[] values) { double desiredResult = values.Average(); Assert.True(MyAverage(desi
[Theory]
[ExcelData("test.xls", "select * from [Sheet1$A1:A7]")]
public void TestMyAverage(double[] values)
{
double desiredResult = values.Average();
Assert.True(MyAverage(desiredResult));
}
但是,该特定代码无法工作,因为它试图将每一行(
double
)转换为double[]
,从而导致错误。我修改了ExcelDataAttribute
。它还没有经过彻底的测试,但似乎有效
有两个新的可选参数:
[Theory]
[ExcelArrayData("test.xls", "select * from [Sheet1$A1:B7]", false, true)]
public void TestMethod(int[] values, int[] values2)
源代码:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Reflection;
using Xunit.Sdk;
namespace UnitTestCalculationStandards
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class ExcelArrayDataAttribute : DataAttribute
{
string connectionTemplate =
"Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0}; Extended Properties='Excel 12.0;HDR=YES;IMEX=1;';";
public ExcelArrayDataAttribute(string fileName, string queryString, bool hasHeader = true, bool returnAsArray = false)
{
// System.Diagnostics.Debugger.Launch();
if (!hasHeader)
{
connectionTemplate = connectionTemplate.Replace("HDR=YES", "HDR=NO");
}
FileName = fileName;
QueryString = queryString;
ReturnAsArray = returnAsArray;
}
public string FileName { get; private set; }
public string QueryString { get; private set; }
private bool ReturnAsArray;
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
if (testMethod == null)
throw new ArgumentNullException("testMethod");
ParameterInfo[] pars = testMethod.GetParameters();
if (ReturnAsArray)
{
return DataSourceAsEnumerable(FileName, QueryString, pars.Select(par => GetEnumerableType(par.ParameterType)).ToArray());
}
else
{
return DataSource(FileName, QueryString, pars.Select(par => par.ParameterType).ToArray());
}
}
static Type GetEnumerableType(Type type)
{
foreach (Type intType in type.GetInterfaces())
{
if (intType.IsGenericType
&& intType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
return intType.GetGenericArguments()[0];
}
}
return null;
}
IEnumerable<object[]> DataSourceAsEnumerable(string fileName, string selectString, Type[] parameterTypes)
{
string connectionString = string.Format(connectionTemplate, GetFullFilename(fileName));
IDataAdapter adapter = new OleDbDataAdapter(selectString, connectionString);
DataSet dataSet = new DataSet();
List<object[]> rows = new List<object[]>();
try
{
adapter.Fill(dataSet);
foreach (DataRow row in dataSet.Tables[0].Rows)
rows.Add(ConvertParameters(row.ItemArray, parameterTypes));
}
finally
{
IDisposable disposable = adapter as IDisposable;
disposable.Dispose();
}
object[] columns = new object[parameterTypes.Length];
for (int i = 0; i < parameterTypes.Length; i++)
{
columns[i] = rows.Select(r => r[i]).ToList();
}
List<object[]> rv = new List<object[]>();
rv.Add(columns.ToArray());
return rv;
}
IEnumerable<object[]> DataSource(string fileName, string selectString, Type[] parameterTypes)
{
string connectionString = string.Format(connectionTemplate, GetFullFilename(fileName));
IDataAdapter adapter = new OleDbDataAdapter(selectString, connectionString);
DataSet dataSet = new DataSet();
try
{
adapter.Fill(dataSet);
foreach (DataRow row in dataSet.Tables[0].Rows)
yield return ConvertParameters(row.ItemArray, parameterTypes);
}
finally
{
IDisposable disposable = adapter as IDisposable;
disposable.Dispose();
}
}
static string GetFullFilename(string filename)
{
string executable = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(executable), filename));
}
static object[] ConvertParameters(object[] values, Type[] parameterTypes)
{
object[] result = new object[values.Length];
for (int idx = 0; idx < values.Length; idx++)
result[idx] = ConvertParameter(values[idx], idx >= parameterTypes.Length ? null : parameterTypes[idx]);
return result;
}
/// <summary>
/// Converts a parameter to its destination parameter type, if necessary.
/// </summary>
/// <param name="parameter">The parameter value</param>
/// <param name="parameterType">The destination parameter type (null if not known)</param>
/// <returns>The converted parameter value</returns>
static object ConvertParameter(object parameter, Type parameterType)
{
if ((parameter is double || parameter is float) &&
(parameterType == typeof(int) || parameterType == typeof(int?)))
{
int intValue;
string floatValueAsString = parameter.ToString();
if (Int32.TryParse(floatValueAsString, out intValue))
return intValue;
}
return parameter;
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统数据;
使用System.Data.OleDb;
使用System.IO;
使用System.Linq;
运用系统反思;
使用Xunit.Sdk;
命名空间UnitTestCalculationStandards
{
[AttributeUsage(AttributeTargets.Method,AllowMultiple=false,Inherited=false)]
公共密封类ExcelArrayDataAttribute:DataAttribute
{
字符串连接模板=
“Provider=Microsoft.ACE.OLEDB.12.0;数据源={0};扩展属性='excel12.0;HDR=YES;IMEX=1;';”;
公共ExcelArrayDataAttribute(字符串文件名、字符串查询字符串、bool HashReader=true、bool returnAsArray=false)
{
//System.Diagnostics.Debugger.Launch();
if(!hasHeader)
{
connectionTemplate=connectionTemplate.Replace(“HDR=YES”,“HDR=NO”);
}
FileName=文件名;
QueryString=QueryString;
ReturnAsArray=ReturnAsArray;
}
公共字符串文件名{get;private set;}
公共字符串查询字符串{get;private set;}
私人布尔返回阵列;
公共重写IEnumerable GetData(MethodInfo testMethod)
{
if(testMethod==null)
抛出新ArgumentNullException(“testMethod”);
ParameterInfo[]pars=testMethod.GetParameters();
如果(返回阵列)
{
返回DataSourceAnumerable(文件名、QueryString、pars.Select(par=>GetEnumerableType(par.ParameterType)).ToArray();
}
其他的
{
返回数据源(文件名、查询字符串、PARS。选择(PAL= > PAR。ParameterType)。toRayay.());
}
}
静态类型GetEnumerableType(类型类型)
{
foreach(Type.GetInterfaces()中的intType类型)
{
如果(intType.IsGenericType
&&intType.GetGenericTypeDefinition()==typeof(IEnumerable))
{
返回intType.GetGenericArguments()[0];
}
}
返回null;
}
IEnumerable数据源可枚举(字符串文件名、字符串选择字符串、类型[]参数类型)
{
string connectionString=string.Format(connectionTemplate,GetFullFilename(fileName));
IDataAdapter=新的OleDbDataAdapter(选择String,connectionString);
数据集=新数据集();
列表行=新列表();
尝试
{
adapter.Fill(数据集);
foreach(数据集中的DataRow行。表[0]。行)
Add(ConvertParameters(row.ItemArray,parameterTypes));
}
最后
{
IDisposable一次性=适配器为IDisposable;
一次性的,一次性的;
}
object[]columns=新对象[parameterTypes.Length];
对于(int i=0;ir[i])。ToList();
}
List rv=新列表();
rv.Add(columns.ToArray());
返回rv;
}
IEnumerable数据源(字符串文件名、字符串selectString、类型[]参数类型)
{
string connectionString=string.Format(connectionTemplate,GetFullFilename(fileName));
IDataAdapter=新的OleDbDataAdapter(选择String,connectionString);
数据集=新数据集();
尝试
{
adapter.Fill(数据集);
foreach(数据集中的DataRow行。表[0]。行)
收益率返回参数(row.ItemArray,parameterTypes);
}
最后
{
IDisposable一次性=适配器为IDisposable;
一次性的,一次性的;
}
}
静态字符串GetFullFilename(字符串文件名)
{
字符串可执行文件=新Uri(Assembly.getExecutionGassembly().CodeBase).LocalPath;
返回Path.GetFullPath(Path.Combine(Path.GetDirectoryName(可执行文件),文件名));
}
静态对象[]转换参数(对象[]值,类型[]参数类型)
{
object[]result=新对象[values.Length];
for(intidx=0;idx=parameterTypes.Length?null:parameterTypes[idx]);
返回结果;
}
///
///如有必要,将参数转换为其目标参数类型。
///
///参数值
///目标参数类型(如果未知,则为null)
///转换后的参数值
静态对象参数(对象参数,类型参数类型)
{
if((参数为double | |参数为float)&&
(parameterType==typeof(int)| | parameterType==typeof(int?))
{
int值;
字符串floatValueAsString=参数.ToString();
if(Int32.TryParse(floatValueAsString,out intValue))
返回值;
}
返回参数;
}
}
}