chore: 完成了文件操作,现在可以对旧文件夹执行更新策略,并添加了单元测试
1. 写逻辑复杂的程序,单元测试必不可少,重构和修改更有信心 2. 单元测试每个测试函数应该是独立的,不相互依赖的,也应该是简单的,否则出现问题不好排查,它叫单元测试 3. 运行测试和debug的时候不要害怕😰😰😰😰😰🙃🙃🙃🙃🙃❤️❤️❤️❤️❤️,它帮你找到了错误,完全没有否定你的意思·····
This commit is contained in:
parent
46315ba760
commit
1809dbebf5
6 changed files with 364 additions and 91 deletions
|
@ -119,11 +119,131 @@ public class Dir(string path, List<AFileOrDir>? children = null, NextOpType? nex
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并两个文件夹,other不会发生改变,this将合并一个副本
|
||||
/// 文件夹合并
|
||||
/// </summary>
|
||||
/// <param name="other">它的一个clone将被合并的dir,它的NextOp 不应该是空,否则什么都不会发生</param>
|
||||
/// <param name="fileDirOp">具体操作步骤</param>
|
||||
/// <param name="diffdir">将要更新的内容</param>
|
||||
/// <param name="IsUpdateObject"> 是否更新Object对象</param>
|
||||
/// <param name="IsUpdateDirFile">是否更新文件目录树</param>
|
||||
/// <returns></returns>
|
||||
public (bool, string) Combine(Dir other)
|
||||
public (bool, string) Combine(
|
||||
FileDirOp? fileDirOp,
|
||||
Dir diffdir,
|
||||
bool IsUpdateObject = true,
|
||||
bool IsUpdateDirFile = false
|
||||
)
|
||||
{
|
||||
if (this.FormatedPath != diffdir.FormatedPath)
|
||||
{
|
||||
return (false, "their path is not same");
|
||||
}
|
||||
else
|
||||
{
|
||||
var ldir = this;
|
||||
var rdir = diffdir;
|
||||
|
||||
foreach (var oc in diffdir.Children)
|
||||
{
|
||||
if (oc is File rfile)
|
||||
{
|
||||
if (rfile.NextOp != null)
|
||||
{
|
||||
if (oc.NextOp == NextOpType.Add)
|
||||
{
|
||||
if (IsUpdateObject)
|
||||
{
|
||||
ldir.AddChild(new File(rfile.FormatedPath, rfile.MTime));
|
||||
}
|
||||
if (IsUpdateDirFile)
|
||||
{
|
||||
fileDirOp?.FileCreate(rfile.FormatedPath, rfile.MTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var n = ldir
|
||||
.Children.Where(x =>
|
||||
x.FormatedPath == oc.FormatedPath && x.Type == DirOrFile.File
|
||||
)
|
||||
.FirstOrDefault();
|
||||
if (n is not null)
|
||||
{
|
||||
if (oc.NextOp == NextOpType.Del)
|
||||
{
|
||||
if (IsUpdateObject)
|
||||
{
|
||||
ldir.Children.Remove(n);
|
||||
}
|
||||
if (IsUpdateDirFile)
|
||||
{
|
||||
fileDirOp?.FileDel(rfile.FormatedPath);
|
||||
}
|
||||
}
|
||||
else if (oc.NextOp == NextOpType.Modify)
|
||||
{
|
||||
if (n is File lfile)
|
||||
{
|
||||
if (IsUpdateObject)
|
||||
{
|
||||
lfile.MTime = rfile.MTime;
|
||||
}
|
||||
if (IsUpdateDirFile)
|
||||
{
|
||||
fileDirOp?.FileModify(rfile.FormatedPath, rfile.MTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (oc is Dir rrdir)
|
||||
{
|
||||
//新增和删除意味着整个文件夹都被新增和删除
|
||||
if (rrdir.NextOp == NextOpType.Add)
|
||||
{
|
||||
if (IsUpdateDirFile)
|
||||
{
|
||||
fileDirOp?.DirCreate(rrdir);
|
||||
}
|
||||
if (IsUpdateObject)
|
||||
{
|
||||
ldir.AddChild(rrdir.Clone(null, true));
|
||||
}
|
||||
}
|
||||
else if (rrdir.NextOp == NextOpType.Del)
|
||||
{
|
||||
if (IsUpdateDirFile)
|
||||
{
|
||||
fileDirOp?.DirDel(rrdir,false);
|
||||
}
|
||||
if (IsUpdateObject)
|
||||
{
|
||||
ldir.Children.RemoveAt(
|
||||
ldir.Children.FindIndex(x => x.FormatedPath == rrdir.FormatedPath)
|
||||
);
|
||||
}
|
||||
}
|
||||
//当子文件夹和文件不确定时
|
||||
else
|
||||
{
|
||||
var n = ldir
|
||||
.Children.Where(x =>
|
||||
x.FormatedPath == rrdir.FormatedPath && x.Type == DirOrFile.Dir
|
||||
)
|
||||
.FirstOrDefault();
|
||||
if (n is Dir lldir)
|
||||
{
|
||||
lldir.Combine(fileDirOp, rrdir, IsUpdateObject, IsUpdateDirFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (true, "");
|
||||
}
|
||||
|
||||
public (bool, string) Combine_Old(Dir other)
|
||||
{
|
||||
if (this.FormatedPath != other.FormatedPath)
|
||||
{
|
||||
|
@ -191,7 +311,7 @@ public class Dir(string path, List<AFileOrDir>? children = null, NextOpType? nex
|
|||
.FirstOrDefault();
|
||||
if (n is Dir lldir)
|
||||
{
|
||||
lldir.Combine(rrdir);
|
||||
lldir.Combine_Old(rrdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,6 +320,26 @@ public class Dir(string path, List<AFileOrDir>? children = null, NextOpType? nex
|
|||
return (true, "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并两个文件夹,other不会发生改变,this将合并一个副本,这不会改变文件结构
|
||||
/// </summary>
|
||||
/// <param name="other">它的一个clone将被合并的dir,它的NextOp 不应该是空,否则什么都不会发生</param>
|
||||
/// <returns></returns>
|
||||
public (bool, string) CombineJustObject(Dir other)
|
||||
{
|
||||
return Combine(null, other, true, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并两个文件夹,other不会发生改变,this将不会改变,而文件结构会改变
|
||||
/// </summary>
|
||||
/// <param name="other">它的一个clone将被合并的dir,它的NextOp 不应该是空,否则什么都不会发生</param>
|
||||
/// <returns></returns>
|
||||
public (bool, string) CombineJustDirFile(FileDirOp fileDirOp, Dir diffDir)
|
||||
{
|
||||
return Combine(fileDirOp, diffDir, false, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加子节点,根目录相同,才会被添加进去
|
||||
/// </summary>
|
||||
|
@ -207,7 +347,7 @@ public class Dir(string path, List<AFileOrDir>? children = null, NextOpType? nex
|
|||
/// <returns></returns>/
|
||||
protected (bool, string) AddChild(AFileOrDir child)
|
||||
{
|
||||
if (child.FormatedPath.Substring(0, this.FormatedPath.Length) != this.FormatedPath)
|
||||
if (child.FormatedPath[..this.FormatedPath.Length] != this.FormatedPath)
|
||||
{
|
||||
return (false, "their rootpath are not same!");
|
||||
}
|
||||
|
@ -270,29 +410,32 @@ public class Dir(string path, List<AFileOrDir>? children = null, NextOpType? nex
|
|||
/// 文件的修改时间,是否修改文件的修改时间,需要定义文件的写入策略 WriteFileStrageFunc
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public (bool, string) WriteByThisInfo()
|
||||
public (bool, string) WriteByThisInfo(FileDirOp fileDirOp)
|
||||
{
|
||||
static (bool, string) f(Dir dir)
|
||||
static (bool, string) f(Dir dir, FileDirOp fileDirOp)
|
||||
{
|
||||
foreach (var child in dir.Children)
|
||||
{
|
||||
if (child.Type == DirOrFile.Dir)
|
||||
{
|
||||
var (IsSuccess, Message) = WriteDirStrageFunc(child.FormatedPath);
|
||||
if (!IsSuccess)
|
||||
{
|
||||
return (false, Message);
|
||||
}
|
||||
if (child is Dir childDir)
|
||||
{
|
||||
f(childDir);
|
||||
var (IsSuccess, Message) = fileDirOp.DirCreate(childDir, false);
|
||||
if (!IsSuccess)
|
||||
{
|
||||
return (false, Message);
|
||||
}
|
||||
f(childDir, fileDirOp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (child is File childFile)
|
||||
{
|
||||
var (IsSuccess, Message) = WriteFileStrageFunc(childFile);
|
||||
var (IsSuccess, Message) = fileDirOp.FileCreate(
|
||||
child.FormatedPath,
|
||||
childFile.MTime
|
||||
);
|
||||
if (!IsSuccess)
|
||||
{
|
||||
return (false, Message);
|
||||
|
@ -306,24 +449,9 @@ public class Dir(string path, List<AFileOrDir>? children = null, NextOpType? nex
|
|||
}
|
||||
return (true, "");
|
||||
}
|
||||
return f(this);
|
||||
return f(this, fileDirOp);
|
||||
}
|
||||
#pragma warning disable CA2211 // Non-constant fields should not be visible
|
||||
public static Func<File, (bool, string)> WriteFileStrageFunc = (File file) =>
|
||||
{
|
||||
return (false, "you must implement this function!");
|
||||
};
|
||||
#pragma warning restore CA2211 // Non-constant fields should not be visible
|
||||
#pragma warning disable CA2211 // Non-constant fields should not be visible
|
||||
public static Func<string, (bool, string)> WriteDirStrageFunc = (string path) =>
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
return (true, "");
|
||||
};
|
||||
#pragma warning restore CA2211 // Non-constant fields should not be visible
|
||||
|
||||
/// <summary>
|
||||
/// 比较两个目录文件树是否相同,不相同返回差异部分,左侧是右侧的下一个版本
|
||||
/// </summary>
|
||||
|
|
90
Server/Common/FileDirOp.cs
Normal file
90
Server/Common/FileDirOp.cs
Normal file
|
@ -0,0 +1,90 @@
|
|||
using System.Text;
|
||||
|
||||
namespace Common;
|
||||
|
||||
public abstract class FileDirOp
|
||||
{
|
||||
public abstract (bool, string) FileCreate(string absolutePath, DateTime mtime);
|
||||
|
||||
public abstract (bool, string) DirCreate(Dir dir, bool IsRecursion = true);
|
||||
|
||||
public abstract (bool, string) FileModify(string absolutePath, DateTime mtime);
|
||||
public abstract (bool, string) FileDel(string absolutePath);
|
||||
public abstract (bool, string) DirDel(Dir dir, bool IsRecursion = true);
|
||||
}
|
||||
|
||||
public class SimpleFileDirOpForTest : FileDirOp
|
||||
{
|
||||
public override (bool, string) FileCreate(string absolutePath, DateTime mtime)
|
||||
{
|
||||
using (FileStream fs = System.IO.File.OpenWrite(absolutePath))
|
||||
{
|
||||
byte[] info = Encoding.UTF8.GetBytes($"this is {absolutePath},Now{mtime}");
|
||||
fs.Write(info, 0, info.Length);
|
||||
}
|
||||
System.IO.File.SetLastWriteTime(absolutePath, mtime);
|
||||
return (true, "");
|
||||
}
|
||||
|
||||
public override (bool, string) FileModify(string absolutePath, DateTime mtime)
|
||||
{
|
||||
using (FileStream fs = System.IO.File.OpenWrite(absolutePath))
|
||||
{
|
||||
byte[] info = Encoding.UTF8.GetBytes($"this is {absolutePath},Now{mtime}");
|
||||
fs.Write(info, 0, info.Length);
|
||||
}
|
||||
System.IO.File.SetLastWriteTime(absolutePath, mtime);
|
||||
return (true, "");
|
||||
}
|
||||
|
||||
public override (bool, string) FileDel(string absolutePath)
|
||||
{
|
||||
//ToDo 权限检查
|
||||
if (System.IO.File.Exists(absolutePath))
|
||||
{
|
||||
System.IO.File.Delete(absolutePath);
|
||||
}
|
||||
return (true, "");
|
||||
}
|
||||
|
||||
public override (bool, string) DirCreate(Dir dir, bool IsRecursion = true)
|
||||
{
|
||||
//TODO需做权限检查
|
||||
if (!Directory.Exists(dir.FormatedPath))
|
||||
{
|
||||
Directory.CreateDirectory(dir.FormatedPath);
|
||||
if (IsRecursion)
|
||||
{
|
||||
foreach (var fd in dir.Children)
|
||||
{
|
||||
if (fd is File file)
|
||||
{
|
||||
this.FileCreate(file.FormatedPath, file.MTime);
|
||||
}
|
||||
else if (fd is Dir sdir)
|
||||
{
|
||||
DirCreate(sdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (true, "");
|
||||
}
|
||||
|
||||
public override (bool, string) DirDel(Dir dir, bool IsRecursion = true)
|
||||
{
|
||||
//TODO 权限检查 正式徐执行递归
|
||||
if (!IsRecursion)
|
||||
{
|
||||
if (Directory.Exists(dir.FormatedPath))
|
||||
{
|
||||
Directory.Delete(dir.FormatedPath, true);
|
||||
}
|
||||
return (true, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +1,86 @@
|
|||
namespace ServerTest;
|
||||
using Common;
|
||||
using Newtonsoft.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Xunit;
|
||||
/*using Newtonsoft.Json;*/
|
||||
using XUnit.Project.Attributes;
|
||||
|
||||
namespace ServerTest;
|
||||
|
||||
/// <summary>
|
||||
/// xUnit将会对每个测试方法创建一个测试上下文,IClassFixture可以用来创建类中共享测试上下文,
|
||||
///
|
||||
///
|
||||
/// XUnit 的测试方法不是按照顺序执行,所以注意对象状态
|
||||
///
|
||||
/// 一般单元测试,每个测试函数应当是独立的,不让它们按照顺序执行,在一般情况下是最好的做法,参考
|
||||
/// https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices
|
||||
/// 目前涉及到一些文件的同步,所以按照顺序执行相对较好,这使用了xUnit的方法使它们按照顺序执行
|
||||
/// </summary>
|
||||
///
|
||||
[TestCaseOrderer(
|
||||
ordererTypeName: "XUnit.Project.Orderers.PriorityOrderer",
|
||||
ordererAssemblyName: "ServerTest"
|
||||
)]
|
||||
public class DirFileOpTest(FilesSeed filesSeed) : IClassFixture<FilesSeed>
|
||||
{
|
||||
private readonly FilesSeed filesSeed = filesSeed;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 测试文件目录写入和提取
|
||||
/// </summary>
|
||||
[Fact]
|
||||
[Fact, TestPriority(0)]
|
||||
public void FileDirWriteExtract()
|
||||
{
|
||||
var (IsSuccess, Message) = filesSeed.NewDir.WriteByThisInfo();
|
||||
Assert.True(IsSuccess);
|
||||
Dir nd = new(filesSeed.NewDir.FormatedPath);
|
||||
nd.ExtractInfo();
|
||||
Assert.True(nd.IsEqual(filesSeed.NewDir));
|
||||
var (IsSuccess, Message) = filesSeed.NewDir.WriteByThisInfo(filesSeed.fileDirOp);
|
||||
var (IsSuccess2, Message2) = filesSeed.OldDir.WriteByThisInfo(filesSeed.fileDirOp);
|
||||
Assert.True(IsSuccess, "新文件写入失败!");
|
||||
Assert.True(IsSuccess2, "旧文件写入失败!");
|
||||
Dir nnd = new(filesSeed.NewDir.FormatedPath);
|
||||
nnd.ExtractInfo();
|
||||
Assert.True(nnd.IsEqual(filesSeed.NewDir), "新文件提取文件夹的信息与写入信息不一致!");
|
||||
Dir nod = new(filesSeed.OldDir.FormatedPath);
|
||||
nod.ExtractInfo();
|
||||
Assert.True(nod.IsEqual(filesSeed.OldDir), "旧提取文件夹的信息与写入信息不一致!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试文件差异比较
|
||||
/// </summary>
|
||||
[Fact]
|
||||
[Fact, TestPriority(1)]
|
||||
public void FileDirDiff()
|
||||
{
|
||||
var cDDir = filesSeed.NewDir.Diff(filesSeed.OldDir);
|
||||
|
||||
|
||||
// Console.WriteLine("################################");
|
||||
// Console.WriteLine(cDDir.Children.Count);
|
||||
//Assert.True(IsSuccess);
|
||||
|
||||
var str = JsonConvert.SerializeObject(cDDir);
|
||||
Assert.True(cDDir.Children.Count !=0);
|
||||
Assert.True(filesSeed.DiffDir.IsEqual(cDDir));
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试文件合并
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void DirsCombine()
|
||||
{
|
||||
var OldDirClone = filesSeed.OldDir.Clone();
|
||||
var (IsSuccess, Message) = OldDirClone.Combine(filesSeed.DiffDir);
|
||||
Assert.True(IsSuccess);
|
||||
//Assert.False(filesSeed.NewDir.IsEqual(filesSeed.OldDir));
|
||||
OldDirClone.ResetRootPath("OldDir","NewDir");
|
||||
// Console.WriteLine(filesSeed.OldDir.Path);
|
||||
Assert.True(OldDirClone.IsEqual(filesSeed.NewDir));
|
||||
|
||||
/*var str = JsonConvert.SerializeObject(cDDir);*/
|
||||
Assert.True(filesSeed.DiffDir.IsEqual(cDDir), "文件对比结果错误!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试同步是否成功
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void FinalSyncFileDir()
|
||||
[Fact, TestPriority(2)]
|
||||
public void SyncFileDir()
|
||||
{
|
||||
Assert.True(true);
|
||||
}
|
||||
var (IsSuccess,Messsage) = filesSeed.OldDir.CombineJustDirFile(filesSeed.fileDirOp,filesSeed.DiffDir);
|
||||
Assert.True(IsSuccess, "文件更新错误!");
|
||||
Dir oldSync = new(filesSeed.OldDir.FormatedPath);
|
||||
oldSync.ExtractInfo();
|
||||
oldSync.ResetRootPath(filesSeed.OldDir.FormatedPath, filesSeed.NewDir.FormatedPath);
|
||||
Assert.True(oldSync.IsEqual(filesSeed.NewDir), "文件夹同步后信息保持不一致!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试文件合并
|
||||
/// </summary>
|
||||
[Fact, TestPriority(3)]
|
||||
public void DirsCombine()
|
||||
{
|
||||
var (IsSuccess, Message) = filesSeed.OldDir.CombineJustObject(filesSeed.DiffDir);
|
||||
Assert.True(IsSuccess, "文件合并出错!");
|
||||
//Assert.False(filesSeed.NewDir.IsEqual(filesSeed.OldDir));
|
||||
filesSeed.OldDir.ResetRootPath("OldDir", "NewDir");
|
||||
// Console.WriteLine(filesSeed.OldDir.Path);
|
||||
Assert.True(filesSeed.OldDir.IsEqual(filesSeed.NewDir), "合并结果不一致!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,18 +7,6 @@ public class FilesSeed : IDisposable
|
|||
{
|
||||
public FilesSeed()
|
||||
{
|
||||
Dir.WriteFileStrageFunc = (Common.File file) =>
|
||||
{
|
||||
//创建或者不创建直接打开文件
|
||||
using (FileStream fs = System.IO.File.OpenWrite(file.FormatedPath))
|
||||
{
|
||||
byte[] info = Encoding.UTF8.GetBytes($"this is {file.FormatedPath},Now{DateTime.Now}");
|
||||
fs.Write(info, 0, info.Length);
|
||||
}
|
||||
Console.WriteLine($"WriteFileStrageFunc {file.FormatedPath}");
|
||||
System.IO.File.SetLastWriteTime(file.FormatedPath, file.MTime);
|
||||
return (true, "");
|
||||
};
|
||||
Console.WriteLine("FilesSeed Construct");
|
||||
// string TestPath = Path.Combine(Directory.GetCurrentDirectory(), "../../..");
|
||||
DateTime NewTime = DateTime.Now.AddSeconds(-99);
|
||||
|
@ -88,20 +76,20 @@ public class FilesSeed : IDisposable
|
|||
$"{TestPath}/OldDir/2/2_2_M",
|
||||
[
|
||||
new Common.File(
|
||||
$"{TestPath}/OldDir/2/2_2/1.txt",
|
||||
$"{TestPath}/OldDir/2/2_2_M/1.txt",
|
||||
OldTime,
|
||||
NextOpType.Del
|
||||
),
|
||||
new Common.File(
|
||||
$"{TestPath}/OldDir/2/2_2/2.txt",
|
||||
$"{TestPath}/OldDir/2/2_2_M/2.txt",
|
||||
OldTime,
|
||||
NextOpType.Del
|
||||
),
|
||||
new Dir(
|
||||
$"{TestPath}/OldDir/2/2_2/2_3",
|
||||
$"{TestPath}/OldDir/2/2_2_M/2_3",
|
||||
[
|
||||
new Common.File(
|
||||
$"{TestPath}/OldDir/2/2_2/2_3/1.txt",
|
||||
$"{TestPath}/OldDir/2/2_2_M/2_3/1.txt",
|
||||
OldTime,
|
||||
NextOpType.Del
|
||||
),
|
||||
|
@ -168,13 +156,13 @@ public class FilesSeed : IDisposable
|
|||
new Dir(
|
||||
$"{TestPath}/OldDir/2/2_2_M",
|
||||
[
|
||||
new Common.File($"{TestPath}/OldDir/2/2_2/1.txt", OldTime),
|
||||
new Common.File($"{TestPath}/OldDir/2/2_2/2.txt", OldTime),
|
||||
new Common.File($"{TestPath}/OldDir/2/2_2_M/1.txt", OldTime),
|
||||
new Common.File($"{TestPath}/OldDir/2/2_2_M/2.txt", OldTime),
|
||||
new Dir(
|
||||
$"{TestPath}/OldDir/2/2_2/2_3",
|
||||
$"{TestPath}/OldDir/2/2_2_M/2_3",
|
||||
[
|
||||
new Common.File(
|
||||
$"{TestPath}/OldDir/2/2_2/2_3/1.txt",
|
||||
$"{TestPath}/OldDir/2/2_2_M/2_3/1.txt",
|
||||
OldTime
|
||||
),
|
||||
]
|
||||
|
@ -185,17 +173,19 @@ public class FilesSeed : IDisposable
|
|||
),
|
||||
]
|
||||
);
|
||||
fileDirOp = new SimpleFileDirOpForTest();
|
||||
}
|
||||
|
||||
private readonly string TestPath = Path.Combine(Directory.GetCurrentDirectory(), "../../..");
|
||||
public Dir NewDir;
|
||||
public Dir OldDir;
|
||||
|
||||
public Dir DiffDir;
|
||||
public FileDirOp fileDirOp;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Directory.Delete(NewDir.FormatedPath, true);
|
||||
Directory.Delete($"{TestPath}/OldDir", true);
|
||||
Directory.Delete($"{TestPath}/NewDir", true);
|
||||
Console.WriteLine("FilesSeed Dispose");
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
|
41
Server/ServerTest/PriorityOrderer.cs
Normal file
41
Server/ServerTest/PriorityOrderer.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
using XUnit.Project.Attributes;
|
||||
|
||||
namespace XUnit.Project.Orderers;
|
||||
|
||||
public class PriorityOrderer : ITestCaseOrderer
|
||||
{
|
||||
public IEnumerable<TTestCase> OrderTestCases<TTestCase>(
|
||||
IEnumerable<TTestCase> testCases) where TTestCase : ITestCase
|
||||
{
|
||||
string assemblyName = typeof(TestPriorityAttribute).AssemblyQualifiedName!;
|
||||
var sortedMethods = new SortedDictionary<int, List<TTestCase>>();
|
||||
foreach (TTestCase testCase in testCases)
|
||||
{
|
||||
int priority = testCase.TestMethod.Method
|
||||
.GetCustomAttributes(assemblyName)
|
||||
.FirstOrDefault()
|
||||
?.GetNamedArgument<int>(nameof(TestPriorityAttribute.Priority)) ?? 0;
|
||||
|
||||
GetOrCreate(sortedMethods, priority).Add(testCase);
|
||||
}
|
||||
|
||||
foreach (TTestCase testCase in
|
||||
sortedMethods.Keys.SelectMany(
|
||||
priority => sortedMethods[priority].OrderBy(
|
||||
testCase => testCase.TestMethod.Method.Name)))
|
||||
{
|
||||
Console.WriteLine(testCase);
|
||||
yield return testCase;
|
||||
}
|
||||
}
|
||||
|
||||
private static TValue GetOrCreate<TKey, TValue>(
|
||||
IDictionary<TKey, TValue> dictionary, TKey key)
|
||||
where TKey : struct
|
||||
where TValue : new() =>
|
||||
dictionary.TryGetValue(key, out TValue? result)
|
||||
? result
|
||||
: (dictionary[key] = new TValue());
|
||||
}
|
9
Server/ServerTest/TestPriorityAttribute.cs
Normal file
9
Server/ServerTest/TestPriorityAttribute.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace XUnit.Project.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||
public class TestPriorityAttribute : Attribute
|
||||
{
|
||||
public int Priority { get; private set; }
|
||||
|
||||
public TestPriorityAttribute(int priority) => Priority = priority;
|
||||
}
|
Loading…
Reference in a new issue