diff --git a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaProject_UnitTestAdapterPackage.cs b/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaProject_UnitTestAdapterPackage.cs
deleted file mode 100644
index 2ffb1148274c2fb4bd8bb73ca7d49d6e35bb98cf..0000000000000000000000000000000000000000
--- a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaProject_UnitTestAdapterPackage.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using Microsoft.VisualStudio.Shell;
-using System;
-using System.Runtime.InteropServices;
-using System.Threading;
-using Task = System.Threading.Tasks.Task;
-
-namespace NahidaProject_UnitTestAdapter
-{
- ///
- /// This is the class that implements the package exposed by this assembly.
- ///
- ///
- ///
- /// The minimum requirement for a class to be considered a valid package for Visual Studio
- /// is to implement the IVsPackage interface and register itself with the shell.
- /// This package uses the helper classes defined inside the Managed Package Framework (MPF)
- /// to do it: it derives from the Package class that provides the implementation of the
- /// IVsPackage interface and uses the registration attributes defined in the framework to
- /// register itself and its components with the shell. These attributes tell the pkgdef creation
- /// utility what data to put into .pkgdef file.
- ///
- ///
- /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file.
- ///
- ///
- [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
- [Guid(NahidaProject_UnitTestAdapterPackage.PackageGuidString)]
- public sealed class NahidaProject_UnitTestAdapterPackage : AsyncPackage
- {
- ///
- /// NahidaProject_UnitTestAdapterPackage GUID string.
- ///
- public const string PackageGuidString = "84132a2c-5bdf-48b1-bb36-922aed519d10";
-
- #region Package Members
-
- ///
- /// Initialization of the package; this method is called right after the package is sited, so this is the place
- /// where you can put all the initialization code that rely on services provided by VisualStudio.
- ///
- /// A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down.
- /// A provider for progress updates.
- /// A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method.
- protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress)
- {
- // When initialized asynchronously, the current thread may be a background thread at this point.
- // Do any initialization that requires the UI thread after switching to the UI thread.
- await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
- }
-
- #endregion
- }
-}
diff --git a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaUnitTestAdapter.cs b/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaUnitTestAdapter.cs
deleted file mode 100644
index b538674c3048fe475cb3343a598aace0b2181f76..0000000000000000000000000000000000000000
--- a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaUnitTestAdapter.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-using Microsoft.VisualStudio.TestPlatform.ObjectModel;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
-using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
-using System;
-using System.Collections.Generic;
-
-namespace NahidaProject_UnitTestAdapter {
- [FileExtension(".exe")]
- [DefaultExecutorUri(NahidaUnitTestConstant.ExecutorUri)]
- public class NahidaUnitTestAdapter : ITestDiscoverer {
- public void DiscoverTests(IEnumerable sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink) {
- logger.SendMessage(TestMessageLevel.Informational, "Starting C++ test discovery...");
-
- foreach (var source in sources) {
- try {
- DiscoverTestsFromExecutable(source, logger, discoverySink);
- }
- catch (Exception exception) {
- logger.SendMessage(TestMessageLevel.Error, $"Error discovering tests from {source}: {exception.Message}");
- }
- }
- }
-
- private void DiscoverTestsFromExecutable(string executablePath, IMessageLogger logger, ITestCaseDiscoverySink discoverySink) {
- // 运行测试可执行文件获取测试列表
- var testList = GetTestListFromExecutable(executablePath, logger);
-
- foreach (var testInfo in testList){
- var testCase = new TestCase(testInfo.FullyQualifiedName, new Uri(NahidaUnitTestConstant.ExecutorUri),executablePath) {
- DisplayName = testInfo.DisplayName,
- CodeFilePath = testInfo.SourceFile,
- LineNumber = testInfo.LineNumber
- };
-
- // 添加自定义属性
- testCase.Traits.Add(new Trait("Category", "CppTest"));
- testCase.Traits.Add(new Trait("Suite", testInfo.TestSuite));
-
- discoverySink.SendTestCase(testCase);
- }
- }
-
- private List GetTestListFromExecutable(string executablePath, IMessageLogger logger){
- var testList = new List();
-
- try{
- // 这里需要根据具体的 C++ 测试框架实现
- // 示例:假设使用 Google Test 并支持 --gtest_list_tests 参数
- var processInfo = new System.Diagnostics.ProcessStartInfo {
- FileName = executablePath,
- Arguments = "",
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true
- };
-
- using (var process = System.Diagnostics.Process.Start(processInfo)) {
- string output = process.StandardOutput.ReadToEnd();
- process.WaitForExit();
-
- testList = ParseGTestListOutput(output, executablePath);
- }
- }
- catch (Exception ex)
- {
- logger.SendMessage(TestMessageLevel.Warning,
- $"Could not get test list from {executablePath}: {ex.Message}");
- }
-
- return testList;
- }
-
- private List ParseGTestListOutput(string output, string executablePath) {
- var testList = new List();
- var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
-
- string currentSuite = string.Empty;
-
- foreach (var line in lines)
- {
- if (line.StartsWith(" ")) // 测试用例
- {
- var testName = line.Trim();
- var testInfo = new NahidaUnitTestData
- {
- FullyQualifiedName = $"{currentSuite}.{testName}",
- DisplayName = testName,
- TestSuite = currentSuite,
- SourceFile = executablePath,
- LineNumber = 0 // 需要通过其他方式获取行号
- };
- testList.Add(testInfo);
- }
- else if (line.EndsWith(".")) // 测试套件
- {
- currentSuite = line.TrimEnd('.');
- }
- }
-
- return testList;
- }
- }
-}
diff --git a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaUnitTestConstant.cs b/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaUnitTestConstant.cs
deleted file mode 100644
index 2c222f13d5873eea70b80393d0ff3602f5b77437..0000000000000000000000000000000000000000
--- a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaUnitTestConstant.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace NahidaProject_UnitTestAdapter
-{
- public static class NahidaUnitTestConstant
- {
- public const string ExecutorUri = "executor://NahidaUnitTestExecutor";
- public const string FriendlyName = "NahidaProject C++ Test Adapter";
- }
-}
diff --git a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaUnitTestData.cs b/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaUnitTestData.cs
deleted file mode 100644
index 6e7b01c0e273677a31a84f5d02b39150755542c2..0000000000000000000000000000000000000000
--- a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/NahidaUnitTestData.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace NahidaProject_UnitTestAdapter {
- public class NahidaUnitTestData {
- public string FullyQualifiedName {
- get;
- set;
- }
-
- public string DisplayName {
- get;
- set;
-
- }
- public string TestSuite {
- get;
- set;
- }
-
- public string SourceFile {
- get;
- set;
- }
-
- public int LineNumber {
- get;
- set;
- }
- }
-}
diff --git a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/source.extension.vsixmanifest b/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/source.extension.vsixmanifest
deleted file mode 100644
index 3b763de00ea5af4c69175d968ff8354bb62cc9a2..0000000000000000000000000000000000000000
--- a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/source.extension.vsixmanifest
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- NahidaProject_UnitTestAdapter
- Test adapter for NahidaProject unit tests.Test adapter for C++ unit tests
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/NahidaProject4CSharp/.gitignore b/NahidaProject4CSharp/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0582db01a9f04027888cefe1c7d17bb3f785b1ae
--- /dev/null
+++ b/NahidaProject4CSharp/.gitignore
@@ -0,0 +1,4 @@
+### Microsoft Visual Studio ###
+.vs
+bin
+obj
\ No newline at end of file
diff --git a/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/App.config b/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/App.config
new file mode 100644
index 0000000000000000000000000000000000000000..193aecc675e7d4600fde2d37cf350bce7a056948
--- /dev/null
+++ b/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest.csproj b/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..e07cbf9f7a7f91cd3051fb55f52aed2b30c67986
--- /dev/null
+++ b/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest.csproj
@@ -0,0 +1,60 @@
+
+
+
+
+ latest
+ Debug
+ AnyCPU
+ {2DA61D72-1C90-4E5A-9FB3-69E1B5200F33}
+ Exe
+ NahidaProject4CSharp.UnitTest.FunctionalTest
+ NahidaProject4CSharp.UnitTest.FunctionalTest
+ v4.8
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {ac8f58ae-96fa-49a3-8b24-0674ddfef2f7}
+ NahidaProject4CSharp.UnitTest
+
+
+
+
\ No newline at end of file
diff --git a/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/Program.cs b/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/Program.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3ace5a22f8e4e49a716c96037af1259208d87766
--- /dev/null
+++ b/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/Program.cs
@@ -0,0 +1,150 @@
+using NahidaProject4CSharp.UnitTest.NahidaBenchmarkTest;
+using NahidaProject4CSharp.UnitTest.NahidaMockTest;
+using NahidaProject4CSharp.UnitTest.NahidaUnitTest;
+using System;
+using System.Reflection;
+using System.Text;
+
+namespace NahidaProject4CSharp.UnitTest.FunctionalTest {
+ public class UnitTestTests{
+
+ [Test] public void TestPoint1() {
+ Assert.Equals(1 + 1, 2);
+ }
+
+ [Test] public void TestPoint2() {
+ Assert.Equals(2 + 2, 22);
+ }
+ }
+
+ [BenchmarkClass(Name = "TestClass1", Description = "Testing various string operations performance")]
+ public class TestClass1 {
+ [Benchmark(Iterations = 1000, Warmup = 10, Description = "String concatenation using + operator")]
+ public void TestPoint1(){
+ string result = "";
+ for (int i = 0; i < 100; i++)
+ {
+ result += "test";
+ }
+ }
+
+ [Benchmark(Iterations = 1000, Warmup = 10, Description = "String concatenation using StringBuilder")]
+ public void TestPoint2(){
+ var sb = new StringBuilder();
+ for (int i = 0; i < 100; i++){
+ sb.Append("test");
+ }
+ sb.ToString();
+ }
+
+ [Benchmark(Iterations = 1000, Warmup = 10, Description = "String.Join operation")]
+ public void TestPoint3(){
+ var array = new string[100];
+ for (int i = 0; i < 100; i++){
+ array[i] = "test";
+ }
+ string.Join("", array);
+ }
+
+ [Benchmark(Iterations = 100, Warmup = 5, Description = "Parameterized string format test")]
+ public void TestPoint4([BenchmarkParam("Hello", "World", "Test")] string input){
+ string.Format("Formatted: {0}", input);
+ }
+ }
+
+ public interface IUserService
+ {
+ string GetUserName(int userId);
+ int GetUserCount();
+ void SaveUser(string name);
+ bool DeleteUser(int userId);
+ }
+
+ public class UserServiceConsumer
+ {
+ private readonly IUserService _userService;
+
+ public UserServiceConsumer(IUserService userService)
+ {
+ _userService = userService;
+ }
+
+ public string GetWelcomeMessage(int userId)
+ {
+ var userName = _userService.GetUserName(userId);
+ return $"Welcome, {userName}!";
+ }
+
+ public void CreateUser(string name)
+ {
+ _userService.SaveUser(name);
+ }
+
+ public bool RemoveUser(int userId)
+ {
+ return _userService.DeleteUser(userId);
+ }
+ }
+
+ internal class Program {
+ static void Main() {
+ var assemblyRunner = new TestRunner();
+ assemblyRunner.RunTests(Assembly.GetExecutingAssembly());
+ assemblyRunner.PrintResults();
+
+ var runner = new BenchmarkRunner();
+
+ runner.OnTestCompleted += (result) =>{
+ if (result.Success){
+ Console.WriteLine($"Completed: {result.TestName} - {result.AverageMs:F3}ms avg");
+ }
+ else{
+ Console.WriteLine($"Failed: {result.TestName} - {result.Exception?.Message}");
+ }
+ };
+
+ runner.OnSuiteCompleted += (suiteResult) =>{
+ Console.WriteLine($"\nSuite '{suiteResult.SuiteName}' completed in {suiteResult.TotalDuration.TotalMilliseconds:F2}ms");
+ };
+
+ var stringResults = runner.Run();
+ BenchmarkReporter.GenerateDetailedConsoleReport(stringResults);
+
+ var mockUserService = MockFactory.CreateMock();
+ mockUserService.Setup(x => x.GetUserName(1), "John Doe");
+ mockUserService.Setup(x => x.GetUserCount(), 5);
+ mockUserService.Setup(x => x.DeleteUser(1), true);
+
+ var consumer = new UserServiceConsumer(mockUserService.Object);
+
+ var welcomeMessage = consumer.GetWelcomeMessage(1);
+ Console.WriteLine($"Welcome Message: {welcomeMessage}");
+
+ consumer.CreateUser("Jane Doe");
+
+ var deleteResult = consumer.RemoveUser(1);
+ Console.WriteLine($"Delete Result: {deleteResult}");
+
+ try
+ {
+ mockUserService.Verify(x => x.GetUserName(1), Times.Once());
+ mockUserService.Verify(x => x.SaveUser("Jane Doe"), Times.Once());
+ mockUserService.Verify(x => x.DeleteUser(1), Times.Once());
+ Console.WriteLine("All verifications passed!");
+ }
+ catch (MockException ex)
+ {
+ Console.WriteLine($"Verification failed: {ex.Message}");
+ }
+
+ try
+ {
+ mockUserService.Verify(x => x.GetUserCount(), Times.Once());
+ }
+ catch (MockException ex)
+ {
+ Console.WriteLine($"Expected verification failure: {ex.Message}");
+ }
+ }
+ }
+}
diff --git a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/Properties/AssemblyInfo.cs b/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/Properties/AssemblyInfo.cs
similarity index 31%
rename from NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/Properties/AssemblyInfo.cs
rename to NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/Properties/AssemblyInfo.cs
index 349aea24046826a6b7576c5c51948c0c60d33b96..007413798dd3aa0f8f3ba636c2ca9bdd32357a20 100644
--- a/NahidaProject-UnitTestAdapter/NahidaProject-UnitTestAdapter/Properties/AssemblyInfo.cs
+++ b/NahidaProject4CSharp/FunctionalTest/NahidaProject4CSharp.UnitTest.FunctionalTest/Properties/AssemblyInfo.cs
@@ -2,32 +2,32 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("NahidaProject_UnitTestAdapter")]
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("NahidaProject4CSharp.UnitTest.FunctionalTest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("NahidaProject_UnitTestAdapter")]
-[assembly: AssemblyCopyright("")]
+[assembly: AssemblyProduct("NahidaProject4CSharp.UnitTest.FunctionalTest")]
+[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
-// Version information for an assembly consists of the following four values:
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("2da61d72-1c90-4e5a-9fb3-69e1b5200f33")]
+
+// 程序集的版本信息由下列四个值组成:
//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
+// 主版本
+// 次版本
+// 生成号
+// 修订号
//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/NahidaProject4CSharp/NahidaProject4CSharp.UnitTest/NahidaBenchmarkTest.cs b/NahidaProject4CSharp/NahidaProject4CSharp.UnitTest/NahidaBenchmarkTest.cs
new file mode 100644
index 0000000000000000000000000000000000000000..23ab6c28b4c0d84dc76f0aab63bbf43a90cea645
--- /dev/null
+++ b/NahidaProject4CSharp/NahidaProject4CSharp.UnitTest/NahidaBenchmarkTest.cs
@@ -0,0 +1,370 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace NahidaProject4CSharp.UnitTest.NahidaBenchmarkTest
+{
+
+ [AttributeUsage(AttributeTargets.Method)]
+ public class BenchmarkAttribute : Attribute
+ {
+ public int Iterations { get; set; } = 1;
+ public int Warmup { get; set; } = 0;
+ public string Description { get; set; } = "";
+ }
+
+ [AttributeUsage(AttributeTargets.Class)]
+ public class BenchmarkClassAttribute : Attribute
+ {
+ public string Name { get; set; } = "";
+ public string Description { get; set; } = "";
+ }
+
+ [AttributeUsage(AttributeTargets.Parameter)]
+ public class BenchmarkParamAttribute : Attribute
+ {
+ public object[] Values { get; set; }
+
+ public BenchmarkParamAttribute(params object[] values)
+ {
+ Values = values;
+ }
+ }
+ public class BenchmarkResult
+ {
+ public string TestName { get; set; }
+ public string Description { get; set; }
+ public TimeSpan Duration { get; set; }
+ public long Ticks { get; set; }
+ public double Milliseconds { get; set; }
+ public Dictionary Parameters { get; set; } = new Dictionary();
+ public Exception Exception { get; set; }
+ public bool Success { get; set; }
+ public long MemoryBefore { get; set; }
+ public long MemoryAfter { get; set; }
+ public long MemoryUsed { get; set; }
+ public int Iterations { get; set; }
+ public double AverageMs { get; set; }
+
+ public override string ToString()
+ {
+ if (!Success)
+ {
+ return $"{TestName}: FAILED - {Exception?.Message}";
+ }
+
+ return $"{TestName}: {AverageMs:F3}ms avg ({Iterations} iterations)";
+ }
+ }
+ public class BenchmarkSuiteResult
+ {
+ public string SuiteName { get; set; }
+ public string Description { get; set; }
+ public List Results { get; set; } = new List();
+ public DateTime StartTime { get; set; }
+ public DateTime EndTime { get; set; }
+ public TimeSpan TotalDuration => EndTime - StartTime;
+
+ public void AddResult(BenchmarkResult result)
+ {
+ Results.Add(result);
+ }
+
+ public IEnumerable SuccessfulResults => Results.Where(r => r.Success);
+ public IEnumerable FailedResults => Results.Where(r => !r.Success);
+ }
+
+ public class BenchmarkRunner
+ {
+ private readonly List _suiteResults = new List();
+
+ public event Action OnTestCompleted;
+ public event Action OnSuiteCompleted;
+
+ public BenchmarkSuiteResult Run() where T : new()
+ {
+ return Run(typeof(T));
+ }
+
+ public BenchmarkSuiteResult Run(Type benchmarkType)
+ {
+ var suiteResult = new BenchmarkSuiteResult
+ {
+ StartTime = DateTime.Now
+ };
+
+ var classAttr = benchmarkType.GetCustomAttribute();
+ suiteResult.SuiteName = !string.IsNullOrEmpty(classAttr?.Name) ? classAttr.Name : benchmarkType.Name;
+ suiteResult.Description = classAttr?.Description ?? "";
+
+ Console.WriteLine($"Starting benchmark suite: {suiteResult.SuiteName}");
+ if (!string.IsNullOrEmpty(suiteResult.Description))
+ {
+ Console.WriteLine($"Description: {suiteResult.Description}");
+ }
+ Console.WriteLine(new string('=', 60));
+
+ var instance = Activator.CreateInstance(benchmarkType);
+
+ var methods = benchmarkType.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.GetCustomAttribute() != null);
+
+ foreach (var method in methods)
+ {
+ var attr = method.GetCustomAttribute();
+ var testName = method.Name;
+ var description = attr.Description;
+
+ var parameters = method.GetParameters();
+ if (parameters.Length == 0)
+ {
+ var result = RunTestMethod(instance, method, attr, testName, description);
+ suiteResult.AddResult(result);
+ OnTestCompleted?.Invoke(result);
+ }
+ else
+ {
+ RunParameterizedTest(instance, method, attr, suiteResult);
+ }
+ }
+
+ suiteResult.EndTime = DateTime.Now;
+ _suiteResults.Add(suiteResult);
+ OnSuiteCompleted?.Invoke(suiteResult);
+
+ return suiteResult;
+ }
+
+ private void RunParameterizedTest(object instance, MethodInfo method, BenchmarkAttribute attr, BenchmarkSuiteResult suiteResult)
+ {
+ var parameters = method.GetParameters();
+ var parameterValues = new List