Przeglądaj źródła

init:初始化xunitTest

WindyRonnie 4 lat temu
commit
f1fc71aacd

+ 63 - 0
.gitattributes

@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs     diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following 
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln       merge=binary
+#*.csproj    merge=binary
+#*.vbproj    merge=binary
+#*.vcxproj   merge=binary
+#*.vcproj    merge=binary
+#*.dbproj    merge=binary
+#*.fsproj    merge=binary
+#*.lsproj    merge=binary
+#*.wixproj   merge=binary
+#*.modelproj merge=binary
+#*.sqlproj   merge=binary
+#*.wwaproj   merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg   binary
+#*.png   binary
+#*.gif   binary
+
+###############################################################################
+# diff behavior for common document formats
+# 
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the 
+# entries below.
+###############################################################################
+#*.doc   diff=astextplain
+#*.DOC   diff=astextplain
+#*.docx  diff=astextplain
+#*.DOCX  diff=astextplain
+#*.dot   diff=astextplain
+#*.DOT   diff=astextplain
+#*.pdf   diff=astextplain
+#*.PDF   diff=astextplain
+#*.rtf   diff=astextplain
+#*.RTF   diff=astextplain

+ 577 - 0
.gitignore

@@ -0,0 +1,577 @@
+## Ignore Visual Studio temporary files, build results, and
+
+## files generated by popular Visual Studio add-ons.
+
+##
+
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+
+*.rsuser
+
+*.suo
+
+*.user
+
+*.userosscache
+
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+
+*.userprefs
+
+# Mono auto generated files
+
+mono_crash.*
+
+# Build results
+
+[Dd]ebug/
+
+[Dd]ebugPublic/
+
+[Rr]elease/
+
+[Rr]eleases/
+
+x64/
+
+x86/
+
+[Ww][Ii][Nn]32/
+
+[Aa][Rr][Mm]/
+
+[Aa][Rr][Mm]64/
+
+bld/
+
+[Bb]in/
+
+[Oo]bj/
+
+[Ll]og/
+
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+
+.vs/
+
+# Uncomment if you have tasks that create the project's static files in wwwroot
+
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+
+Generated\ Files/
+
+# MSTest test Results
+
+[Tt]est[Rr]esult*/
+
+[Bb]uild[Ll]og.*
+
+# NUnit
+
+*.VisualState.xml
+
+TestResult.xml
+
+nunit-*.xml
+
+# Build Results of an ATL Project
+
+[Dd]ebugPS/
+
+[Rr]eleasePS/
+
+dlldata.c
+
+# Benchmark Results
+
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+
+project.lock.json
+
+project.fragment.lock.json
+
+artifacts/
+
+# ASP.NET Scaffolding
+
+ScaffoldingReadMe.txt
+
+# StyleCop
+
+StyleCopReport.xml
+
+# Files built by Visual Studio
+
+*_i.c
+
+*_p.c
+
+*_h.h
+
+*.ilk
+
+*.meta
+
+*.obj
+
+*.iobj
+
+*.pch
+
+*.pdb
+
+*.ipdb
+
+*.pgc
+
+*.pgd
+
+*.rsp
+
+*.sbr
+
+*.tlb
+
+*.tli
+
+*.tlh
+
+*.tmp
+
+*.tmp_proj
+
+*_wpftmp.csproj
+
+*.log
+
+*.vspscc
+
+*.vssscc
+
+.builds
+
+*.pidb
+
+*.svclog
+
+*.scc
+
+# Chutzpah Test files
+
+_Chutzpah*
+
+# Visual C++ cache files
+
+ipch/
+
+*.aps
+
+*.ncb
+
+*.opendb
+
+*.opensdf
+
+*.sdf
+
+*.cachefile
+
+*.VC.db
+
+*.VC.VC.opendb
+
+# Visual Studio profiler
+
+*.psess
+
+*.vsp
+
+*.vspx
+
+*.sap
+
+# Visual Studio Trace Files
+
+*.e2e
+
+# TFS 2012 Local Workspace
+
+$tf/
+
+# Guidance Automation Toolkit
+
+*.gpState
+
+# ReSharper is a .NET coding add-in
+
+_ReSharper*/
+
+*.[Rr]e[Ss]harper
+
+*.DotSettings.user
+
+# TeamCity is a build add-in
+
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+
+.axoCover/*
+
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+
+*.coverage
+
+*.coveragexml
+
+# NCrunch
+
+_NCrunch_*
+
+.*crunch*.local.xml
+
+nCrunchTemp_*
+
+# MightyMoose
+
+*.mm.*
+
+AutoTest.Net/
+
+# Web workbench (sass)
+
+.sass-cache/
+
+# Installshield output folder
+
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+
+DocProject/buildhelp/
+
+DocProject/Help/*.HxT
+
+DocProject/Help/*.HxC
+
+DocProject/Help/*.hhc
+
+DocProject/Help/*.hhk
+
+DocProject/Help/*.hhp
+
+DocProject/Help/Html2
+
+DocProject/Help/html
+
+# Click-Once directory
+
+publish/
+
+# Publish Web Output
+
+*.[Pp]ublish.xml
+
+*.azurePubxml
+
+# Note: Comment the next line if you want to checkin your web deploy settings,
+
+# but database connection strings (with potential passwords) will be unencrypted
+
+*.pubxml
+
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+
+# checkin your Azure Web App publish settings, but sensitive information contained
+
+# in these scripts will be unencrypted
+
+PublishScripts/
+
+# NuGet Packages
+
+*.nupkg
+
+# NuGet Symbol Packages
+
+*.snupkg
+
+# The packages folder can be ignored because of Package Restore
+
+**/[Pp]ackages/*
+
+# except build/, which is used as an MSBuild target.
+
+!**/[Pp]ackages/build/
+
+# Uncomment if necessary however generally it will be regenerated when needed
+
+#!**/[Pp]ackages/repositories.config
+
+# NuGet v3's project.json files produces more ignorable files
+
+*.nuget.props
+
+*.nuget.targets
+
+# Microsoft Azure Build Output
+
+csx/
+
+*.build.csdef
+
+# Microsoft Azure Emulator
+
+ecf/
+
+rcf/
+
+# Windows Store app package directories and files
+
+AppPackages/
+
+BundleArtifacts/
+
+Package.StoreAssociation.xml
+
+_pkginfo.txt
+
+*.appx
+
+*.appxbundle
+
+*.appxupload
+
+# Visual Studio cache files
+
+# files ending in .cache can be ignored
+
+*.[Cc]ache
+
+# but keep track of directories ending in .cache
+
+!?*.[Cc]ache/
+
+# Others
+
+ClientBin/
+
+~$*
+
+*~
+
+*.dbmdl
+
+*.dbproj.schemaview
+
+*.jfm
+
+*.pfx
+
+*.publishsettings
+
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+
+#bower_components/
+
+# RIA/Silverlight projects
+
+Generated_Code/
+
+# Backup & report files from converting an old project file
+
+# to a newer Visual Studio version. Backup files are not needed,
+
+# because we have git ;-)
+
+_UpgradeReport_Files/
+
+Backup*/
+
+UpgradeLog*.XML
+
+UpgradeLog*.htm
+
+ServiceFabricBackup/
+
+*.rptproj.bak
+
+# SQL Server files
+
+*.mdf
+
+*.ldf
+
+*.ndf
+
+# Business Intelligence projects
+
+*.rdl.data
+
+*.bim.layout
+
+*.bim_*.settings
+
+*.rptproj.rsuser
+
+*- [Bb]ackup.rdl
+
+*- [Bb]ackup ([0-9]).rdl
+
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+
+.ntvs_analysis.dat
+
+node_modules/
+
+# Visual Studio 6 build log
+
+*.plg
+
+# Visual Studio 6 workspace options file
+
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+
+*.vbw
+
+# Visual Studio LightSwitch build output
+
+**/*.HTMLClient/GeneratedArtifacts
+
+**/*.DesktopClient/GeneratedArtifacts
+
+**/*.DesktopClient/ModelManifest.xml
+
+**/*.Server/GeneratedArtifacts
+
+**/*.Server/ModelManifest.xml
+
+_Pvt_Extensions
+
+# Paket dependency manager
+
+.paket/paket.exe
+
+paket-files/
+
+# FAKE - F# Make
+
+.fake/
+
+# CodeRush personal settings
+
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+
+__pycache__/
+
+*.pyc
+
+# Cake - Uncomment if you are using it
+
+# tools/**
+
+# !tools/packages.config
+
+# Tabs Studio
+
+*.tss
+
+# Telerik's JustMock configuration file
+
+*.jmconfig
+
+# BizTalk build output
+
+*.btp.cs
+
+*.btm.cs
+
+*.odx.cs
+
+*.xsd.cs
+
+# OpenCover UI analysis results
+
+OpenCover/
+
+# Azure Stream Analytics local run output
+
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+
+.mfractor/
+
+# Local History for Visual Studio
+
+.localhistory/
+
+# BeatPulse healthcheck temp database
+
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+
+.ionide/
+
+# Fody - auto-generated XML schema
+
+FodyWeavers.xsd

+ 21 - 0
MyUnitTest/MyUnitDemo/Calculator.cs

@@ -0,0 +1,21 @@
+using System;
+
+namespace MyUnitDemo
+{
+    /// <summary>
+    /// 计算器类
+    /// </summary>
+    public class Calculator
+    {
+        /// <summary>
+        /// 加法计算
+        /// </summary>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        /// <returns></returns>
+        public int Add(int x, int y)
+        {
+            return x + y;
+        }
+    }
+}

+ 17 - 0
MyUnitTest/MyUnitDemo/LongTimeTask.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MyUnitDemo
+{
+    public class LongTimeTask
+    {
+        public LongTimeTask() 
+        {
+            Thread.Sleep(2000);
+        }
+    }
+}

+ 7 - 0
MyUnitTest/MyUnitDemo/MyUnitDemo.csproj

@@ -0,0 +1,7 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+  </PropertyGroup>
+
+</Project>

+ 59 - 0
MyUnitTest/MyUnitDemo/Patient.cs

@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyUnitDemo
+{
+    public class Patient : Person, INotifyPropertyChanged
+    {
+        public Patient()
+        {
+            IsNew = true;
+            BloodSugar = 4.90003f;
+            History = new List<string>();
+        }
+
+        public string FullName => $"{FirstName} {LastName}";
+        public int HeartBeatRate { get; set; }
+        public bool IsNew { get; set; }
+        public float BloodSugar { get; set; }
+        public List<string> History { get; set; }
+
+        public event EventHandler<EventArgs> PatientSlept;
+        public event PropertyChangedEventHandler PropertyChanged;
+        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+        }
+        public void OnPatientSleep()
+        {
+            PatientSlept?.Invoke(this, EventArgs.Empty);
+        }
+        public void Sleep()
+        {
+            OnPatientSleep();
+        }
+
+        public void NotAllowed()
+        {
+            throw new InvalidOperationException("No able to Create");
+        }
+
+        public void IncreaseHeartBeatRate()
+        {
+            HeartBeatRate = CalculateHeartBeatRate() + 2;
+            OnPropertyChanged(nameof(HeartBeatRate));
+        }
+
+        private int CalculateHeartBeatRate()
+        {
+            var random = new Random();
+            return random.Next(1, 100);
+        }
+
+    }
+}

+ 14 - 0
MyUnitTest/MyUnitDemo/Person.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyUnitDemo
+{
+    public class Person
+    {
+        public string FirstName { get; set; }
+        public string LastName { get; set; }
+    }
+}

+ 31 - 0
MyUnitTest/MyUnitTest.sln

@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.32002.261
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyxUnitTest", "MyxUnitTest\MyxUnitTest.csproj", "{6FEE3B62-087A-4B14-B272-A1EF31EB6A4D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyUnitDemo", "MyUnitDemo\MyUnitDemo.csproj", "{3B68E091-F8D1-4397-8218-490B609CDAC1}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{6FEE3B62-087A-4B14-B272-A1EF31EB6A4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6FEE3B62-087A-4B14-B272-A1EF31EB6A4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6FEE3B62-087A-4B14-B272-A1EF31EB6A4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6FEE3B62-087A-4B14-B272-A1EF31EB6A4D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3B68E091-F8D1-4397-8218-490B609CDAC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B68E091-F8D1-4397-8218-490B609CDAC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B68E091-F8D1-4397-8218-490B609CDAC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3B68E091-F8D1-4397-8218-490B609CDAC1}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {0F7FD98A-E857-4B4B-BA80-FA70CCB4D3BE}
+	EndGlobalSection
+EndGlobal

+ 51 - 0
MyUnitTest/MyxUnitTest/CalculatorTest.cs

@@ -0,0 +1,51 @@
+using MyUnitDemo;
+using MyxUnitTest.Data;
+using System;
+using Xunit;
+
+namespace MyxUnitTest
+{
+    [Trait("Category", "Calc")] // 创建特征分组
+    [Collection("Long Time Task Collection")] // 根据字符串共享上下文
+    public class CalculatorTest
+    {
+        [Fact]
+        public void ShouldAdd()
+        {
+            // Arrange 先决条件设定
+            var sut = new Calculator(); //System Under Test
+            // Act 执行生产代码并返回结果
+            var result = sut.Add(1, 2);
+            // Assert 健查结果
+            Assert.Equal(3, result);
+        }
+
+        [Fact]
+        public void ShouldStayTheSameWhenAddZero()
+        {
+            // Arrange 先决条件设定
+            var sut = new Calculator(); //System Under Test
+            // Act 执行生产代码并返回结果
+            var result = sut.Add(2, 0);
+            // Assert 健查结果
+            Assert.Equal(2, result);
+
+        }
+
+        [Theory]
+        //[InlineData(1, 2, 3)]
+        //[InlineData(2, 3, 5)]
+        //[InlineData(1, 3, 4)]
+        //[InlineData(0, 2, 2)]
+        //[MemberData(nameof(CalculatorTestData.TestData), MemberType = typeof(CalculatorTestData))]
+        //[MemberData(nameof(CalculatorCsvData.TestData), MemberType = typeof(CalculatorCsvData))] // 读取CSV文件
+        [CalculatorData] // 自定义特性
+        public void ShouldAddEquals(int x, int y, int expected)
+        {
+            var sut = new Calculator();
+            var result = sut.Add(x, y);
+            Assert.Equal(expected, result);
+        }
+
+    }
+}

+ 31 - 0
MyUnitTest/MyxUnitTest/Data/CalculatorCsvData.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyxUnitTest.Data
+{
+    /// <summary>
+    /// 读取CSV文件
+    /// </summary>
+    public class CalculatorCsvData
+    {
+        public static IEnumerable<object[]> TestData
+        {
+            get
+            {
+                string[] csvLines = File.ReadAllLines("Data\\TestData.csv");
+                var testCases = new List<object[]>();
+                foreach (var csvLine in csvLines)
+                {
+                    IEnumerable<int> values = csvLine.Split(',').Select(int.Parse);
+                    object[] testCase = values.Cast<object>().ToArray();
+                    testCases.Add(testCase);
+                }
+                return testCases;
+            }
+        }
+    }
+}

+ 24 - 0
MyUnitTest/MyxUnitTest/Data/CalculatorDataAttribute.cs

@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit.Sdk;
+
+namespace MyxUnitTest.Data
+{
+    /// <summary>
+    /// 自定义特性
+    /// </summary>
+    public class CalculatorDataAttribute : DataAttribute
+    {
+        public override IEnumerable<object[]> GetData(MethodInfo testMethod)
+        {
+            yield return new object[] { 0, 100, 100 };
+            yield return new object[] { 1, 99, 100 };
+            yield return new object[] { 50, 50, 100 };
+            yield return new object[] { 101, 1, 102 };
+        }
+    }
+}

+ 21 - 0
MyUnitTest/MyxUnitTest/Data/CalculatorTestData.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyxUnitTest.Data
+{
+    public static class CalculatorTestData
+    {
+        private static readonly List<object[]> Data = new List<object[]>
+        {
+            new object[] {1, 2, 3},
+             new object[] {1, 3, 4},
+              new object[] {2, 4, 6},
+               new object[] {0, 1, 1}
+        };
+
+        public static IEnumerable<object[]> TestData => Data;
+    }
+}

+ 5 - 0
MyUnitTest/MyxUnitTest/Data/TestData.csv

@@ -0,0 +1,5 @@
+1,2,3
+2,4,6
+3,5,8
+0,2,2
+1,0,1

+ 22 - 0
MyUnitTest/MyxUnitTest/LongTimeTaskFixture.cs

@@ -0,0 +1,22 @@
+using MyUnitDemo;
+using System;
+
+namespace MyxUnitTest
+{
+    /// <summary>
+    /// 共享上下文类
+    /// </summary>
+    public class LongTimeTaskFixture : IDisposable
+    {
+        // 跑多个测试时只有一个实例
+        public LongTimeTask Task { get; }
+        public LongTimeTaskFixture() 
+        {
+            Task = new LongTimeTask();
+        }
+
+        public void Dispose()
+        {
+        }
+    }
+}

+ 26 - 0
MyUnitTest/MyxUnitTest/MyxUnitTest.csproj

@@ -0,0 +1,26 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+
+    <IsPackable>false</IsPackable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+    <PackageReference Include="xunit" Version="2.4.1" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+      <PrivateAssets>all</PrivateAssets>
+    </PackageReference>
+    <PackageReference Include="coverlet.collector" Version="3.0.2">
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+      <PrivateAssets>all</PrivateAssets>
+    </PackageReference>
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\MyUnitDemo\MyUnitDemo.csproj" />
+  </ItemGroup>
+
+</Project>

+ 169 - 0
MyUnitTest/MyxUnitTest/PatientShould.cs

@@ -0,0 +1,169 @@
+using MyUnitDemo;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace MyxUnitTest
+{
+    [Collection("Long Time Task Collection")] // 根据字符串共享上下文
+    public class PatientShould : IDisposable, IClassFixture<LongTimeTaskFixture>
+    {
+        private readonly ITestOutputHelper _output;
+        private readonly Patient _patient;
+        private readonly LongTimeTask _task;
+        public PatientShould(ITestOutputHelper output, LongTimeTaskFixture fixture)
+        {
+            _output = output;
+            //Arrange 先决条件构造函数设定
+            _patient = new Patient();
+            _task = fixture.Task;
+        }
+
+        [Fact]
+        [Trait("Category", "New")] // 创建特征分组
+        public void BeNewWhenCreated()
+        {
+            _output.WriteLine("第一个测试");
+
+            //Arrange 先决条件设定
+            var patient = new Patient();
+            // Act 执行生产代码并返回结果 
+            var result = _patient.IsNew;
+            _output.WriteLine("第一个测试");
+            // Assert 判断结果是否为True
+            Assert.True(result);
+        }
+
+
+        [Fact]
+        [Trait("Category", "Name")] // 创建特征分组
+        public void HaveCorrectFullName()
+        {
+            var patient = new Patient()
+            {
+                FirstName = "Nick",
+                LastName = "Carter"
+            };
+
+            var fullName = patient.FullName;
+
+            Assert.Equal("Nick Carter", fullName);
+            Assert.StartsWith("Nick", fullName);
+            Assert.EndsWith("Carter", fullName);
+            Assert.Contains("Nick Carter", fullName);
+            Assert.Contains("ck Car", fullName);
+
+            Assert.NotEqual("NICK CARTER", fullName);
+
+            Assert.Matches(@"^[A-Z][a-z]*\s[A-Z][a-z]*", fullName);
+        }
+
+        [Fact]
+        [Trait("Category", "New")] // 创建特征分组
+        [Trait("Category", "Name")] // 创建特征分组
+        public void HaveDefaultBloodSugarWhenCreated()
+        {
+            var p = new Patient();
+
+            var bloodSugar = p.BloodSugar;
+
+            Assert.Equal(4.9f, bloodSugar, 4);
+            Assert.InRange(bloodSugar, 3.9f, 6.1f);
+        }
+
+        [Fact]
+        public void HaveNoNameWhenCreated()
+        {
+            var p = new Patient();
+
+            Assert.Null(p.FirstName);
+            Assert.NotNull(p);
+        }
+
+        [Fact(Skip = "不需要跑这个测试")]
+        public void HaveHadAColdBefore()
+        {
+            var p = new Patient();
+
+            var diseases = new List<string>
+            {
+                "感冒",
+                "发烧",
+                "水痘",
+                "腹泻"
+            };
+            p.History.Add("感冒");
+            p.History.Add("发烧");
+            p.History.Add("水痘");
+            p.History.Add("腹泻");
+
+            Assert.Contains("感冒", p.History);
+            Assert.DoesNotContain("心脏病", p.History);
+
+            // Predicate
+            Assert.Contains(p.History, x => x.StartsWith("水"));
+
+            // 判断每个值的长度都大于等于2
+            Assert.All(p.History, x => Assert.True(x.Length >= 2));
+
+            // 比较集合元素的值相等,而不是引用
+            Assert.Equal(diseases, p.History);
+        }
+
+        [Fact]
+        public void BeAPerson()
+        {
+            var p = new Patient();
+            var p2 = new Patient();
+
+            Assert.IsType<Patient>(p);
+            Assert.IsNotType<Person>(p);
+
+            // 判断父类
+            Assert.IsAssignableFrom<Person>(p);
+
+            Assert.NotSame(p, p2);
+        }
+
+        [Fact]
+        public void ThrowExceptionsWhenErrorOccurred()
+        {
+            var p = new Patient();
+
+            var ex = Assert.Throws<InvalidOperationException>(() => p.NotAllowed());
+
+            Assert.Equal("No able to Create", ex.Message);
+        }
+
+        [Fact]
+        public void RaiseSleptEvent()
+        {
+            var p = new Patient();
+
+            // 判断是否触发事件
+            Assert.Raises<EventArgs>(
+                handler => p.PatientSlept += handler,
+                handler => p.PatientSlept -= handler,
+                () => p.Sleep());
+        }
+
+        [Fact]
+        public void RaisePropertyChangedEvent()
+        {
+            var p = new Patient();
+
+            // 判断属性改变事件是否触发
+            Assert.PropertyChanged(p, nameof(p.HeartBeatRate), () => p.IncreaseHeartBeatRate());
+        }
+
+        public void Dispose()
+        {
+            GC.SuppressFinalize(this);
+            _output.WriteLine("清理了资源");
+        }
+    }
+}

+ 18 - 0
MyUnitTest/MyxUnitTest/TaskCollection.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace MyxUnitTest
+{
+    /// <summary>
+    /// 根据字符串共享上下文
+    /// </summary>
+    [CollectionDefinition("Long Time Task Collection")]
+    public class TaskCollection : ICollectionFixture<LongTimeTaskFixture>
+    {
+
+    }
+}