XFEExtension
【DLL】XFE各类拓展是一个C#的DLL库,旨在优化C#代码中常用语句的使用,并提供更简洁的访问方式,同时提供Xunit测试框架,快速搭建服务器/客户端,免费ChatGPTAPI接口,免费通讯服务器,XFE下载器,新增格式等
关注
0
Fork
0
Star
0
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using XFEExtension.ArrayExtension;
using XFEExtension.AttributeExtension;
using XFEExtension.ReflectionExtension;
using XFEExtension.StringExtension;
using XFEExtension.TaskExtension;
namespace XFEExtension
{
#region 异常
/// <summary>
/// XFEExtension的异常
/// </summary>
public class XFEExtensionException : Exception
{
/// <summary>
/// XFEExtension的异常
/// </summary>
/// <param name="message"></param>
internal XFEExtensionException(string message) : base(message) { }
/// <summary>
/// XFEExtension的异常
/// </summary>
/// <param name="message"></param>
/// <param name="innerException"></param>
internal XFEExtensionException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFEJson转换的异常
/// </summary>
public class XFEJsonTransformException : XFEExtensionException
{
/// <summary>
/// XFEJson转换的异常
/// </summary>
/// <param name="message"></param>
internal XFEJsonTransformException(string message) : base(message) { }
/// <summary>
/// XFEJson转换的异常
/// </summary>
/// <param name="message"></param>
/// <param name="innerException"></param>
internal XFEJsonTransformException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFEChatGPT的异常
/// </summary>
public class XFEChatGPTException : XFEExtensionException
{
/// <summary>
/// XFEChatGPT的异常
/// </summary>
/// <param name="message"></param>
internal XFEChatGPTException(string message) : base(message) { }
internal XFEChatGPTException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFE网络通信的异常
/// </summary>
public class XFECyberCommException : XFEExtensionException
{
/// <summary>
/// XFE网络通信的异常
/// </summary>
/// <param name="message"></param>
internal XFECyberCommException(string message) : base(message) { }
internal XFECyberCommException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFE邮件的异常
/// </summary>
public class XFEMailException : XFEExtensionException
{
internal XFEMailException(string message) : base(message) { }
internal XFEMailException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFE字典的异常
/// </summary>
public class XFEDictionaryException : XFEExtensionException
{
internal XFEDictionaryException(string message) : base(message) { }
internal XFEDictionaryException(string message, Exception innerException) : base(message, innerException) { }
}
#endregion
/// <summary>
/// XFEExtension编写
/// </summary>
public abstract class XFECode
{
private static int CTimeCounter = 0;
private static bool CurrentMethodIsAsserted = false;
private static string CurrentAssertMessage = string.Empty;
#region 暂停
/// <summary>
/// 暂停
/// </summary>
/// <param name="ShowText">是否显示提示</param>
protected static void Pause(bool ShowText = true)
{
if (ShowText)
{
Console.WriteLine("按任意键继续...");
}
Console.ReadKey();
}
/// <summary>
/// 暂停
/// </summary>
/// <param name="ShowText">显示的文字</param>
protected static void Pause(string ShowText)
{
Console.WriteLine(ShowText);
Console.ReadKey();
}
/// <summary>
/// 暂停,按下指定按键继续
/// </summary>
/// <param name="consoleKey">指定的按键</param>
protected static void Pause(ConsoleKey consoleKey)
{
Console.WriteLine($"按 {consoleKey} 键继续");
while (Console.ReadKey().Key != consoleKey) ;
}
/// <summary>
/// 暂停,按下指定按键继续
/// </summary>
/// <param name="consoleKey">指定的按键</param>
/// <param name="ShowText">显示的文字</param>
protected static void Pause(ConsoleKey consoleKey, string ShowText)
{
Console.WriteLine(ShowText);
while (Console.ReadKey().Key != consoleKey) ;
}
#endregion
/// <summary>
/// 并行循环指定次数
/// </summary>
/// <param name="action">执行的操作</param>
/// <param name="count">循环次数</param>
/// <param name="autoWaitAll">自动等待所有线程执行完毕</param>
protected static async Task<List<Task>> Circle(Action action, int count, bool autoWaitAll = false)
{
var taskList = new List<Task>();
for (int i = 0; i < count; i++)
{
taskList.Add(action.StartNewTask());
}
if (autoWaitAll)
await Task.WhenAll(taskList);
return taskList;
}
/// <summary>
/// 并行循环指定次数
/// </summary>
/// <param name="action">执行的操作</param>
/// <param name="count">循环次数</param>
protected static async void CircleOrderly(Action action, int count)
{
for (int i = 0; i < count; i++)
{
await action.StartNewTask();
}
}
/// <summary>
/// 计算一段代码执行所需时间
/// </summary>
/// <param name="action"></param>
/// <param name="autoOutPut">自动输出</param>
/// <param name="timerName">该次计时标识名</param>
/// <returns></returns>
public static TimeSpan CTime(Action action, bool autoOutPut = true, string timerName = "无标识名计时器")
{
var timeCounter = new Stopwatch();
timeCounter.Start();
action?.Invoke();
timeCounter.Stop();
CTimeCounter++;
var elapsedTime = timeCounter.Elapsed;
if (autoOutPut)
if (elapsedTime.TotalHours >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间:{elapsedTime}");
else if (elapsedTime.TotalMinutes >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {Math.Floor(elapsedTime.TotalMinutes)} 分 {elapsedTime.Seconds} 秒");
else if (elapsedTime.TotalSeconds >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalSeconds:F3} 秒");
else if (elapsedTime.TotalMilliseconds >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalMilliseconds * 1000:F3} 纳秒");
return elapsedTime;
}
/// <summary>
/// 计算一段代码执行所需时间
/// </summary>
/// <param name="action"></param>
/// <param name="autoOutPut">自动输出</param>
/// <param name="timerName">该次计时标识名</param>
/// <returns></returns>
public static async Task<TimeSpan> CTimeAsync(Func<Task> action, bool autoOutPut = true, string timerName = "无标识名计时器")
{
var timeCounter = new Stopwatch();
timeCounter.Start();
await action?.Invoke();
timeCounter.Stop();
CTimeCounter++;
var elapsedTime = timeCounter.Elapsed;
if (autoOutPut)
if (elapsedTime.TotalHours >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间:{elapsedTime}");
else if (elapsedTime.TotalMinutes >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {Math.Floor(elapsedTime.TotalMinutes)} 分 {elapsedTime.Seconds} 秒");
else if (elapsedTime.TotalSeconds >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalSeconds:F3} 秒");
else if (elapsedTime.TotalMilliseconds >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalMilliseconds * 1000:F3} 纳秒");
return elapsedTime;
}
/// <summary>
/// 计算一段代码执行所需时间
/// </summary>
/// <returns></returns>
/// <exception cref="XFEExtensionException"></exception>
protected static async Task RunTest()
{
var isFirstClass = true;
var subClasses = Assembly.GetEntryAssembly().GetTypes()
.Where(type => type.IsSubclassOf(typeof(XFECode)));
foreach (var subClass in subClasses)
{
var mainColor = ConsoleColor.Blue;
var classColor = ConsoleColor.Green;
var classBorderColor = ConsoleColor.DarkGreen;
var methodColor = ConsoleColor.Yellow;
var methodBorderColor = ConsoleColor.DarkYellow;
var successColor = ConsoleColor.Green;
var failColor = ConsoleColor.Red;
var timeColor = ConsoleColor.Cyan;
var counterColor = ConsoleColor.Gray;
if (subClass.GetCustomAttributes(typeof(TestThemeAttribute), false).FirstOrDefault() is TestThemeAttribute themeAttribute)
{
mainColor = themeAttribute.MainColor;
classColor = themeAttribute.ClassColor;
classBorderColor = themeAttribute.ClassBorderColor;
methodColor = themeAttribute.MethodColor;
methodBorderColor = themeAttribute.MethodBorderColor;
successColor = themeAttribute.SuccessColor;
failColor = themeAttribute.FailColor;
timeColor = themeAttribute.TimeColor;
counterColor = themeAttribute.CounterColor;
}
var singleRunMethods = subClass.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).Where(m => m.IsDefined(typeof(SMTestAttribute)));
#region 静态测试
var isFirstStaticMethod = true;
foreach (var method in singleRunMethods)
{
var attributes = method.GetCustomAttributes(typeof(SMTestAttribute));
foreach (var likeAttribute in attributes)
{
if (likeAttribute is SMTestAttribute attribute)
{
string timerName = "方法名:" + method.Name;
if (likeAttribute is SMNTestAttribute subAttribute)
{
timerName = "标识名:" + subAttribute.TimerName;
}
if (attribute is SMNRTestAttribute resultAttribute)
{
timerName = "标识名:" + resultAttribute.TimerName;
}
object[] paramsForMethod = null;
if (attribute.Params != null)
{
paramsForMethod = attribute.Params;
}
else
{
paramsForMethod = method.GetDefaultParameters();
}
var timeCounter = new Stopwatch();
var selfTimeCounter = new Stopwatch();
var elapsedTime = new TimeSpan();
var isSuccessful = true;
var isResultEqual = true;
var failedMessage = string.Empty;
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = methodBorderColor;
if (isFirstStaticMethod)
{
isFirstStaticMethod = false;
}
else
{
Console.WriteLine("\n\n\n\n\n");
}
var borderCount = (Console.BufferWidth - timerName.DisplayLength()) / 2;
if (timerName != null)
{
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
if ((Console.BufferWidth - timerName.DisplayLength()) % 2 == 1)
Console.Write("=");
Console.ForegroundColor = mainColor;
Console.Write(timerName.Substring(0, 4));
Console.ForegroundColor = methodColor;
Console.Write(timerName.Substring(4));
Console.ForegroundColor = methodBorderColor;
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
}
else
{
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
}
Console.WriteLine("\n");
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("开始执行");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write($"\t方法:");
Console.ForegroundColor = methodColor;
Console.Write(method.Name);
Console.ForegroundColor = mainColor;
Console.Write($"\t类:");
Console.ForegroundColor = classColor;
Console.WriteLine($"{subClass.Name}\n");
Console.ResetColor();
selfTimeCounter.Start();
selfTimeCounter.Stop();
try
{
CurrentMethodIsAsserted = false;
if (method.ReturnType == typeof(Task))
{
timeCounter.Start();
await (Task)method.Invoke(Activator.CreateInstance(subClass), paramsForMethod);
timeCounter.Stop();
}
else
{
timeCounter.Start();
var result = method.Invoke(Activator.CreateInstance(subClass), paramsForMethod);
timeCounter.Stop();
if (attribute is SMRTestAttribute resultAttribute2)
{
isResultEqual = result.Equals(resultAttribute2.ReturnValue);
if (!isResultEqual)
{
isSuccessful = false;
failedMessage = $"预期结果:{resultAttribute2.ReturnValue}\t实际结果:{result}";
}
}
}
if (CurrentMethodIsAsserted)
{
isSuccessful = false;
if (failedMessage == string.Empty)
failedMessage = CurrentAssertMessage;
else
failedMessage += $"\n{CurrentAssertMessage}";
CurrentMethodIsAsserted = false;
CurrentAssertMessage = string.Empty;
}
}
catch (Exception e)
{
isSuccessful = false;
failedMessage = e.Message;
}
elapsedTime = timeCounter.Elapsed - selfTimeCounter.Elapsed;
CTimeCounter++;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine();
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("执行完成");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write("\t执行批次:");
Console.ForegroundColor = counterColor;
Console.Write(CTimeCounter);
Console.ForegroundColor = mainColor;
Console.Write("\t执行时间:");
Console.ForegroundColor = timeColor;
if (elapsedTime.TotalHours >= 1)
Console.WriteLine(elapsedTime);
else if (elapsedTime.TotalMinutes >= 1)
Console.WriteLine($"{elapsedTime.Minutes} 分 {elapsedTime.Seconds} 秒 {elapsedTime.Milliseconds} 毫秒");
else if (elapsedTime.TotalSeconds >= 1)
Console.WriteLine($"{elapsedTime.TotalSeconds:F3} 秒");
else if (elapsedTime.TotalMilliseconds >= 1)
Console.WriteLine($"{elapsedTime.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"{elapsedTime.TotalMilliseconds * 1000:F2} 纳秒");
Console.ForegroundColor = ConsoleColor.Black;
Console.WriteLine();
if (isSuccessful && isResultEqual)
{
Console.BackgroundColor = successColor;
Console.Write("测试通过");
}
else
{
Console.BackgroundColor = failColor;
Console.Write("测试失败");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = failColor;
Console.WriteLine($"\t失败原因:{failedMessage}");
}
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
Console.ForegroundColor = methodBorderColor;
Console.Write("\n");
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
Console.ResetColor();
Console.WriteLine("\n");
Console.WriteLine("\n");
}
}
}
#endregion
var classAttributes = subClass.GetCustomAttributes(typeof(CTestAttribute));
var classRunMethods = subClass.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).Where(m => m.IsDefined(typeof(MTestAttribute)));
foreach (var classAttribute in classAttributes.Cast<CTestAttribute>())
{
var isFirstMethod = true;
var failedList = new List<MethodAndCounter>();
object classInstance = classAttribute.Params is null;
if (classAttribute.Params is null)
{
classInstance = subClass.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null).Invoke(classAttribute.Params);
}
else
{
classInstance = subClass.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, classAttribute.Params.GetTypes(), null).Invoke(classAttribute.Params);
}
var setUpAttribute = subClass.GetAttribute<TSetUpAttribute>();
if (setUpAttribute != null)
{
var setUpMethod = subClass.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).Where(m => m.IsDefined(typeof(TSetUpAttribute))).FirstOrDefault();
if (setUpMethod != null)
{
setUpMethod.Invoke(classInstance, setUpMethod.GetDefaultParameters());
}
}
string classOtherName = "类名:" + subClass.Name;
if (classAttribute is CNTestAttribute subClassAttribute)
{
classOtherName = "标识名:" + subClassAttribute.ClassOtherName;
}
var classTimeCounter = new Stopwatch();
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = classBorderColor;
if (isFirstClass)
{
isFirstClass = false;
}
else
{
Console.WriteLine("\n\n\n\n\n\n\n\n");
}
var borderCount = (Console.BufferWidth - classOtherName.DisplayLength()) / 2;
if (classOtherName != null)
{
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
if ((Console.BufferWidth - classOtherName.DisplayLength()) % 2 == 1)
Console.Write("=");
Console.ForegroundColor = mainColor;
if (classOtherName.Substring(0, 4) == "标识名:")
{
Console.Write(classOtherName.Substring(0, 4));
Console.ForegroundColor = classColor;
Console.Write(classOtherName.Substring(4));
}
else
{
Console.Write(classOtherName.Substring(0, 3));
Console.ForegroundColor = classColor;
Console.Write(classOtherName.Substring(3));
}
Console.ForegroundColor = classBorderColor;
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
}
else
{
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
}
Console.WriteLine("\n");
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("开始执行");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write("\t类名:");
Console.ForegroundColor = classColor;
Console.WriteLine($"{subClass.Name}\n\n\n\n\n");
Console.ResetColor();
classTimeCounter.Start();
foreach (var method in classRunMethods)
{
var attributes = method.GetCustomAttributes(typeof(MTestAttribute));
foreach (MTestAttribute attribute in attributes)
{
if (attribute is MTestAttribute methodAttribute)
{
string methodOtherName = "方法名:" + method.Name;
if (attribute is MNTestAttribute subAttribute)
{
methodOtherName = "标识名:" + subAttribute.MethodOtherName;
}
if (attribute is MNRTestAttribute resultAttribute)
{
methodOtherName = "标识名:" + resultAttribute.MethodOtherName;
}
object[] paramsForMethod = null;
if (attribute.Params != null)
{
paramsForMethod = attribute.Params;
}
else
{
paramsForMethod = method.GetDefaultParameters();
}
var timeCounter = new Stopwatch();
var selfTimeCounter = new Stopwatch();
var elapsedTime = new TimeSpan();
var isSuccessful = true;
var isResultEqual = true;
var failedMessage = string.Empty;
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = methodBorderColor;
if (isFirstMethod)
{
isFirstMethod = false;
}
else
{
Console.WriteLine("\n\n\n\n\n");
}
borderCount = (Console.BufferWidth - methodOtherName.DisplayLength()) / 2;
if (methodOtherName != null)
{
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
if ((Console.BufferWidth - methodOtherName.DisplayLength()) % 2 == 1)
Console.Write("=");
Console.ForegroundColor = mainColor;
Console.Write(methodOtherName.Substring(0, 4));
Console.ForegroundColor = methodColor;
Console.Write(methodOtherName.Substring(4));
Console.ForegroundColor = methodBorderColor;
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
}
else
{
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
}
Console.WriteLine("\n");
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("开始执行");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write($"\t方法:");
Console.ForegroundColor = methodColor;
Console.Write(method.Name);
Console.ForegroundColor = mainColor;
Console.Write($"\t类:");
Console.ForegroundColor = classColor;
Console.WriteLine($"{subClass.Name}\n");
Console.ResetColor();
selfTimeCounter.Start();
selfTimeCounter.Stop();
try
{
CurrentMethodIsAsserted = false;
if (method.ReturnType == typeof(Task))
{
timeCounter.Start();
await (Task)method.Invoke(classInstance, paramsForMethod);
timeCounter.Stop();
}
else
{
timeCounter.Start();
var result = method.Invoke(classInstance, paramsForMethod);
timeCounter.Stop();
if (methodAttribute is MRTestAttribute resultAttribute2)
{
isResultEqual = result.Equals(resultAttribute2.ReturnValue);
if (!isResultEqual)
{
isSuccessful = false;
failedMessage = $"预期结果:{resultAttribute2.ReturnValue}\t实际结果:{result}";
}
}
}
if (CurrentMethodIsAsserted)
{
isSuccessful = false;
if (failedMessage == string.Empty)
failedMessage = CurrentAssertMessage;
else
failedMessage += $"\n{CurrentAssertMessage}";
CurrentMethodIsAsserted = false;
CurrentAssertMessage = string.Empty;
}
}
catch (Exception e)
{
isSuccessful = false;
failedMessage = e.Message;
}
elapsedTime = timeCounter.Elapsed - selfTimeCounter.Elapsed;
CTimeCounter++;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine();
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("执行完成");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write("\t执行批次:");
Console.ForegroundColor = counterColor;
Console.Write(CTimeCounter);
Console.ForegroundColor = mainColor;
Console.Write("\t执行时间:");
Console.ForegroundColor = timeColor;
if (elapsedTime.TotalHours >= 1)
Console.WriteLine(elapsedTime);
else if (elapsedTime.TotalMinutes >= 1)
Console.WriteLine($"{elapsedTime.Minutes} 分 {elapsedTime.Seconds} 秒 {elapsedTime.Milliseconds} 毫秒");
else if (elapsedTime.TotalSeconds >= 1)
Console.WriteLine($"{elapsedTime.TotalSeconds:F3} 秒");
else if (elapsedTime.TotalMilliseconds >= 1)
Console.WriteLine($"{elapsedTime.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"{elapsedTime.TotalMilliseconds * 1000:F2} 纳秒");
Console.ForegroundColor = ConsoleColor.Black;
Console.WriteLine();
if (isSuccessful && isResultEqual)
{
Console.BackgroundColor = successColor;
Console.Write("测试通过");
}
else
{
Console.BackgroundColor = failColor;
Console.Write("测试失败");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = failColor;
Console.WriteLine($"\t失败原因:{failedMessage}");
failedList.Add(new MethodAndCounter(method, CTimeCounter, failedMessage));
}
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
Console.ForegroundColor = methodBorderColor;
Console.Write("\n");
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
Console.ResetColor();
}
}
}
classTimeCounter.Stop();
CTimeCounter++;
Console.WriteLine("\n\n\n\n\n");
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("执行完成");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write("\t执行批次:");
Console.ForegroundColor = counterColor;
Console.Write(CTimeCounter);
Console.ForegroundColor = mainColor;
Console.Write("\t执行时间:");
Console.ForegroundColor = timeColor;
if (classTimeCounter.Elapsed.TotalHours >= 1)
Console.WriteLine(classTimeCounter.Elapsed);
else if (classTimeCounter.Elapsed.TotalMinutes >= 1)
Console.WriteLine($"{classTimeCounter.Elapsed.Minutes} 分 {classTimeCounter.Elapsed.Seconds} 秒 {classTimeCounter.Elapsed.Milliseconds} 毫秒");
else if (classTimeCounter.Elapsed.TotalSeconds >= 1)
Console.WriteLine($"{classTimeCounter.Elapsed.TotalSeconds:F3} 秒");
else if (classTimeCounter.Elapsed.TotalMilliseconds >= 1)
Console.WriteLine($"{classTimeCounter.Elapsed.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"{classTimeCounter.Elapsed.TotalMilliseconds * 1000:F2} 纳秒");
Console.ForegroundColor = ConsoleColor.Black;
Console.WriteLine();
if (failedList.Count == 0)
{
Console.BackgroundColor = successColor;
Console.Write("测试通过");
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine();
}
else
{
Console.BackgroundColor = failColor;
Console.Write("测试失败");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = failColor;
Console.WriteLine("\t未通过的方法:");
foreach (var failedMethod in failedList)
{
Console.ForegroundColor = mainColor;
Console.Write("\t\t方法名:");
Console.ForegroundColor = methodColor;
Console.Write(failedMethod.Method.Name);
Console.ForegroundColor = mainColor;
Console.Write("\t执行批次:");
Console.ForegroundColor = counterColor;
Console.Write(failedMethod.Counter);
Console.ForegroundColor = mainColor;
Console.Write("\t失败原因:");
Console.ForegroundColor = failColor;
Console.WriteLine(failedMethod.FailMessage);
}
}
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = classBorderColor;
Console.Write("\n");
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
Console.ResetColor();
}
}
}
/// <summary>
/// 断言:判断条件为真
/// </summary>
/// <param name="condition">判断条件</param>
protected static bool Assert(bool condition)
{
if (!condition)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = "断言失败:期望为真,实际为假";
return false;
}
return true;
}
/// <summary>
/// 断言:判断条件为真
/// </summary>
/// <param name="condition">判断条件</param>
/// <param name="message">消息</param>
protected static bool Assert(bool condition, string message)
{
if (!condition)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = message;
return false;
}
return true;
}
/// <summary>
/// 断言:判断条件为假
/// </summary>
/// <param name="condition">判断条件</param>
protected static bool AssertF(bool condition)
{
if (condition)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = "断言失败:期望为假,实际为真";
return false;
}
return true;
}
/// <summary>
/// 断言:判断条件为假
/// </summary>
/// <param name="condition">判断条件</param>
/// <param name="message">消息</param>
protected static bool AssertF(bool condition, string message)
{
if (condition)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = message;
return false;
}
return true;
}
/// <summary>
/// 断言:判断两个值是否相等
/// </summary>
/// <typeparam name="T">值的类型</typeparam>
/// <param name="expected">期望值</param>
/// <param name="actual">实际值</param>
protected static bool AssertE<T>(T expected, T actual)
{
var result = !EqualityComparer<T>.Default.Equals(expected, actual);
if (result)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = $"断言失败:期望 {expected},实际 {actual}";
return false;
}
return true;
}
/// <summary>
/// 断言:判断两个值是否相等
/// </summary>
/// <typeparam name="T">值的类型</typeparam>
/// <param name="expected">期望值</param>
/// <param name="actual">实际值</param>
/// <param name="message">消息</param>
protected static bool AssertE<T>(T expected, T actual, string message)
{
var result = !EqualityComparer<T>.Default.Equals(expected, actual);
if (result)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = message;
return false;
}
return true;
}
static XFECode()
{
new Action(async () => await RunTest()).StartNewTask();
}
}
#region 特性
/// <summary>
/// 测试颜色主题
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class TestThemeAttribute : Attribute
{
/// <summary>
/// 主色
/// </summary>
public ConsoleColor MainColor { get; set; }
/// <summary>
/// 类颜色
/// </summary>
public ConsoleColor ClassColor { get; set; }
/// <summary>
/// 类边框颜色
/// </summary>
public ConsoleColor ClassBorderColor { get; set; }
/// <summary>
/// 方法颜色
/// </summary>
public ConsoleColor MethodColor { get; set; }
/// <summary>
/// 方法边框颜色
/// </summary>
public ConsoleColor MethodBorderColor { get; set; }
/// <summary>
/// 成功颜色
/// </summary>
public ConsoleColor SuccessColor { get; set; }
/// <summary>
/// 失败颜色
/// </summary>
public ConsoleColor FailColor { get; set; }
/// <summary>
/// 时间颜色
/// </summary>
public ConsoleColor TimeColor { get; set; }
/// <summary>
/// 计数器颜色
/// </summary>
public ConsoleColor CounterColor { get; set; }
/// <summary>
/// 测试颜色主题
/// </summary>
/// <param name="mainColor">主色</param>
/// <param name="classColor">类颜色</param>
/// <param name="classBorderColor">类边框颜色</param>
/// <param name="methodColor">方法颜色</param>
/// <param name="methodBorderColor">方法边框颜色</param>
/// <param name="successColor">成功颜色</param>
/// <param name="failColor">失败颜色</param>
/// <param name="timeColor">时间颜色</param>
/// <param name="counterColor">计数器颜色</param>
public TestThemeAttribute(ConsoleColor mainColor = ConsoleColor.Blue, ConsoleColor classColor = ConsoleColor.Green, ConsoleColor classBorderColor = ConsoleColor.DarkGreen, ConsoleColor methodColor = ConsoleColor.Yellow, ConsoleColor methodBorderColor = ConsoleColor.DarkYellow, ConsoleColor successColor = ConsoleColor.Green, ConsoleColor failColor = ConsoleColor.Red, ConsoleColor timeColor = ConsoleColor.Cyan, ConsoleColor counterColor = ConsoleColor.Gray)
{
MainColor = mainColor;
ClassColor = classColor;
ClassBorderColor = classBorderColor;
MethodColor = methodColor;
MethodBorderColor = methodBorderColor;
SuccessColor = successColor;
FailColor = failColor;
TimeColor = timeColor;
CounterColor = counterColor;
}
}
/// <summary>
/// 测试特性基类
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class XFETestAttributeBase : Attribute
{
/// <summary>
/// 参数
/// </summary>
public object[] Params { get; set; }
}
/// <summary>
/// 用于计时的特性
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SMTestAttribute : XFETestAttributeBase
{
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
/// <param name="values">传参</param>
public SMTestAttribute(params object[] values)
{
Params = values;
}
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
public SMTestAttribute() { }
}
/// <summary>
/// 用于计时的特性,可自定义名称
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class SMNTestAttribute : SMTestAttribute
{
/// <summary>
/// 该次计时标识名
/// </summary>
public string TimerName { get; set; }
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
/// <param name="timerName">计时器名称</param>
/// <param name="values">传参</param>
public SMNTestAttribute(string timerName, params object[] values)
{
TimerName = timerName;
Params = values;
}
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
public SMNTestAttribute(string timerName)
{
TimerName = timerName;
}
}
/// <summary>
/// 用于计时的特性,可绑定返回值
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SMRTestAttribute : SMTestAttribute
{
/// <summary>
/// 返回值
/// </summary>
public object ReturnValue { get; set; }
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
/// <param name="valuesAndResult">传参</param>
public SMRTestAttribute(params object[] valuesAndResult)
{
ReturnValue = valuesAndResult[valuesAndResult.Length - 1];
Params = valuesAndResult.Take(valuesAndResult.Length - 1).ToArray();
}
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
public SMRTestAttribute() { }
}
/// <summary>
/// 用于计时的特性,可自定义名称和返回值
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class SMNRTestAttribute : SMRTestAttribute
{
/// <summary>
/// 该次计时标识名
/// </summary>
public string TimerName { get; set; }
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
/// <param name="timerName">计时器名称</param>
/// <param name="valuesAndResult">传参</param>
public SMNRTestAttribute(string timerName, params object[] valuesAndResult)
{
TimerName = timerName;
ReturnValue = valuesAndResult[valuesAndResult.Length - 1];
Params = valuesAndResult.Take(valuesAndResult.Length - 1).ToArray();
}
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
public SMNRTestAttribute() { }
}
/// <summary>
/// 方法测试
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MTestAttribute : XFETestAttributeBase
{
/// <summary>
/// 方法测试
/// </summary>
/// <param name="values">传参</param>
public MTestAttribute(params object[] values)
{
Params = values;
}
/// <summary>
/// 方法测试
/// </summary>
public MTestAttribute() { }
}
/// <summary>
/// 方法测试,可自定义名称
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class MNTestAttribute : MTestAttribute
{
/// <summary>
/// 方法别名
/// </summary>
public string MethodOtherName { get; set; }
/// <summary>
/// 方法测试
/// </summary>
/// <param name="methodOtherName">方法别名</param>
/// <param name="values">传参</param>
public MNTestAttribute(string methodOtherName, params object[] values)
{
MethodOtherName = methodOtherName;
Params = values;
}
/// <summary>
/// 方法测试
/// </summary>
/// <param name="methodOtherName">方法别名</param>
public MNTestAttribute(string methodOtherName)
{
MethodOtherName = methodOtherName;
}
/// <summary>
/// 方法测试
/// </summary>
public MNTestAttribute() { }
}
/// <summary>
/// 方法测试,可自定义返回值
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MRTestAttribute : MTestAttribute
{
/// <summary>
/// 返回值
/// </summary>
public object ReturnValue { get; set; }
/// <summary>
/// 方法测试
/// </summary>
/// <param name="valuesAndResult">传参</param>
public MRTestAttribute(params object[] valuesAndResult)
{
ReturnValue = valuesAndResult[valuesAndResult.Length - 1];
Params = valuesAndResult.Take(valuesAndResult.Length - 1).ToArray();
}
/// <summary>
/// 方法测试
/// </summary>
public MRTestAttribute() { }
}
/// <summary>
/// 方法测试,可自定义名称和返回值
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class MNRTestAttribute : MRTestAttribute
{
/// <summary>
/// 方法别名
/// </summary>
public string MethodOtherName { get; set; }
/// <summary>
/// 方法测试
/// </summary>
/// <param name="methodOtherName">方法别名</param>
/// <param name="valuesAndResult">传参</param>
public MNRTestAttribute(string methodOtherName, params object[] valuesAndResult)
{
MethodOtherName = methodOtherName;
ReturnValue = valuesAndResult[valuesAndResult.Length - 1];
Params = valuesAndResult.Take(valuesAndResult.Length - 1).ToArray();
}
/// <summary>
/// 方法测试
/// </summary>
public MNRTestAttribute() { }
}
/// <summary>
/// 类测试
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class CTestAttribute : XFETestAttributeBase
{
/// <summary>
/// 类测试
/// </summary>
/// <param name="values">创建类时构造方法的传参</param>
public CTestAttribute(params object[] values)
{
Params = values;
}
/// <summary>
/// 类测试
/// </summary>
public CTestAttribute() { }
}
/// <summary>
/// 类测试
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class CNTestAttribute : CTestAttribute
{
/// <summary>
/// 类别名
/// </summary>
public string ClassOtherName { get; set; }
/// <summary>
/// 类测试
/// </summary>
/// <param name="values">创建类时构造方法的传参</param>
/// <param name="classOtherName">类别名</param>
public CNTestAttribute(string classOtherName, params object[] values)
{
Params = values;
ClassOtherName = classOtherName;
}
}
/// <summary>
/// 用于标记测试类初始函数的特性
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public sealed class TSetUpAttribute : XFETestAttributeBase
{
/// <summary>
/// 用于标记测试类构造函数的特性
/// </summary>
/// <param name="values"></param>
public TSetUpAttribute(params object[] values)
{
Params = values;
}
}
#endregion
/// <summary>
/// 对代码整体书写习惯的拓展
/// </summary>
public static class XFEExtension
{
/// <summary>
/// 使得计时器可以直接调用(单位:秒)
/// </summary>
/// <param name="waitTime"></param>
/// <returns></returns>
public static TaskAwaiter GetAwaiter(this int waitTime)
=> Task.Delay(TimeSpan.FromSeconds(waitTime)).GetAwaiter();
/// <summary>
/// 使得计时器可以直接调用(单位:秒)
/// </summary>
/// <param name="waitTime"></param>
/// <returns></returns>
public static TaskAwaiter GetAwaiter(this double waitTime)
=> Task.Delay(TimeSpan.FromSeconds(waitTime)).GetAwaiter();
}
class MethodAndCounter
{
/// <summary>
/// 获取或设置当前测试记录对应的方法反射信息。
/// </summary>
public MethodInfo Method { get; set; }
/// <summary>
/// 获取或设置当前方法已执行或统计的次数。
/// </summary>
public int Counter { get; set; }
/// <summary>
/// 获取或设置当前方法测试失败时使用的说明信息。
/// </summary>
public string FailMessage { get; set; }
/// <summary>
/// 创建包含方法、计数值和失败说明的测试记录。
/// </summary>
/// <param name="method">当前测试记录对应的方法反射信息。</param>
/// <param name="counter">方法已执行或统计的次数。</param>
/// <param name="failMessage">方法测试失败时使用的说明信息。</param>
public MethodAndCounter(MethodInfo method, int counter, string failMessage)
{
Method = method;
Counter = counter;
FailMessage = failMessage;
}
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using XFEExtension.ArrayExtension;
using XFEExtension.AttributeExtension;
using XFEExtension.ReflectionExtension;
using XFEExtension.StringExtension;
using XFEExtension.TaskExtension;
namespace XFEExtension
{
#region 异常
/// <summary>
/// XFEExtension的异常
/// </summary>
public class XFEExtensionException : Exception
{
/// <summary>
/// XFEExtension的异常
/// </summary>
/// <param name="message"></param>
internal XFEExtensionException(string message) : base(message) { }
/// <summary>
/// XFEExtension的异常
/// </summary>
/// <param name="message"></param>
/// <param name="innerException"></param>
internal XFEExtensionException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFEJson转换的异常
/// </summary>
public class XFEJsonTransformException : XFEExtensionException
{
/// <summary>
/// XFEJson转换的异常
/// </summary>
/// <param name="message"></param>
internal XFEJsonTransformException(string message) : base(message) { }
/// <summary>
/// XFEJson转换的异常
/// </summary>
/// <param name="message"></param>
/// <param name="innerException"></param>
internal XFEJsonTransformException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFEChatGPT的异常
/// </summary>
public class XFEChatGPTException : XFEExtensionException
{
/// <summary>
/// XFEChatGPT的异常
/// </summary>
/// <param name="message"></param>
internal XFEChatGPTException(string message) : base(message) { }
internal XFEChatGPTException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFE网络通信的异常
/// </summary>
public class XFECyberCommException : XFEExtensionException
{
/// <summary>
/// XFE网络通信的异常
/// </summary>
/// <param name="message"></param>
internal XFECyberCommException(string message) : base(message) { }
internal XFECyberCommException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFE邮件的异常
/// </summary>
public class XFEMailException : XFEExtensionException
{
internal XFEMailException(string message) : base(message) { }
internal XFEMailException(string message, Exception innerException) : base(message, innerException) { }
}
/// <summary>
/// XFE字典的异常
/// </summary>
public class XFEDictionaryException : XFEExtensionException
{
internal XFEDictionaryException(string message) : base(message) { }
internal XFEDictionaryException(string message, Exception innerException) : base(message, innerException) { }
}
#endregion
/// <summary>
/// XFEExtension编写
/// </summary>
public abstract class XFECode
{
private static int CTimeCounter = 0;
private static bool CurrentMethodIsAsserted = false;
private static string CurrentAssertMessage = string.Empty;
#region 暂停
/// <summary>
/// 暂停
/// </summary>
/// <param name="ShowText">是否显示提示</param>
protected static void Pause(bool ShowText = true)
{
if (ShowText)
{
Console.WriteLine("按任意键继续...");
}
Console.ReadKey();
}
/// <summary>
/// 暂停
/// </summary>
/// <param name="ShowText">显示的文字</param>
protected static void Pause(string ShowText)
{
Console.WriteLine(ShowText);
Console.ReadKey();
}
/// <summary>
/// 暂停,按下指定按键继续
/// </summary>
/// <param name="consoleKey">指定的按键</param>
protected static void Pause(ConsoleKey consoleKey)
{
Console.WriteLine($"按 {consoleKey} 键继续");
while (Console.ReadKey().Key != consoleKey) ;
}
/// <summary>
/// 暂停,按下指定按键继续
/// </summary>
/// <param name="consoleKey">指定的按键</param>
/// <param name="ShowText">显示的文字</param>
protected static void Pause(ConsoleKey consoleKey, string ShowText)
{
Console.WriteLine(ShowText);
while (Console.ReadKey().Key != consoleKey) ;
}
#endregion
/// <summary>
/// 并行循环指定次数
/// </summary>
/// <param name="action">执行的操作</param>
/// <param name="count">循环次数</param>
/// <param name="autoWaitAll">自动等待所有线程执行完毕</param>
protected static async Task<List<Task>> Circle(Action action, int count, bool autoWaitAll = false)
{
var taskList = new List<Task>();
for (int i = 0; i < count; i++)
{
taskList.Add(action.StartNewTask());
}
if (autoWaitAll)
await Task.WhenAll(taskList);
return taskList;
}
/// <summary>
/// 并行循环指定次数
/// </summary>
/// <param name="action">执行的操作</param>
/// <param name="count">循环次数</param>
protected static async void CircleOrderly(Action action, int count)
{
for (int i = 0; i < count; i++)
{
await action.StartNewTask();
}
}
/// <summary>
/// 计算一段代码执行所需时间
/// </summary>
/// <param name="action"></param>
/// <param name="autoOutPut">自动输出</param>
/// <param name="timerName">该次计时标识名</param>
/// <returns></returns>
public static TimeSpan CTime(Action action, bool autoOutPut = true, string timerName = "无标识名计时器")
{
var timeCounter = new Stopwatch();
timeCounter.Start();
action?.Invoke();
timeCounter.Stop();
CTimeCounter++;
var elapsedTime = timeCounter.Elapsed;
if (autoOutPut)
if (elapsedTime.TotalHours >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间:{elapsedTime}");
else if (elapsedTime.TotalMinutes >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {Math.Floor(elapsedTime.TotalMinutes)} 分 {elapsedTime.Seconds} 秒");
else if (elapsedTime.TotalSeconds >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalSeconds:F3} 秒");
else if (elapsedTime.TotalMilliseconds >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalMilliseconds * 1000:F3} 纳秒");
return elapsedTime;
}
/// <summary>
/// 计算一段代码执行所需时间
/// </summary>
/// <param name="action"></param>
/// <param name="autoOutPut">自动输出</param>
/// <param name="timerName">该次计时标识名</param>
/// <returns></returns>
public static async Task<TimeSpan> CTimeAsync(Func<Task> action, bool autoOutPut = true, string timerName = "无标识名计时器")
{
var timeCounter = new Stopwatch();
timeCounter.Start();
await action?.Invoke();
timeCounter.Stop();
CTimeCounter++;
var elapsedTime = timeCounter.Elapsed;
if (autoOutPut)
if (elapsedTime.TotalHours >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间:{elapsedTime}");
else if (elapsedTime.TotalMinutes >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {Math.Floor(elapsedTime.TotalMinutes)} 分 {elapsedTime.Seconds} 秒");
else if (elapsedTime.TotalSeconds >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalSeconds:F3} 秒");
else if (elapsedTime.TotalMilliseconds >= 1)
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"标识名:{timerName}\t执行批次:{CTimeCounter}\t执行时间: {elapsedTime.TotalMilliseconds * 1000:F3} 纳秒");
return elapsedTime;
}
/// <summary>
/// 计算一段代码执行所需时间
/// </summary>
/// <returns></returns>
/// <exception cref="XFEExtensionException"></exception>
protected static async Task RunTest()
{
var isFirstClass = true;
var subClasses = Assembly.GetEntryAssembly().GetTypes()
.Where(type => type.IsSubclassOf(typeof(XFECode)));
foreach (var subClass in subClasses)
{
var mainColor = ConsoleColor.Blue;
var classColor = ConsoleColor.Green;
var classBorderColor = ConsoleColor.DarkGreen;
var methodColor = ConsoleColor.Yellow;
var methodBorderColor = ConsoleColor.DarkYellow;
var successColor = ConsoleColor.Green;
var failColor = ConsoleColor.Red;
var timeColor = ConsoleColor.Cyan;
var counterColor = ConsoleColor.Gray;
if (subClass.GetCustomAttributes(typeof(TestThemeAttribute), false).FirstOrDefault() is TestThemeAttribute themeAttribute)
{
mainColor = themeAttribute.MainColor;
classColor = themeAttribute.ClassColor;
classBorderColor = themeAttribute.ClassBorderColor;
methodColor = themeAttribute.MethodColor;
methodBorderColor = themeAttribute.MethodBorderColor;
successColor = themeAttribute.SuccessColor;
failColor = themeAttribute.FailColor;
timeColor = themeAttribute.TimeColor;
counterColor = themeAttribute.CounterColor;
}
var singleRunMethods = subClass.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).Where(m => m.IsDefined(typeof(SMTestAttribute)));
#region 静态测试
var isFirstStaticMethod = true;
foreach (var method in singleRunMethods)
{
var attributes = method.GetCustomAttributes(typeof(SMTestAttribute));
foreach (var likeAttribute in attributes)
{
if (likeAttribute is SMTestAttribute attribute)
{
string timerName = "方法名:" + method.Name;
if (likeAttribute is SMNTestAttribute subAttribute)
{
timerName = "标识名:" + subAttribute.TimerName;
}
if (attribute is SMNRTestAttribute resultAttribute)
{
timerName = "标识名:" + resultAttribute.TimerName;
}
object[] paramsForMethod = null;
if (attribute.Params != null)
{
paramsForMethod = attribute.Params;
}
else
{
paramsForMethod = method.GetDefaultParameters();
}
var timeCounter = new Stopwatch();
var selfTimeCounter = new Stopwatch();
var elapsedTime = new TimeSpan();
var isSuccessful = true;
var isResultEqual = true;
var failedMessage = string.Empty;
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = methodBorderColor;
if (isFirstStaticMethod)
{
isFirstStaticMethod = false;
}
else
{
Console.WriteLine("\n\n\n\n\n");
}
var borderCount = (Console.BufferWidth - timerName.DisplayLength()) / 2;
if (timerName != null)
{
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
if ((Console.BufferWidth - timerName.DisplayLength()) % 2 == 1)
Console.Write("=");
Console.ForegroundColor = mainColor;
Console.Write(timerName.Substring(0, 4));
Console.ForegroundColor = methodColor;
Console.Write(timerName.Substring(4));
Console.ForegroundColor = methodBorderColor;
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
}
else
{
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
}
Console.WriteLine("\n");
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("开始执行");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write($"\t方法:");
Console.ForegroundColor = methodColor;
Console.Write(method.Name);
Console.ForegroundColor = mainColor;
Console.Write($"\t类:");
Console.ForegroundColor = classColor;
Console.WriteLine($"{subClass.Name}\n");
Console.ResetColor();
selfTimeCounter.Start();
selfTimeCounter.Stop();
try
{
CurrentMethodIsAsserted = false;
if (method.ReturnType == typeof(Task))
{
timeCounter.Start();
await (Task)method.Invoke(Activator.CreateInstance(subClass), paramsForMethod);
timeCounter.Stop();
}
else
{
timeCounter.Start();
var result = method.Invoke(Activator.CreateInstance(subClass), paramsForMethod);
timeCounter.Stop();
if (attribute is SMRTestAttribute resultAttribute2)
{
isResultEqual = result.Equals(resultAttribute2.ReturnValue);
if (!isResultEqual)
{
isSuccessful = false;
failedMessage = $"预期结果:{resultAttribute2.ReturnValue}\t实际结果:{result}";
}
}
}
if (CurrentMethodIsAsserted)
{
isSuccessful = false;
if (failedMessage == string.Empty)
failedMessage = CurrentAssertMessage;
else
failedMessage += $"\n{CurrentAssertMessage}";
CurrentMethodIsAsserted = false;
CurrentAssertMessage = string.Empty;
}
}
catch (Exception e)
{
isSuccessful = false;
failedMessage = e.Message;
}
elapsedTime = timeCounter.Elapsed - selfTimeCounter.Elapsed;
CTimeCounter++;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine();
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("执行完成");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write("\t执行批次:");
Console.ForegroundColor = counterColor;
Console.Write(CTimeCounter);
Console.ForegroundColor = mainColor;
Console.Write("\t执行时间:");
Console.ForegroundColor = timeColor;
if (elapsedTime.TotalHours >= 1)
Console.WriteLine(elapsedTime);
else if (elapsedTime.TotalMinutes >= 1)
Console.WriteLine($"{elapsedTime.Minutes} 分 {elapsedTime.Seconds} 秒 {elapsedTime.Milliseconds} 毫秒");
else if (elapsedTime.TotalSeconds >= 1)
Console.WriteLine($"{elapsedTime.TotalSeconds:F3} 秒");
else if (elapsedTime.TotalMilliseconds >= 1)
Console.WriteLine($"{elapsedTime.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"{elapsedTime.TotalMilliseconds * 1000:F2} 纳秒");
Console.ForegroundColor = ConsoleColor.Black;
Console.WriteLine();
if (isSuccessful && isResultEqual)
{
Console.BackgroundColor = successColor;
Console.Write("测试通过");
}
else
{
Console.BackgroundColor = failColor;
Console.Write("测试失败");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = failColor;
Console.WriteLine($"\t失败原因:{failedMessage}");
}
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
Console.ForegroundColor = methodBorderColor;
Console.Write("\n");
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
Console.ResetColor();
Console.WriteLine("\n");
Console.WriteLine("\n");
}
}
}
#endregion
var classAttributes = subClass.GetCustomAttributes(typeof(CTestAttribute));
var classRunMethods = subClass.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).Where(m => m.IsDefined(typeof(MTestAttribute)));
foreach (var classAttribute in classAttributes.Cast<CTestAttribute>())
{
var isFirstMethod = true;
var failedList = new List<MethodAndCounter>();
object classInstance = classAttribute.Params is null;
if (classAttribute.Params is null)
{
classInstance = subClass.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null).Invoke(classAttribute.Params);
}
else
{
classInstance = subClass.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, classAttribute.Params.GetTypes(), null).Invoke(classAttribute.Params);
}
var setUpAttribute = subClass.GetAttribute<TSetUpAttribute>();
if (setUpAttribute != null)
{
var setUpMethod = subClass.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).Where(m => m.IsDefined(typeof(TSetUpAttribute))).FirstOrDefault();
if (setUpMethod != null)
{
setUpMethod.Invoke(classInstance, setUpMethod.GetDefaultParameters());
}
}
string classOtherName = "类名:" + subClass.Name;
if (classAttribute is CNTestAttribute subClassAttribute)
{
classOtherName = "标识名:" + subClassAttribute.ClassOtherName;
}
var classTimeCounter = new Stopwatch();
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = classBorderColor;
if (isFirstClass)
{
isFirstClass = false;
}
else
{
Console.WriteLine("\n\n\n\n\n\n\n\n");
}
var borderCount = (Console.BufferWidth - classOtherName.DisplayLength()) / 2;
if (classOtherName != null)
{
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
if ((Console.BufferWidth - classOtherName.DisplayLength()) % 2 == 1)
Console.Write("=");
Console.ForegroundColor = mainColor;
if (classOtherName.Substring(0, 4) == "标识名:")
{
Console.Write(classOtherName.Substring(0, 4));
Console.ForegroundColor = classColor;
Console.Write(classOtherName.Substring(4));
}
else
{
Console.Write(classOtherName.Substring(0, 3));
Console.ForegroundColor = classColor;
Console.Write(classOtherName.Substring(3));
}
Console.ForegroundColor = classBorderColor;
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
}
else
{
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
}
Console.WriteLine("\n");
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("开始执行");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write("\t类名:");
Console.ForegroundColor = classColor;
Console.WriteLine($"{subClass.Name}\n\n\n\n\n");
Console.ResetColor();
classTimeCounter.Start();
foreach (var method in classRunMethods)
{
var attributes = method.GetCustomAttributes(typeof(MTestAttribute));
foreach (MTestAttribute attribute in attributes)
{
if (attribute is MTestAttribute methodAttribute)
{
string methodOtherName = "方法名:" + method.Name;
if (attribute is MNTestAttribute subAttribute)
{
methodOtherName = "标识名:" + subAttribute.MethodOtherName;
}
if (attribute is MNRTestAttribute resultAttribute)
{
methodOtherName = "标识名:" + resultAttribute.MethodOtherName;
}
object[] paramsForMethod = null;
if (attribute.Params != null)
{
paramsForMethod = attribute.Params;
}
else
{
paramsForMethod = method.GetDefaultParameters();
}
var timeCounter = new Stopwatch();
var selfTimeCounter = new Stopwatch();
var elapsedTime = new TimeSpan();
var isSuccessful = true;
var isResultEqual = true;
var failedMessage = string.Empty;
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = methodBorderColor;
if (isFirstMethod)
{
isFirstMethod = false;
}
else
{
Console.WriteLine("\n\n\n\n\n");
}
borderCount = (Console.BufferWidth - methodOtherName.DisplayLength()) / 2;
if (methodOtherName != null)
{
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
if ((Console.BufferWidth - methodOtherName.DisplayLength()) % 2 == 1)
Console.Write("=");
Console.ForegroundColor = mainColor;
Console.Write(methodOtherName.Substring(0, 4));
Console.ForegroundColor = methodColor;
Console.Write(methodOtherName.Substring(4));
Console.ForegroundColor = methodBorderColor;
for (int i = 0; i < borderCount; i++)
{
Console.Write("=");
}
}
else
{
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
}
Console.WriteLine("\n");
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("开始执行");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write($"\t方法:");
Console.ForegroundColor = methodColor;
Console.Write(method.Name);
Console.ForegroundColor = mainColor;
Console.Write($"\t类:");
Console.ForegroundColor = classColor;
Console.WriteLine($"{subClass.Name}\n");
Console.ResetColor();
selfTimeCounter.Start();
selfTimeCounter.Stop();
try
{
CurrentMethodIsAsserted = false;
if (method.ReturnType == typeof(Task))
{
timeCounter.Start();
await (Task)method.Invoke(classInstance, paramsForMethod);
timeCounter.Stop();
}
else
{
timeCounter.Start();
var result = method.Invoke(classInstance, paramsForMethod);
timeCounter.Stop();
if (methodAttribute is MRTestAttribute resultAttribute2)
{
isResultEqual = result.Equals(resultAttribute2.ReturnValue);
if (!isResultEqual)
{
isSuccessful = false;
failedMessage = $"预期结果:{resultAttribute2.ReturnValue}\t实际结果:{result}";
}
}
}
if (CurrentMethodIsAsserted)
{
isSuccessful = false;
if (failedMessage == string.Empty)
failedMessage = CurrentAssertMessage;
else
failedMessage += $"\n{CurrentAssertMessage}";
CurrentMethodIsAsserted = false;
CurrentAssertMessage = string.Empty;
}
}
catch (Exception e)
{
isSuccessful = false;
failedMessage = e.Message;
}
elapsedTime = timeCounter.Elapsed - selfTimeCounter.Elapsed;
CTimeCounter++;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine();
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("执行完成");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write("\t执行批次:");
Console.ForegroundColor = counterColor;
Console.Write(CTimeCounter);
Console.ForegroundColor = mainColor;
Console.Write("\t执行时间:");
Console.ForegroundColor = timeColor;
if (elapsedTime.TotalHours >= 1)
Console.WriteLine(elapsedTime);
else if (elapsedTime.TotalMinutes >= 1)
Console.WriteLine($"{elapsedTime.Minutes} 分 {elapsedTime.Seconds} 秒 {elapsedTime.Milliseconds} 毫秒");
else if (elapsedTime.TotalSeconds >= 1)
Console.WriteLine($"{elapsedTime.TotalSeconds:F3} 秒");
else if (elapsedTime.TotalMilliseconds >= 1)
Console.WriteLine($"{elapsedTime.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"{elapsedTime.TotalMilliseconds * 1000:F2} 纳秒");
Console.ForegroundColor = ConsoleColor.Black;
Console.WriteLine();
if (isSuccessful && isResultEqual)
{
Console.BackgroundColor = successColor;
Console.Write("测试通过");
}
else
{
Console.BackgroundColor = failColor;
Console.Write("测试失败");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = failColor;
Console.WriteLine($"\t失败原因:{failedMessage}");
failedList.Add(new MethodAndCounter(method, CTimeCounter, failedMessage));
}
Console.BackgroundColor = ConsoleColor.Black;
Console.Write("\n");
Console.ForegroundColor = methodBorderColor;
Console.Write("\n");
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
Console.ResetColor();
}
}
}
classTimeCounter.Stop();
CTimeCounter++;
Console.WriteLine("\n\n\n\n\n");
Console.BackgroundColor = mainColor;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write("执行完成");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = mainColor;
Console.Write("\t执行批次:");
Console.ForegroundColor = counterColor;
Console.Write(CTimeCounter);
Console.ForegroundColor = mainColor;
Console.Write("\t执行时间:");
Console.ForegroundColor = timeColor;
if (classTimeCounter.Elapsed.TotalHours >= 1)
Console.WriteLine(classTimeCounter.Elapsed);
else if (classTimeCounter.Elapsed.TotalMinutes >= 1)
Console.WriteLine($"{classTimeCounter.Elapsed.Minutes} 分 {classTimeCounter.Elapsed.Seconds} 秒 {classTimeCounter.Elapsed.Milliseconds} 毫秒");
else if (classTimeCounter.Elapsed.TotalSeconds >= 1)
Console.WriteLine($"{classTimeCounter.Elapsed.TotalSeconds:F3} 秒");
else if (classTimeCounter.Elapsed.TotalMilliseconds >= 1)
Console.WriteLine($"{classTimeCounter.Elapsed.TotalMilliseconds:F3} 毫秒");
else
Console.WriteLine($"{classTimeCounter.Elapsed.TotalMilliseconds * 1000:F2} 纳秒");
Console.ForegroundColor = ConsoleColor.Black;
Console.WriteLine();
if (failedList.Count == 0)
{
Console.BackgroundColor = successColor;
Console.Write("测试通过");
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine();
}
else
{
Console.BackgroundColor = failColor;
Console.Write("测试失败");
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = failColor;
Console.WriteLine("\t未通过的方法:");
foreach (var failedMethod in failedList)
{
Console.ForegroundColor = mainColor;
Console.Write("\t\t方法名:");
Console.ForegroundColor = methodColor;
Console.Write(failedMethod.Method.Name);
Console.ForegroundColor = mainColor;
Console.Write("\t执行批次:");
Console.ForegroundColor = counterColor;
Console.Write(failedMethod.Counter);
Console.ForegroundColor = mainColor;
Console.Write("\t失败原因:");
Console.ForegroundColor = failColor;
Console.WriteLine(failedMethod.FailMessage);
}
}
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = classBorderColor;
Console.Write("\n");
for (int i = 0; i < Console.BufferWidth; i++)
{
Console.Write("=");
}
Console.ResetColor();
}
}
}
/// <summary>
/// 断言:判断条件为真
/// </summary>
/// <param name="condition">判断条件</param>
protected static bool Assert(bool condition)
{
if (!condition)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = "断言失败:期望为真,实际为假";
return false;
}
return true;
}
/// <summary>
/// 断言:判断条件为真
/// </summary>
/// <param name="condition">判断条件</param>
/// <param name="message">消息</param>
protected static bool Assert(bool condition, string message)
{
if (!condition)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = message;
return false;
}
return true;
}
/// <summary>
/// 断言:判断条件为假
/// </summary>
/// <param name="condition">判断条件</param>
protected static bool AssertF(bool condition)
{
if (condition)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = "断言失败:期望为假,实际为真";
return false;
}
return true;
}
/// <summary>
/// 断言:判断条件为假
/// </summary>
/// <param name="condition">判断条件</param>
/// <param name="message">消息</param>
protected static bool AssertF(bool condition, string message)
{
if (condition)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = message;
return false;
}
return true;
}
/// <summary>
/// 断言:判断两个值是否相等
/// </summary>
/// <typeparam name="T">值的类型</typeparam>
/// <param name="expected">期望值</param>
/// <param name="actual">实际值</param>
protected static bool AssertE<T>(T expected, T actual)
{
var result = !EqualityComparer<T>.Default.Equals(expected, actual);
if (result)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = $"断言失败:期望 {expected},实际 {actual}";
return false;
}
return true;
}
/// <summary>
/// 断言:判断两个值是否相等
/// </summary>
/// <typeparam name="T">值的类型</typeparam>
/// <param name="expected">期望值</param>
/// <param name="actual">实际值</param>
/// <param name="message">消息</param>
protected static bool AssertE<T>(T expected, T actual, string message)
{
var result = !EqualityComparer<T>.Default.Equals(expected, actual);
if (result)
{
CurrentMethodIsAsserted = true;
CurrentAssertMessage = message;
return false;
}
return true;
}
static XFECode()
{
new Action(async () => await RunTest()).StartNewTask();
}
}
#region 特性
/// <summary>
/// 测试颜色主题
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class TestThemeAttribute : Attribute
{
/// <summary>
/// 主色
/// </summary>
public ConsoleColor MainColor { get; set; }
/// <summary>
/// 类颜色
/// </summary>
public ConsoleColor ClassColor { get; set; }
/// <summary>
/// 类边框颜色
/// </summary>
public ConsoleColor ClassBorderColor { get; set; }
/// <summary>
/// 方法颜色
/// </summary>
public ConsoleColor MethodColor { get; set; }
/// <summary>
/// 方法边框颜色
/// </summary>
public ConsoleColor MethodBorderColor { get; set; }
/// <summary>
/// 成功颜色
/// </summary>
public ConsoleColor SuccessColor { get; set; }
/// <summary>
/// 失败颜色
/// </summary>
public ConsoleColor FailColor { get; set; }
/// <summary>
/// 时间颜色
/// </summary>
public ConsoleColor TimeColor { get; set; }
/// <summary>
/// 计数器颜色
/// </summary>
public ConsoleColor CounterColor { get; set; }
/// <summary>
/// 测试颜色主题
/// </summary>
/// <param name="mainColor">主色</param>
/// <param name="classColor">类颜色</param>
/// <param name="classBorderColor">类边框颜色</param>
/// <param name="methodColor">方法颜色</param>
/// <param name="methodBorderColor">方法边框颜色</param>
/// <param name="successColor">成功颜色</param>
/// <param name="failColor">失败颜色</param>
/// <param name="timeColor">时间颜色</param>
/// <param name="counterColor">计数器颜色</param>
public TestThemeAttribute(ConsoleColor mainColor = ConsoleColor.Blue, ConsoleColor classColor = ConsoleColor.Green, ConsoleColor classBorderColor = ConsoleColor.DarkGreen, ConsoleColor methodColor = ConsoleColor.Yellow, ConsoleColor methodBorderColor = ConsoleColor.DarkYellow, ConsoleColor successColor = ConsoleColor.Green, ConsoleColor failColor = ConsoleColor.Red, ConsoleColor timeColor = ConsoleColor.Cyan, ConsoleColor counterColor = ConsoleColor.Gray)
{
MainColor = mainColor;
ClassColor = classColor;
ClassBorderColor = classBorderColor;
MethodColor = methodColor;
MethodBorderColor = methodBorderColor;
SuccessColor = successColor;
FailColor = failColor;
TimeColor = timeColor;
CounterColor = counterColor;
}
}
/// <summary>
/// 测试特性基类
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class XFETestAttributeBase : Attribute
{
/// <summary>
/// 参数
/// </summary>
public object[] Params { get; set; }
}
/// <summary>
/// 用于计时的特性
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SMTestAttribute : XFETestAttributeBase
{
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
/// <param name="values">传参</param>
public SMTestAttribute(params object[] values)
{
Params = values;
}
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
public SMTestAttribute() { }
}
/// <summary>
/// 用于计时的特性,可自定义名称
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class SMNTestAttribute : SMTestAttribute
{
/// <summary>
/// 该次计时标识名
/// </summary>
public string TimerName { get; set; }
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
/// <param name="timerName">计时器名称</param>
/// <param name="values">传参</param>
public SMNTestAttribute(string timerName, params object[] values)
{
TimerName = timerName;
Params = values;
}
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
public SMNTestAttribute(string timerName)
{
TimerName = timerName;
}
}
/// <summary>
/// 用于计时的特性,可绑定返回值
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SMRTestAttribute : SMTestAttribute
{
/// <summary>
/// 返回值
/// </summary>
public object ReturnValue { get; set; }
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
/// <param name="valuesAndResult">传参</param>
public SMRTestAttribute(params object[] valuesAndResult)
{
ReturnValue = valuesAndResult[valuesAndResult.Length - 1];
Params = valuesAndResult.Take(valuesAndResult.Length - 1).ToArray();
}
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
public SMRTestAttribute() { }
}
/// <summary>
/// 用于计时的特性,可自定义名称和返回值
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class SMNRTestAttribute : SMRTestAttribute
{
/// <summary>
/// 该次计时标识名
/// </summary>
public string TimerName { get; set; }
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
/// <param name="timerName">计时器名称</param>
/// <param name="valuesAndResult">传参</param>
public SMNRTestAttribute(string timerName, params object[] valuesAndResult)
{
TimerName = timerName;
ReturnValue = valuesAndResult[valuesAndResult.Length - 1];
Params = valuesAndResult.Take(valuesAndResult.Length - 1).ToArray();
}
/// <summary>
/// 计算执行一段代码所需时间
/// </summary>
public SMNRTestAttribute() { }
}
/// <summary>
/// 方法测试
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MTestAttribute : XFETestAttributeBase
{
/// <summary>
/// 方法测试
/// </summary>
/// <param name="values">传参</param>
public MTestAttribute(params object[] values)
{
Params = values;
}
/// <summary>
/// 方法测试
/// </summary>
public MTestAttribute() { }
}
/// <summary>
/// 方法测试,可自定义名称
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class MNTestAttribute : MTestAttribute
{
/// <summary>
/// 方法别名
/// </summary>
public string MethodOtherName { get; set; }
/// <summary>
/// 方法测试
/// </summary>
/// <param name="methodOtherName">方法别名</param>
/// <param name="values">传参</param>
public MNTestAttribute(string methodOtherName, params object[] values)
{
MethodOtherName = methodOtherName;
Params = values;
}
/// <summary>
/// 方法测试
/// </summary>
/// <param name="methodOtherName">方法别名</param>
public MNTestAttribute(string methodOtherName)
{
MethodOtherName = methodOtherName;
}
/// <summary>
/// 方法测试
/// </summary>
public MNTestAttribute() { }
}
/// <summary>
/// 方法测试,可自定义返回值
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MRTestAttribute : MTestAttribute
{
/// <summary>
/// 返回值
/// </summary>
public object ReturnValue { get; set; }
/// <summary>
/// 方法测试
/// </summary>
/// <param name="valuesAndResult">传参</param>
public MRTestAttribute(params object[] valuesAndResult)
{
ReturnValue = valuesAndResult[valuesAndResult.Length - 1];
Params = valuesAndResult.Take(valuesAndResult.Length - 1).ToArray();
}
/// <summary>
/// 方法测试
/// </summary>
public MRTestAttribute() { }
}
/// <summary>
/// 方法测试,可自定义名称和返回值
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class MNRTestAttribute : MRTestAttribute
{
/// <summary>
/// 方法别名
/// </summary>
public string MethodOtherName { get; set; }
/// <summary>
/// 方法测试
/// </summary>
/// <param name="methodOtherName">方法别名</param>
/// <param name="valuesAndResult">传参</param>
public MNRTestAttribute(string methodOtherName, params object[] valuesAndResult)
{
MethodOtherName = methodOtherName;
ReturnValue = valuesAndResult[valuesAndResult.Length - 1];
Params = valuesAndResult.Take(valuesAndResult.Length - 1).ToArray();
}
/// <summary>
/// 方法测试
/// </summary>
public MNRTestAttribute() { }
}
/// <summary>
/// 类测试
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class CTestAttribute : XFETestAttributeBase
{
/// <summary>
/// 类测试
/// </summary>
/// <param name="values">创建类时构造方法的传参</param>
public CTestAttribute(params object[] values)
{
Params = values;
}
/// <summary>
/// 类测试
/// </summary>
public CTestAttribute() { }
}
/// <summary>
/// 类测试
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class CNTestAttribute : CTestAttribute
{
/// <summary>
/// 类别名
/// </summary>
public string ClassOtherName { get; set; }
/// <summary>
/// 类测试
/// </summary>
/// <param name="values">创建类时构造方法的传参</param>
/// <param name="classOtherName">类别名</param>
public CNTestAttribute(string classOtherName, params object[] values)
{
Params = values;
ClassOtherName = classOtherName;
}
}
/// <summary>
/// 用于标记测试类初始函数的特性
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public sealed class TSetUpAttribute : XFETestAttributeBase
{
/// <summary>
/// 用于标记测试类构造函数的特性
/// </summary>
/// <param name="values"></param>
public TSetUpAttribute(params object[] values)
{
Params = values;
}
}
#endregion
/// <summary>
/// 对代码整体书写习惯的拓展
/// </summary>
public static class XFEExtension
{
/// <summary>
/// 使得计时器可以直接调用(单位:秒)
/// </summary>
/// <param name="waitTime"></param>
/// <returns></returns>
public static TaskAwaiter GetAwaiter(this int waitTime)
=> Task.Delay(TimeSpan.FromSeconds(waitTime)).GetAwaiter();
/// <summary>
/// 使得计时器可以直接调用(单位:秒)
/// </summary>
/// <param name="waitTime"></param>
/// <returns></returns>
public static TaskAwaiter GetAwaiter(this double waitTime)
=> Task.Delay(TimeSpan.FromSeconds(waitTime)).GetAwaiter();
}
class MethodAndCounter
{
/// <summary>
/// 获取或设置当前测试记录对应的方法反射信息。
/// </summary>
public MethodInfo Method { get; set; }
/// <summary>
/// 获取或设置当前方法已执行或统计的次数。
/// </summary>
public int Counter { get; set; }
/// <summary>
/// 获取或设置当前方法测试失败时使用的说明信息。
/// </summary>
public string FailMessage { get; set; }
/// <summary>
/// 创建包含方法、计数值和失败说明的测试记录。
/// </summary>
/// <param name="method">当前测试记录对应的方法反射信息。</param>
/// <param name="counter">方法已执行或统计的次数。</param>
/// <param name="failMessage">方法测试失败时使用的说明信息。</param>
public MethodAndCounter(MethodInfo method, int counter, string failMessage)
{
Method = method;
Counter = counter;
FailMessage = failMessage;
}
}
}