{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运行 xUnit 单元测试\n",
    "====================="
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Polgylot Notebooks 并没有直接支持单元测试框架。不能像VS里那样方便的进行单元测试。简单远行的话,可以使用下面的方案!"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1、引入必要的NuGet包到.NET Interactive环境中"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div><div><strong>Restore sources</strong><ul><li><span>https://api.nuget.org/v3/index.json</span></li></ul></div><div></div><div><strong>Installed Packages</strong><ul><li><span>xunit, 2.9.3</span></li><li><span>xunit.assert, 2.9.3</span></li><li><span>xunit.runner.visualstudio, 3.1.0</span></li></ul></div></div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "// 默认包源\n",
    "#i \"nuget:https://api.nuget.org/v3/index.json\"\n",
    "\n",
    "//Nuget 包引用\n",
    "#r \"nuget:xunit\"\n",
    "#r \"nuget: xunit.assert\"\n",
    "#r \"nuget:xunit.runner.visualstudio\"\n",
    "#r \"nuget:xunit.runner.console\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2、定义测试类和测试方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "using Xunit;\n",
    "\n",
    "public class CalculatorTests\n",
    "{\n",
    "    [Fact]\n",
    "    public void Add_ReturnsCorrectSum()\n",
    "    {\n",
    "        var calculator = new Calculator();\n",
    "        var result = calculator.Add(2, 2);\n",
    "        Assert.Equal(4, result);\n",
    "    }\n",
    "\n",
    "    [Fact]\n",
    "    public void Subtract_ReturnsCorrectDifference()\n",
    "    {\n",
    "        var calculator = new Calculator();\n",
    "        var result = calculator.Subtract(5, 3);\n",
    "        Assert.Equal(2, result);\n",
    "    }\n",
    "}\n",
    "\n",
    "public class Calculator\n",
    "{\n",
    "    public int Add(int x, int y) => x + y;\n",
    "    public int Subtract(int x, int y) => x - y;\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3、执行测试并获取结果。在.NET Interactive中,直接运行xUnit测试并不像在Visual Studio或通过命令行那样直接。你需要手动实例化测试类并调用测试方法,或者使用反射来自动发现和执行测试方法。以下是一个简化的例子,展示如何手动执行测试方法并输出结果。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 手动调用测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tests executed successfully.\r\n"
     ]
    }
   ],
   "source": [
    "// 手动执行测试方法\n",
    "var calculatorTests = new CalculatorTests();\n",
    "\n",
    "// 执行Add_ReturnsCorrectSum测试\n",
    "calculatorTests.Add_ReturnsCorrectSum();\n",
    "\n",
    "// 执行Subtract_ReturnsCorrectDifference测试\n",
    "calculatorTests.Subtract_ReturnsCorrectDifference();\n",
    "\n",
    "Console.WriteLine(\"Tests executed successfully.\");\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 使用反射的例子"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div><div><strong>Restore sources</strong><ul><li><span>https://api.nuget.org/v3/index.json</span></li></ul></div><div></div><div><strong>Installed Packages</strong><ul><li><span>xunit, 2.9.3</span></li><li><span>xunit.assert, 2.9.3</span></li></ul></div></div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#r \"nuget: xunit\"\n",
    "#r \"nuget: xunit.assert\"\n",
    "\n",
    "using Xunit;\n",
    "using System.Reflection;\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ Add_TwoNumbers_ReturnsSum 通过\r\n"
     ]
    }
   ],
   "source": [
    "//被测试类\n",
    "public class Calculator\n",
    "{\n",
    "    public int Add(int a, int b) => a + b;\n",
    "}\n",
    "\n",
    "//测试类\n",
    "public class CalculatorTests\n",
    "{\n",
    "    [Fact]\n",
    "    public void Add_TwoNumbers_ReturnsSum()\n",
    "    {\n",
    "        var calculator = new Calculator();\n",
    "        int result = calculator.Add(1, 2);\n",
    "        Assert.Equal(3, result); //:ml-citation{ref=\"3,4\" data=\"citationList\"}\n",
    "    }\n",
    "}\n",
    "\n",
    "//使用反射,调用被测试类\n",
    "var testInstance = new CalculatorTests();\n",
    "var testMethods = testInstance.GetType()\n",
    "    .GetMethods()\n",
    "    .Where(m => m.GetCustomAttributes(typeof(FactAttribute), false).Length > 0);\n",
    "\n",
    "foreach (var method in testMethods)\n",
    "{\n",
    "    try\n",
    "    {\n",
    "        method.Invoke(testInstance, null);\n",
    "        Console.WriteLine($\"✅ {method.Name} 通过\");\n",
    "    }\n",
    "    catch (Exception ex)\n",
    "    {\n",
    "        Console.WriteLine($\"❌ {method.Name} 失败: {ex.InnerException?.Message}\");\n",
    "    }\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "polyglot-notebook"
  },
  "orig_nbformat": 4,
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "name": "csharp"
     },
     {
      "aliases": [],
      "name": "razor"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}