Browse Source
- 重构IRanGainControlHandler接口,移除RanIPEndPoint参数,统一从ICellularNetworkContext获取端点信息 - 修复SetTxGainCommand构造函数,添加参数验证 - 创建SetAllTxGainCommand和SetAllTxGainCommandHandler,支持批量设置发送增益 - 创建RanAPIController,提供统一的RAN API访问接口 - 优化依赖注入配置,统一使用工厂模式release/web-ui-v1.0.0
36 changed files with 2649 additions and 3 deletions
@ -0,0 +1,53 @@ |
|||
using X1.Domain.Common; |
|||
using MediatR; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace X1.Application.Features.ScenarioTestCases.Commands.CreateScenarioTestCase; |
|||
|
|||
/// <summary>
|
|||
/// 创建场景测试用例命令
|
|||
/// </summary>
|
|||
public class CreateScenarioTestCaseCommand : IRequest<OperationResult<CreateScenarioTestCaseResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "场景ID不能为空")] |
|||
public string ScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 测试用例列表
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "测试用例列表不能为空")] |
|||
[MinLength(1, ErrorMessage = "至少需要包含一个测试用例")] |
|||
public List<ScenarioTestCaseItem> TestCases { get; set; } = new(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 场景测试用例项
|
|||
/// </summary>
|
|||
public class ScenarioTestCaseItem |
|||
{ |
|||
/// <summary>
|
|||
/// 测试用例流程ID
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "测试用例流程ID不能为空")] |
|||
public string TestCaseFlowId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 执行顺序
|
|||
/// </summary>
|
|||
[Range(0, int.MaxValue, ErrorMessage = "执行顺序必须大于等于0")] |
|||
public int ExecutionOrder { get; set; } = 0; |
|||
|
|||
/// <summary>
|
|||
/// 循环次数
|
|||
/// </summary>
|
|||
[Range(1, int.MaxValue, ErrorMessage = "循环次数必须大于0")] |
|||
public int LoopCount { get; set; } = 1; |
|||
|
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } = true; |
|||
} |
|||
@ -0,0 +1,131 @@ |
|||
using MediatR; |
|||
using Microsoft.Extensions.Logging; |
|||
using X1.Domain.Common; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.TestCase; |
|||
using X1.Domain.Repositories.Base; |
|||
using X1.Domain.Services; |
|||
|
|||
namespace X1.Application.Features.ScenarioTestCases.Commands.CreateScenarioTestCase; |
|||
|
|||
/// <summary>
|
|||
/// 创建场景测试用例命令处理器
|
|||
/// </summary>
|
|||
public class CreateScenarioTestCaseCommandHandler : IRequestHandler<CreateScenarioTestCaseCommand, OperationResult<CreateScenarioTestCaseResponse>> |
|||
{ |
|||
private readonly IScenarioTestCaseRepository _scenarioTestCaseRepository; |
|||
private readonly ITestScenarioRepository _testScenarioRepository; |
|||
private readonly ILogger<CreateScenarioTestCaseCommandHandler> _logger; |
|||
private readonly IUnitOfWork _unitOfWork; |
|||
private readonly ICurrentUserService _currentUserService; |
|||
|
|||
/// <summary>
|
|||
/// 初始化命令处理器
|
|||
/// </summary>
|
|||
public CreateScenarioTestCaseCommandHandler( |
|||
IScenarioTestCaseRepository scenarioTestCaseRepository, |
|||
ITestScenarioRepository testScenarioRepository, |
|||
ILogger<CreateScenarioTestCaseCommandHandler> logger, |
|||
IUnitOfWork unitOfWork, |
|||
ICurrentUserService currentUserService) |
|||
{ |
|||
_scenarioTestCaseRepository = scenarioTestCaseRepository; |
|||
_testScenarioRepository = testScenarioRepository; |
|||
_logger = logger; |
|||
_unitOfWork = unitOfWork; |
|||
_currentUserService = currentUserService; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 处理创建场景测试用例命令
|
|||
/// </summary>
|
|||
public async Task<OperationResult<CreateScenarioTestCaseResponse>> Handle(CreateScenarioTestCaseCommand request, CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogInformation("开始创建场景测试用例,场景ID: {ScenarioId}, 测试用例数量: {TestCaseCount}", |
|||
request.ScenarioId, request.TestCases.Count); |
|||
|
|||
// 获取当前用户ID
|
|||
var currentUserId = _currentUserService.GetCurrentUserId(); |
|||
if (string.IsNullOrEmpty(currentUserId)) |
|||
{ |
|||
_logger.LogError("无法获取当前用户ID,用户可能未认证"); |
|||
return OperationResult<CreateScenarioTestCaseResponse>.CreateFailure("用户未认证,无法创建场景测试用例"); |
|||
} |
|||
|
|||
// 验证场景是否存在
|
|||
var scenario = await _testScenarioRepository.GetByIdAsync(request.ScenarioId, cancellationToken:cancellationToken); |
|||
if (scenario == null) |
|||
{ |
|||
_logger.LogWarning("测试场景不存在,场景ID: {ScenarioId}", request.ScenarioId); |
|||
return OperationResult<CreateScenarioTestCaseResponse>.CreateFailure($"测试场景不存在,场景ID: {request.ScenarioId}"); |
|||
} |
|||
|
|||
var response = new CreateScenarioTestCaseResponse |
|||
{ |
|||
TotalCount = request.TestCases.Count |
|||
}; |
|||
|
|||
// 批量检查场景中已存在的测试用例流程ID
|
|||
var testCaseFlowIds = request.TestCases.Select(x => x.TestCaseFlowId).ToList(); |
|||
var existingTestCaseFlowIds = await _scenarioTestCaseRepository.GetExistingTestCaseFlowIdsAsync( |
|||
request.ScenarioId, testCaseFlowIds, cancellationToken); |
|||
|
|||
// 批量创建测试用例
|
|||
foreach (var testCase in request.TestCases) |
|||
{ |
|||
try |
|||
{ |
|||
// 检查场景中是否已存在指定的测试用例
|
|||
if (existingTestCaseFlowIds.Contains(testCase.TestCaseFlowId)) |
|||
{ |
|||
var errorMessage = $"场景中已存在指定的测试用例,测试用例流程ID: {testCase.TestCaseFlowId}"; |
|||
response.ErrorMessages.Add(errorMessage); |
|||
response.FailureCount++; |
|||
_logger.LogWarning(errorMessage); |
|||
continue; |
|||
} |
|||
|
|||
// 创建场景测试用例实体
|
|||
var scenarioTestCase = ScenarioTestCase.Create( |
|||
scenarioId: request.ScenarioId, |
|||
testCaseFlowId: testCase.TestCaseFlowId, |
|||
executionOrder: testCase.ExecutionOrder, |
|||
loopCount: testCase.LoopCount, |
|||
isEnabled: testCase.IsEnabled, |
|||
createdBy: currentUserId); |
|||
|
|||
// 保存场景测试用例
|
|||
await _scenarioTestCaseRepository.AddAsync(scenarioTestCase, cancellationToken); |
|||
|
|||
response.SuccessIds.Add(scenarioTestCase.Id); |
|||
response.SuccessCount++; |
|||
|
|||
_logger.LogDebug("成功创建场景测试用例,场景测试用例ID: {ScenarioTestCaseId}, 测试用例流程ID: {TestCaseFlowId}", |
|||
scenarioTestCase.Id, testCase.TestCaseFlowId); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
var errorMessage = $"创建测试用例失败,测试用例流程ID: {testCase.TestCaseFlowId}, 错误: {ex.Message}"; |
|||
response.ErrorMessages.Add(errorMessage); |
|||
response.FailureCount++; |
|||
_logger.LogError(ex, errorMessage); |
|||
} |
|||
} |
|||
|
|||
// 保存更改到数据库
|
|||
await _unitOfWork.SaveChangesAsync(cancellationToken); |
|||
|
|||
_logger.LogInformation("创建场景测试用例完成,场景ID: {ScenarioId}, 成功: {SuccessCount}, 失败: {FailureCount}", |
|||
request.ScenarioId, response.SuccessCount, response.FailureCount); |
|||
|
|||
return OperationResult<CreateScenarioTestCaseResponse>.CreateSuccess(response); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "创建场景测试用例时发生错误,场景ID: {ScenarioId}", request.ScenarioId); |
|||
return OperationResult<CreateScenarioTestCaseResponse>.CreateFailure($"创建场景测试用例时发生错误: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
namespace X1.Application.Features.ScenarioTestCases.Commands.CreateScenarioTestCase; |
|||
|
|||
/// <summary>
|
|||
/// 创建场景测试用例响应
|
|||
/// </summary>
|
|||
public class CreateScenarioTestCaseResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 成功创建的测试用例数量
|
|||
/// </summary>
|
|||
public int SuccessCount { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 失败的测试用例数量
|
|||
/// </summary>
|
|||
public int FailureCount { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 总数量
|
|||
/// </summary>
|
|||
public int TotalCount { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 成功创建的测试用例ID列表
|
|||
/// </summary>
|
|||
public List<string> SuccessIds { get; set; } = new(); |
|||
|
|||
/// <summary>
|
|||
/// 失败的错误信息
|
|||
/// </summary>
|
|||
public List<string> ErrorMessages { get; set; } = new(); |
|||
|
|||
/// <summary>
|
|||
/// 是否全部成功
|
|||
/// </summary>
|
|||
public bool IsAllSuccess => FailureCount == 0; |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
using X1.Domain.Common; |
|||
using MediatR; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace X1.Application.Features.ScenarioTestCases.Queries.GetScenarioTestCases; |
|||
|
|||
/// <summary>
|
|||
/// 获取场景测试用例列表查询
|
|||
/// </summary>
|
|||
public class GetScenarioTestCasesQuery : IRequest<OperationResult<GetScenarioTestCasesResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "场景ID不能为空")] |
|||
public string ScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 是否只获取启用的测试用例
|
|||
/// </summary>
|
|||
public bool? IsEnabled { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否包含详细信息
|
|||
/// </summary>
|
|||
public bool IncludeDetails { get; set; } = false; |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
using MediatR; |
|||
using Microsoft.Extensions.Logging; |
|||
using X1.Domain.Common; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.TestCase; |
|||
|
|||
namespace X1.Application.Features.ScenarioTestCases.Queries.GetScenarioTestCases; |
|||
|
|||
/// <summary>
|
|||
/// 获取场景测试用例列表查询处理器
|
|||
/// </summary>
|
|||
public class GetScenarioTestCasesQueryHandler : IRequestHandler<GetScenarioTestCasesQuery, OperationResult<GetScenarioTestCasesResponse>> |
|||
{ |
|||
private readonly IScenarioTestCaseRepository _scenarioTestCaseRepository; |
|||
private readonly ITestScenarioRepository _testScenarioRepository; |
|||
private readonly ILogger<GetScenarioTestCasesQueryHandler> _logger; |
|||
|
|||
/// <summary>
|
|||
/// 初始化查询处理器
|
|||
/// </summary>
|
|||
public GetScenarioTestCasesQueryHandler( |
|||
IScenarioTestCaseRepository scenarioTestCaseRepository, |
|||
ITestScenarioRepository testScenarioRepository, |
|||
ILogger<GetScenarioTestCasesQueryHandler> logger) |
|||
{ |
|||
_scenarioTestCaseRepository = scenarioTestCaseRepository; |
|||
_testScenarioRepository = testScenarioRepository; |
|||
_logger = logger; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 处理获取场景测试用例列表查询
|
|||
/// </summary>
|
|||
public async Task<OperationResult<GetScenarioTestCasesResponse>> Handle(GetScenarioTestCasesQuery request, CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogInformation("开始获取场景测试用例列表,场景ID: {ScenarioId}, 包含详细信息: {IncludeDetails}", |
|||
request.ScenarioId, request.IncludeDetails); |
|||
|
|||
// 验证场景是否存在
|
|||
var scenario = await _testScenarioRepository.GetByIdAsync(request.ScenarioId, cancellationToken:cancellationToken); |
|||
if (scenario == null) |
|||
{ |
|||
_logger.LogWarning("测试场景不存在,场景ID: {ScenarioId}", request.ScenarioId); |
|||
return OperationResult<GetScenarioTestCasesResponse>.CreateFailure($"测试场景不存在,场景ID: {request.ScenarioId}"); |
|||
} |
|||
|
|||
// 获取场景测试用例
|
|||
IEnumerable<ScenarioTestCase> testCases; |
|||
if (request.IncludeDetails) |
|||
{ |
|||
testCases = await _scenarioTestCaseRepository.GetWithDetailsByScenarioIdAsync(request.ScenarioId, cancellationToken); |
|||
} |
|||
else if (request.IsEnabled.HasValue) |
|||
{ |
|||
testCases = await _scenarioTestCaseRepository.GetEnabledByScenarioIdAsync(request.ScenarioId, cancellationToken); |
|||
} |
|||
else |
|||
{ |
|||
testCases = await _scenarioTestCaseRepository.GetByScenarioIdAsync(request.ScenarioId, cancellationToken); |
|||
} |
|||
|
|||
// 转换为DTO
|
|||
var testCaseDtos = testCases.Select(x => new ScenarioTestCaseDto |
|||
{ |
|||
ScenarioTestCaseId = x.Id, |
|||
ScenarioId = x.ScenarioId, |
|||
TestCaseFlowId = x.TestCaseFlowId, |
|||
TestCaseFlowName = x.TestCaseFlow?.Name, |
|||
ExecutionOrder = x.ExecutionOrder, |
|||
LoopCount = x.LoopCount, |
|||
IsEnabled = x.IsEnabled, |
|||
CreatedAt = x.CreatedAt, |
|||
CreatedBy = x.CreatedBy, |
|||
UpdatedAt = x.UpdatedAt, |
|||
UpdatedBy = x.UpdatedBy |
|||
}).ToList(); |
|||
|
|||
// 构建响应
|
|||
var response = new GetScenarioTestCasesResponse |
|||
{ |
|||
ScenarioId = request.ScenarioId, |
|||
TestCases = testCaseDtos, |
|||
TotalCount = testCaseDtos.Count |
|||
}; |
|||
|
|||
_logger.LogInformation("获取场景测试用例列表成功,场景ID: {ScenarioId}, 测试用例数量: {TestCaseCount}", |
|||
request.ScenarioId, testCaseDtos.Count); |
|||
return OperationResult<GetScenarioTestCasesResponse>.CreateSuccess(response); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "获取场景测试用例列表时发生错误,场景ID: {ScenarioId}", request.ScenarioId); |
|||
return OperationResult<GetScenarioTestCasesResponse>.CreateFailure($"获取场景测试用例列表时发生错误: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
namespace X1.Application.Features.ScenarioTestCases.Queries.GetScenarioTestCases; |
|||
|
|||
/// <summary>
|
|||
/// 获取场景测试用例列表响应
|
|||
/// </summary>
|
|||
public class GetScenarioTestCasesResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
public string ScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景测试用例列表
|
|||
/// </summary>
|
|||
public List<ScenarioTestCaseDto> TestCases { get; set; } = new(); |
|||
|
|||
/// <summary>
|
|||
/// 总数量
|
|||
/// </summary>
|
|||
public int TotalCount { get; set; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 场景测试用例数据传输对象
|
|||
/// </summary>
|
|||
public class ScenarioTestCaseDto |
|||
{ |
|||
/// <summary>
|
|||
/// 场景测试用例ID
|
|||
/// </summary>
|
|||
public string ScenarioTestCaseId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
public string ScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 测试用例流程ID
|
|||
/// </summary>
|
|||
public string TestCaseFlowId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 测试用例流程名称
|
|||
/// </summary>
|
|||
public string? TestCaseFlowName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 执行顺序
|
|||
/// </summary>
|
|||
public int ExecutionOrder { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 循环次数
|
|||
/// </summary>
|
|||
public int LoopCount { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建时间
|
|||
/// </summary>
|
|||
public DateTime CreatedAt { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建人
|
|||
/// </summary>
|
|||
public string CreatedBy { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 更新时间
|
|||
/// </summary>
|
|||
public DateTime UpdatedAt { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 更新人
|
|||
/// </summary>
|
|||
public string UpdatedBy { get; set; } = null!; |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using X1.Domain.Common; |
|||
using MediatR; |
|||
|
|||
namespace X1.Application.Features.TestCaseFlow.Queries.GetFormTypeStepTypeMapping; |
|||
|
|||
/// <summary>
|
|||
/// 获取表单类型到步骤类型映射查询
|
|||
/// </summary>
|
|||
public class GetFormTypeStepTypeMappingQuery : IRequest<OperationResult<GetFormTypeStepTypeMappingResponse>> |
|||
{ |
|||
// 无需额外参数,返回所有映射关系
|
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
using MediatR; |
|||
using X1.Domain.Common; |
|||
|
|||
namespace X1.Application.Features.TestCaseFlow.Queries.GetFormTypeStepTypeMapping; |
|||
|
|||
/// <summary>
|
|||
/// 获取表单类型到步骤类型映射查询处理器
|
|||
/// </summary>
|
|||
public class GetFormTypeStepTypeMappingQueryHandler : IRequestHandler<GetFormTypeStepTypeMappingQuery, OperationResult<GetFormTypeStepTypeMappingResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 处理查询
|
|||
/// </summary>
|
|||
/// <param name="request">查询请求</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>操作结果</returns>
|
|||
public async Task<OperationResult<GetFormTypeStepTypeMappingResponse>> Handle(GetFormTypeStepTypeMappingQuery request, CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
// 构建响应对象
|
|||
var response = new GetFormTypeStepTypeMappingResponse(); |
|||
|
|||
// 获取测试流程类型列表
|
|||
response.TestFlowTypes = TestFlowTypeConverter.GetTestFlowTypes().Select(tft => new TestFlowTypeDto |
|||
{ |
|||
Value = tft.Value, |
|||
Name = tft.Name, |
|||
Description = tft.Description |
|||
}).ToList(); |
|||
|
|||
return await Task.FromResult(OperationResult<GetFormTypeStepTypeMappingResponse>.CreateSuccess(response)); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
return await Task.FromResult(OperationResult<GetFormTypeStepTypeMappingResponse>.CreateFailure($"获取测试流程类型失败: {ex.Message}")); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
namespace X1.Application.Features.TestCaseFlow.Queries.GetFormTypeStepTypeMapping; |
|||
|
|||
/// <summary>
|
|||
/// 获取测试流程类型响应
|
|||
/// </summary>
|
|||
public class GetFormTypeStepTypeMappingResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 测试流程类型列表
|
|||
/// </summary>
|
|||
public List<TestFlowTypeDto> TestFlowTypes { get; set; } = new(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 测试流程类型DTO
|
|||
/// </summary>
|
|||
public class TestFlowTypeDto |
|||
{ |
|||
/// <summary>
|
|||
/// 测试流程类型值
|
|||
/// </summary>
|
|||
public int Value { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 测试流程类型名称
|
|||
/// </summary>
|
|||
public string Name { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 测试流程类型描述
|
|||
/// </summary>
|
|||
public string Description { get; set; } = null!; |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using X1.Domain.Common; |
|||
using MediatR; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using X1.Domain.Entities.TestCase; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Commands.CreateTestScenario; |
|||
|
|||
/// <summary>
|
|||
/// 创建测试场景命令
|
|||
/// </summary>
|
|||
public class CreateTestScenarioCommand : IRequest<OperationResult<CreateTestScenarioResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 场景名称
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "场景名称不能为空")] |
|||
[MaxLength(200, ErrorMessage = "场景名称不能超过200个字符")] |
|||
public string ScenarioName { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景类型
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "场景类型不能为空")] |
|||
public ScenarioType Type { get; set; } = ScenarioType.Functional; |
|||
|
|||
/// <summary>
|
|||
/// 场景描述
|
|||
/// </summary>
|
|||
[MaxLength(1000, ErrorMessage = "场景描述不能超过1000个字符")] |
|||
public string? Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } = true; |
|||
} |
|||
@ -0,0 +1,133 @@ |
|||
using MediatR; |
|||
using Microsoft.Extensions.Logging; |
|||
using X1.Domain.Common; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.TestCase; |
|||
using X1.Domain.Repositories.Base; |
|||
using X1.Domain.Services; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Commands.CreateTestScenario; |
|||
|
|||
/// <summary>
|
|||
/// 创建测试场景命令处理器
|
|||
/// </summary>
|
|||
public class CreateTestScenarioCommandHandler : IRequestHandler<CreateTestScenarioCommand, OperationResult<CreateTestScenarioResponse>> |
|||
{ |
|||
private readonly ITestScenarioRepository _testScenarioRepository; |
|||
private readonly ILogger<CreateTestScenarioCommandHandler> _logger; |
|||
private readonly IUnitOfWork _unitOfWork; |
|||
private readonly ICurrentUserService _currentUserService; |
|||
|
|||
/// <summary>
|
|||
/// 初始化命令处理器
|
|||
/// </summary>
|
|||
public CreateTestScenarioCommandHandler( |
|||
ITestScenarioRepository testScenarioRepository, |
|||
ILogger<CreateTestScenarioCommandHandler> logger, |
|||
IUnitOfWork unitOfWork, |
|||
ICurrentUserService currentUserService) |
|||
{ |
|||
_testScenarioRepository = testScenarioRepository; |
|||
_logger = logger; |
|||
_unitOfWork = unitOfWork; |
|||
_currentUserService = currentUserService; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 处理创建测试场景命令
|
|||
/// </summary>
|
|||
public async Task<OperationResult<CreateTestScenarioResponse>> Handle(CreateTestScenarioCommand request, CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogInformation("开始创建测试场景,场景名称: {ScenarioName}", request.ScenarioName); |
|||
|
|||
// 生成场景编码
|
|||
var scenarioCode = await GenerateScenarioCodeAsync(request.Type, cancellationToken); |
|||
|
|||
// 获取当前用户ID
|
|||
var currentUserId = _currentUserService.GetCurrentUserId(); |
|||
if (string.IsNullOrEmpty(currentUserId)) |
|||
{ |
|||
_logger.LogError("无法获取当前用户ID,用户可能未认证"); |
|||
return OperationResult<CreateTestScenarioResponse>.CreateFailure("用户未认证,无法创建测试场景"); |
|||
} |
|||
|
|||
// 创建测试场景实体
|
|||
var testScenario = TestScenario.Create( |
|||
scenarioCode: scenarioCode, |
|||
scenarioName: request.ScenarioName, |
|||
type: request.Type, |
|||
description: request.Description, |
|||
isEnabled: request.IsEnabled, |
|||
createdBy: currentUserId); |
|||
|
|||
// 保存测试场景
|
|||
await _testScenarioRepository.AddAsync(testScenario, cancellationToken); |
|||
|
|||
// 保存更改到数据库
|
|||
await _unitOfWork.SaveChangesAsync(cancellationToken); |
|||
|
|||
// 构建响应
|
|||
var response = new CreateTestScenarioResponse |
|||
{ |
|||
TestScenarioId = testScenario.Id, |
|||
ScenarioCode = testScenario.ScenarioCode, |
|||
ScenarioName = testScenario.ScenarioName, |
|||
Type = testScenario.Type.ToString(), |
|||
Description = testScenario.Description, |
|||
IsEnabled = testScenario.IsEnabled, |
|||
CreatedAt = testScenario.CreatedAt, |
|||
CreatedBy = testScenario.CreatedBy |
|||
}; |
|||
|
|||
_logger.LogInformation("测试场景创建成功,场景ID: {TestScenarioId}, 场景编码: {ScenarioCode}, 场景名称: {ScenarioName}", |
|||
testScenario.Id, testScenario.ScenarioCode, testScenario.ScenarioName); |
|||
return OperationResult<CreateTestScenarioResponse>.CreateSuccess(response); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "创建测试场景时发生错误,场景名称: {ScenarioName}", request.ScenarioName); |
|||
return OperationResult<CreateTestScenarioResponse>.CreateFailure($"创建测试场景时发生错误: {ex.Message}"); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 生成场景编码
|
|||
/// </summary>
|
|||
private async Task<string> GenerateScenarioCodeAsync(ScenarioType type, CancellationToken cancellationToken) |
|||
{ |
|||
var prefix = type switch |
|||
{ |
|||
ScenarioType.Functional => "FUNC", |
|||
ScenarioType.Performance => "PERF", |
|||
ScenarioType.Security => "SEC", |
|||
ScenarioType.Integration => "INT", |
|||
ScenarioType.Regression => "REG", |
|||
_ => "GEN" |
|||
}; |
|||
|
|||
var date = DateTime.Now.ToString("yyyyMMdd"); |
|||
var random = new Random(); |
|||
var suffix = random.Next(1000, 9999).ToString(); |
|||
|
|||
var scenarioCode = $"{prefix}_{date}_{suffix}"; |
|||
|
|||
// 检查生成的编码是否已存在,如果存在则重新生成
|
|||
var maxAttempts = 10; |
|||
var attempts = 0; |
|||
while (await _testScenarioRepository.ExistsByScenarioCodeAsync(scenarioCode, cancellationToken: cancellationToken) && attempts < maxAttempts) |
|||
{ |
|||
suffix = random.Next(1000, 9999).ToString(); |
|||
scenarioCode = $"{prefix}_{date}_{suffix}"; |
|||
attempts++; |
|||
} |
|||
|
|||
if (attempts >= maxAttempts) |
|||
{ |
|||
throw new InvalidOperationException("无法生成唯一的场景编码,请稍后重试"); |
|||
} |
|||
|
|||
return scenarioCode; |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
namespace X1.Application.Features.TestScenarios.Commands.CreateTestScenario; |
|||
|
|||
/// <summary>
|
|||
/// 创建测试场景响应
|
|||
/// </summary>
|
|||
public class CreateTestScenarioResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
public string TestScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景编码
|
|||
/// </summary>
|
|||
public string ScenarioCode { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景名称
|
|||
/// </summary>
|
|||
public string ScenarioName { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景类型
|
|||
/// </summary>
|
|||
public string Type { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景描述
|
|||
/// </summary>
|
|||
public string? Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建时间
|
|||
/// </summary>
|
|||
public DateTime CreatedAt { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建人
|
|||
/// </summary>
|
|||
public string CreatedBy { get; set; } = null!; |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using X1.Domain.Common; |
|||
using MediatR; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Commands.DeleteTestScenario; |
|||
|
|||
/// <summary>
|
|||
/// 删除测试场景命令
|
|||
/// </summary>
|
|||
public class DeleteTestScenarioCommand : IRequest<OperationResult<bool>> |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "场景ID不能为空")] |
|||
public string TestScenarioId { get; set; } = null!; |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
using MediatR; |
|||
using Microsoft.Extensions.Logging; |
|||
using X1.Domain.Common; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.TestCase; |
|||
using X1.Domain.Repositories.Base; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Commands.DeleteTestScenario; |
|||
|
|||
/// <summary>
|
|||
/// 删除测试场景命令处理器
|
|||
/// </summary>
|
|||
public class DeleteTestScenarioCommandHandler : IRequestHandler<DeleteTestScenarioCommand, OperationResult<bool>> |
|||
{ |
|||
private readonly ITestScenarioRepository _testScenarioRepository; |
|||
private readonly IScenarioTestCaseRepository _scenarioTestCaseRepository; |
|||
private readonly ILogger<DeleteTestScenarioCommandHandler> _logger; |
|||
private readonly IUnitOfWork _unitOfWork; |
|||
|
|||
/// <summary>
|
|||
/// 初始化命令处理器
|
|||
/// </summary>
|
|||
public DeleteTestScenarioCommandHandler( |
|||
ITestScenarioRepository testScenarioRepository, |
|||
IScenarioTestCaseRepository scenarioTestCaseRepository, |
|||
ILogger<DeleteTestScenarioCommandHandler> logger, |
|||
IUnitOfWork unitOfWork) |
|||
{ |
|||
_testScenarioRepository = testScenarioRepository; |
|||
_scenarioTestCaseRepository = scenarioTestCaseRepository; |
|||
_logger = logger; |
|||
_unitOfWork = unitOfWork; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 处理删除测试场景命令
|
|||
/// </summary>
|
|||
public async Task<OperationResult<bool>> Handle(DeleteTestScenarioCommand request, CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogInformation("开始删除测试场景,场景ID: {TestScenarioId}", request.TestScenarioId); |
|||
|
|||
// 查找测试场景
|
|||
var testScenario = await _testScenarioRepository.GetByIdAsync(request.TestScenarioId, cancellationToken: cancellationToken); |
|||
if (testScenario == null) |
|||
{ |
|||
_logger.LogWarning("测试场景不存在,场景ID: {TestScenarioId}", request.TestScenarioId); |
|||
return OperationResult<bool>.CreateFailure($"测试场景不存在,场景ID: {request.TestScenarioId}"); |
|||
} |
|||
|
|||
// 检查是否有关联的测试用例
|
|||
var testCaseCount = await _scenarioTestCaseRepository.GetCountByScenarioIdAsync(request.TestScenarioId, cancellationToken); |
|||
if (testCaseCount > 0) |
|||
{ |
|||
_logger.LogWarning("测试场景存在关联的测试用例,无法删除,场景ID: {TestScenarioId}, 测试用例数量: {TestCaseCount}", |
|||
request.TestScenarioId, testCaseCount); |
|||
return OperationResult<bool>.CreateFailure($"测试场景存在 {testCaseCount} 个关联的测试用例,无法删除"); |
|||
} |
|||
|
|||
// 删除测试场景
|
|||
_testScenarioRepository.Delete(testScenario); |
|||
|
|||
// 保存更改到数据库
|
|||
await _unitOfWork.SaveChangesAsync(cancellationToken); |
|||
|
|||
_logger.LogInformation("测试场景删除成功,场景ID: {TestScenarioId}, 场景编码: {ScenarioCode}", |
|||
testScenario.Id, testScenario.ScenarioCode); |
|||
return OperationResult<bool>.CreateSuccess(true); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "删除测试场景时发生错误,场景ID: {TestScenarioId}", request.TestScenarioId); |
|||
return OperationResult<bool>.CreateFailure($"删除测试场景时发生错误: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using X1.Domain.Common; |
|||
using MediatR; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Commands.UpdateTestScenario; |
|||
|
|||
/// <summary>
|
|||
/// 更新测试场景命令
|
|||
/// </summary>
|
|||
public class UpdateTestScenarioCommand : IRequest<OperationResult<UpdateTestScenarioResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "场景ID不能为空")] |
|||
public string TestScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景描述
|
|||
/// </summary>
|
|||
[MaxLength(1000, ErrorMessage = "场景描述不能超过1000个字符")] |
|||
public string? Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } = true; |
|||
} |
|||
@ -0,0 +1,92 @@ |
|||
using MediatR; |
|||
using Microsoft.Extensions.Logging; |
|||
using X1.Domain.Common; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.TestCase; |
|||
using X1.Domain.Repositories.Base; |
|||
using X1.Domain.Services; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Commands.UpdateTestScenario; |
|||
|
|||
/// <summary>
|
|||
/// 更新测试场景命令处理器
|
|||
/// </summary>
|
|||
public class UpdateTestScenarioCommandHandler : IRequestHandler<UpdateTestScenarioCommand, OperationResult<UpdateTestScenarioResponse>> |
|||
{ |
|||
private readonly ITestScenarioRepository _testScenarioRepository; |
|||
private readonly ILogger<UpdateTestScenarioCommandHandler> _logger; |
|||
private readonly IUnitOfWork _unitOfWork; |
|||
private readonly ICurrentUserService _currentUserService; |
|||
|
|||
/// <summary>
|
|||
/// 初始化命令处理器
|
|||
/// </summary>
|
|||
public UpdateTestScenarioCommandHandler( |
|||
ITestScenarioRepository testScenarioRepository, |
|||
ILogger<UpdateTestScenarioCommandHandler> logger, |
|||
IUnitOfWork unitOfWork, |
|||
ICurrentUserService currentUserService) |
|||
{ |
|||
_testScenarioRepository = testScenarioRepository; |
|||
_logger = logger; |
|||
_unitOfWork = unitOfWork; |
|||
_currentUserService = currentUserService; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 处理更新测试场景命令
|
|||
/// </summary>
|
|||
public async Task<OperationResult<UpdateTestScenarioResponse>> Handle(UpdateTestScenarioCommand request, CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogInformation("开始更新测试场景,场景ID: {TestScenarioId}", request.TestScenarioId); |
|||
|
|||
// 获取当前用户ID
|
|||
var currentUserId = _currentUserService.GetCurrentUserId(); |
|||
if (string.IsNullOrEmpty(currentUserId)) |
|||
{ |
|||
_logger.LogError("无法获取当前用户ID,用户可能未认证"); |
|||
return OperationResult<UpdateTestScenarioResponse>.CreateFailure("用户未认证,无法更新测试场景"); |
|||
} |
|||
|
|||
// 查找测试场景
|
|||
var testScenario = await _testScenarioRepository.GetByIdAsync(request.TestScenarioId, cancellationToken:cancellationToken); |
|||
if (testScenario == null) |
|||
{ |
|||
_logger.LogWarning("测试场景不存在,场景ID: {TestScenarioId}", request.TestScenarioId); |
|||
return OperationResult<UpdateTestScenarioResponse>.CreateFailure($"测试场景不存在,场景ID: {request.TestScenarioId}"); |
|||
} |
|||
|
|||
// 更新测试场景(只允许更新描述和启用状态)
|
|||
testScenario.UpdateDescription(request.Description); |
|||
testScenario.SetEnabled(request.IsEnabled); |
|||
testScenario.UpdateAuditInfo(currentUserId); |
|||
|
|||
// 保存更改到数据库
|
|||
await _unitOfWork.SaveChangesAsync(cancellationToken); |
|||
|
|||
// 构建响应
|
|||
var response = new UpdateTestScenarioResponse |
|||
{ |
|||
TestScenarioId = testScenario.Id, |
|||
ScenarioCode = testScenario.ScenarioCode, |
|||
ScenarioName = testScenario.ScenarioName, |
|||
Type = testScenario.Type.ToString(), |
|||
Description = testScenario.Description, |
|||
IsEnabled = testScenario.IsEnabled, |
|||
UpdatedAt = testScenario.UpdatedAt, |
|||
UpdatedBy = testScenario.UpdatedBy |
|||
}; |
|||
|
|||
_logger.LogInformation("测试场景更新成功,场景ID: {TestScenarioId}, 场景编码: {ScenarioCode}", |
|||
testScenario.Id, testScenario.ScenarioCode); |
|||
return OperationResult<UpdateTestScenarioResponse>.CreateSuccess(response); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "更新测试场景时发生错误,场景ID: {TestScenarioId}", request.TestScenarioId); |
|||
return OperationResult<UpdateTestScenarioResponse>.CreateFailure($"更新测试场景时发生错误: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
namespace X1.Application.Features.TestScenarios.Commands.UpdateTestScenario; |
|||
|
|||
/// <summary>
|
|||
/// 更新测试场景响应
|
|||
/// </summary>
|
|||
public class UpdateTestScenarioResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
public string TestScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景编码
|
|||
/// </summary>
|
|||
public string ScenarioCode { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景名称
|
|||
/// </summary>
|
|||
public string ScenarioName { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景类型
|
|||
/// </summary>
|
|||
public string Type { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景描述
|
|||
/// </summary>
|
|||
public string? Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 更新时间
|
|||
/// </summary>
|
|||
public DateTime UpdatedAt { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 更新人
|
|||
/// </summary>
|
|||
public string UpdatedBy { get; set; } = null!; |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using X1.Domain.Common; |
|||
using MediatR; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Queries.GetTestScenarioById; |
|||
|
|||
/// <summary>
|
|||
/// 根据ID获取测试场景查询
|
|||
/// </summary>
|
|||
public class GetTestScenarioByIdQuery : IRequest<OperationResult<GetTestScenarioByIdResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "场景ID不能为空")] |
|||
public string TestScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 是否包含测试用例
|
|||
/// </summary>
|
|||
public bool IncludeTestCases { get; set; } = false; |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
using MediatR; |
|||
using Microsoft.Extensions.Logging; |
|||
using X1.Domain.Common; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.TestCase; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Queries.GetTestScenarioById; |
|||
|
|||
/// <summary>
|
|||
/// 根据ID获取测试场景查询处理器
|
|||
/// </summary>
|
|||
public class GetTestScenarioByIdQueryHandler : IRequestHandler<GetTestScenarioByIdQuery, OperationResult<GetTestScenarioByIdResponse>> |
|||
{ |
|||
private readonly ITestScenarioRepository _testScenarioRepository; |
|||
private readonly ILogger<GetTestScenarioByIdQueryHandler> _logger; |
|||
|
|||
/// <summary>
|
|||
/// 初始化查询处理器
|
|||
/// </summary>
|
|||
public GetTestScenarioByIdQueryHandler( |
|||
ITestScenarioRepository testScenarioRepository, |
|||
ILogger<GetTestScenarioByIdQueryHandler> logger) |
|||
{ |
|||
_testScenarioRepository = testScenarioRepository; |
|||
_logger = logger; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 处理根据ID获取测试场景查询
|
|||
/// </summary>
|
|||
public async Task<OperationResult<GetTestScenarioByIdResponse>> Handle(GetTestScenarioByIdQuery request, CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogInformation("开始获取测试场景详情,场景ID: {TestScenarioId}, 包含测试用例: {IncludeTestCases}", |
|||
request.TestScenarioId, request.IncludeTestCases); |
|||
|
|||
// 获取测试场景
|
|||
TestScenario? testScenario; |
|||
if (request.IncludeTestCases) |
|||
{ |
|||
testScenario = await _testScenarioRepository.GetWithTestCasesAsync(request.TestScenarioId, cancellationToken); |
|||
} |
|||
else |
|||
{ |
|||
testScenario = await _testScenarioRepository.GetByIdAsync(request.TestScenarioId, cancellationToken: cancellationToken); |
|||
} |
|||
|
|||
if (testScenario == null) |
|||
{ |
|||
_logger.LogWarning("测试场景不存在,场景ID: {TestScenarioId}", request.TestScenarioId); |
|||
return OperationResult<GetTestScenarioByIdResponse>.CreateFailure($"测试场景不存在,场景ID: {request.TestScenarioId}"); |
|||
} |
|||
|
|||
// 构建响应
|
|||
var response = new GetTestScenarioByIdResponse |
|||
{ |
|||
TestScenarioId = testScenario.Id, |
|||
ScenarioCode = testScenario.ScenarioCode, |
|||
ScenarioName = testScenario.ScenarioName, |
|||
Type = testScenario.Type.ToString(), |
|||
Description = testScenario.Description, |
|||
IsEnabled = testScenario.IsEnabled, |
|||
CreatedAt = testScenario.CreatedAt, |
|||
CreatedBy = testScenario.CreatedBy, |
|||
UpdatedAt = testScenario.UpdatedAt, |
|||
UpdatedBy = testScenario.UpdatedBy |
|||
}; |
|||
|
|||
// 如果包含测试用例,则添加测试用例信息
|
|||
if (request.IncludeTestCases && testScenario.ScenarioTestCases != null) |
|||
{ |
|||
response.TestCases = testScenario.ScenarioTestCases |
|||
.OrderBy(x => x.ExecutionOrder) |
|||
.Select(x => new ScenarioTestCaseDto |
|||
{ |
|||
ScenarioTestCaseId = x.Id, |
|||
TestCaseFlowId = x.TestCaseFlowId, |
|||
TestCaseFlowName = x.TestCaseFlow?.Name ?? "未知", |
|||
ExecutionOrder = x.ExecutionOrder, |
|||
LoopCount = x.LoopCount, |
|||
IsEnabled = x.IsEnabled, |
|||
CreatedAt = x.CreatedAt, |
|||
CreatedBy = x.CreatedBy |
|||
}) |
|||
.ToList(); |
|||
} |
|||
|
|||
_logger.LogInformation("获取测试场景详情成功,场景ID: {TestScenarioId}, 场景编码: {ScenarioCode}", |
|||
testScenario.Id, testScenario.ScenarioCode); |
|||
return OperationResult<GetTestScenarioByIdResponse>.CreateSuccess(response); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "获取测试场景详情时发生错误,场景ID: {TestScenarioId}", request.TestScenarioId); |
|||
return OperationResult<GetTestScenarioByIdResponse>.CreateFailure($"获取测试场景详情时发生错误: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,108 @@ |
|||
namespace X1.Application.Features.TestScenarios.Queries.GetTestScenarioById; |
|||
|
|||
/// <summary>
|
|||
/// 根据ID获取测试场景响应
|
|||
/// </summary>
|
|||
public class GetTestScenarioByIdResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
public string TestScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景编码
|
|||
/// </summary>
|
|||
public string ScenarioCode { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景名称
|
|||
/// </summary>
|
|||
public string ScenarioName { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景类型
|
|||
/// </summary>
|
|||
public string Type { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景描述
|
|||
/// </summary>
|
|||
public string? Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建时间
|
|||
/// </summary>
|
|||
public DateTime CreatedAt { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建人
|
|||
/// </summary>
|
|||
public string CreatedBy { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 更新时间
|
|||
/// </summary>
|
|||
public DateTime UpdatedAt { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 更新人
|
|||
/// </summary>
|
|||
public string UpdatedBy { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 测试用例列表
|
|||
/// </summary>
|
|||
public List<ScenarioTestCaseDto>? TestCases { get; set; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 场景测试用例数据传输对象
|
|||
/// </summary>
|
|||
public class ScenarioTestCaseDto |
|||
{ |
|||
/// <summary>
|
|||
/// 场景测试用例ID
|
|||
/// </summary>
|
|||
public string ScenarioTestCaseId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 测试用例流程ID
|
|||
/// </summary>
|
|||
public string TestCaseFlowId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 测试用例流程名称
|
|||
/// </summary>
|
|||
public string TestCaseFlowName { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 执行顺序
|
|||
/// </summary>
|
|||
public int ExecutionOrder { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 循环次数
|
|||
/// </summary>
|
|||
public int LoopCount { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建时间
|
|||
/// </summary>
|
|||
public DateTime CreatedAt { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建人
|
|||
/// </summary>
|
|||
public string CreatedBy { get; set; } = null!; |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using X1.Domain.Common; |
|||
using MediatR; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using X1.Domain.Entities.TestCase; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Queries.GetTestScenarios; |
|||
|
|||
/// <summary>
|
|||
/// 获取测试场景列表查询
|
|||
/// </summary>
|
|||
public class GetTestScenariosQuery : IRequest<OperationResult<GetTestScenariosResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 页码
|
|||
/// </summary>
|
|||
[Range(1, int.MaxValue, ErrorMessage = "页码必须大于0")] |
|||
public int PageNumber { get; set; } = 1; |
|||
|
|||
/// <summary>
|
|||
/// 每页数量
|
|||
/// </summary>
|
|||
[Range(1, 1000, ErrorMessage = "每页数量必须在1-1000之间")] |
|||
public int PageSize { get; set; } = 10; |
|||
|
|||
/// <summary>
|
|||
/// 搜索关键词
|
|||
/// </summary>
|
|||
[MaxLength(100)] |
|||
public string? SearchTerm { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 场景类型
|
|||
/// </summary>
|
|||
public ScenarioType? Type { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否只获取启用的场景
|
|||
/// </summary>
|
|||
public bool? IsEnabled { get; set; } |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
using MediatR; |
|||
using Microsoft.Extensions.Logging; |
|||
using X1.Domain.Common; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.TestCase; |
|||
|
|||
namespace X1.Application.Features.TestScenarios.Queries.GetTestScenarios; |
|||
|
|||
/// <summary>
|
|||
/// 获取测试场景列表查询处理器
|
|||
/// </summary>
|
|||
public class GetTestScenariosQueryHandler : IRequestHandler<GetTestScenariosQuery, OperationResult<GetTestScenariosResponse>> |
|||
{ |
|||
private readonly ITestScenarioRepository _testScenarioRepository; |
|||
private readonly ILogger<GetTestScenariosQueryHandler> _logger; |
|||
|
|||
/// <summary>
|
|||
/// 初始化查询处理器
|
|||
/// </summary>
|
|||
public GetTestScenariosQueryHandler( |
|||
ITestScenarioRepository testScenarioRepository, |
|||
ILogger<GetTestScenariosQueryHandler> logger) |
|||
{ |
|||
_testScenarioRepository = testScenarioRepository; |
|||
_logger = logger; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 处理获取测试场景列表查询
|
|||
/// </summary>
|
|||
public async Task<OperationResult<GetTestScenariosResponse>> Handle(GetTestScenariosQuery request, CancellationToken cancellationToken) |
|||
{ |
|||
try |
|||
{ |
|||
_logger.LogInformation("开始获取测试场景列表,页码: {PageNumber}, 每页数量: {PageSize}", |
|||
request.PageNumber, request.PageSize); |
|||
|
|||
// 获取所有测试场景
|
|||
var allScenarios = await _testScenarioRepository.GetAllAsync(cancellationToken:cancellationToken); |
|||
|
|||
// 应用过滤条件
|
|||
var filteredScenarios = allScenarios.AsQueryable(); |
|||
|
|||
// 按类型过滤
|
|||
if (request.Type.HasValue) |
|||
{ |
|||
filteredScenarios = filteredScenarios.Where(x => x.Type == request.Type.Value); |
|||
} |
|||
|
|||
// 按启用状态过滤
|
|||
if (request.IsEnabled.HasValue) |
|||
{ |
|||
filteredScenarios = filteredScenarios.Where(x => x.IsEnabled == request.IsEnabled.Value); |
|||
} |
|||
|
|||
// 按搜索关键词过滤
|
|||
if (!string.IsNullOrWhiteSpace(request.SearchTerm)) |
|||
{ |
|||
var searchTerm = request.SearchTerm.ToLower(); |
|||
filteredScenarios = filteredScenarios.Where(x => |
|||
x.ScenarioCode.ToLower().Contains(searchTerm) || |
|||
x.ScenarioName.ToLower().Contains(searchTerm) || |
|||
(x.Description != null && x.Description.ToLower().Contains(searchTerm))); |
|||
} |
|||
|
|||
// 计算总数
|
|||
var totalCount = filteredScenarios.Count(); |
|||
|
|||
// 分页
|
|||
var pagedScenarios = filteredScenarios |
|||
.OrderBy(x => x.ScenarioCode) |
|||
.Skip((request.PageNumber - 1) * request.PageSize) |
|||
.Take(request.PageSize) |
|||
.ToList(); |
|||
|
|||
// 转换为DTO
|
|||
var scenarioDtos = pagedScenarios.Select(x => new TestScenarioDto |
|||
{ |
|||
TestScenarioId = x.Id, |
|||
ScenarioCode = x.ScenarioCode, |
|||
ScenarioName = x.ScenarioName, |
|||
Type = x.Type.ToString(), |
|||
Description = x.Description, |
|||
IsEnabled = x.IsEnabled, |
|||
CreatedAt = x.CreatedAt, |
|||
CreatedBy = x.CreatedBy, |
|||
UpdatedAt = x.UpdatedAt, |
|||
UpdatedBy = x.UpdatedBy |
|||
}).ToList(); |
|||
|
|||
// 构建响应
|
|||
var response = new GetTestScenariosResponse |
|||
{ |
|||
TestScenarios = scenarioDtos, |
|||
TotalCount = totalCount, |
|||
PageNumber = request.PageNumber, |
|||
PageSize = request.PageSize, |
|||
TotalPages = (int)Math.Ceiling((double)totalCount / request.PageSize) |
|||
}; |
|||
|
|||
_logger.LogInformation("获取测试场景列表成功,总数: {TotalCount}, 当前页数量: {CurrentPageCount}", |
|||
totalCount, scenarioDtos.Count); |
|||
return OperationResult<GetTestScenariosResponse>.CreateSuccess(response); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "获取测试场景列表时发生错误"); |
|||
return OperationResult<GetTestScenariosResponse>.CreateFailure($"获取测试场景列表时发生错误: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
namespace X1.Application.Features.TestScenarios.Queries.GetTestScenarios; |
|||
|
|||
/// <summary>
|
|||
/// 获取测试场景列表响应
|
|||
/// </summary>
|
|||
public class GetTestScenariosResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 测试场景列表
|
|||
/// </summary>
|
|||
public List<TestScenarioDto> TestScenarios { get; set; } = new(); |
|||
|
|||
/// <summary>
|
|||
/// 总数量
|
|||
/// </summary>
|
|||
public int TotalCount { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 页码
|
|||
/// </summary>
|
|||
public int PageNumber { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 每页数量
|
|||
/// </summary>
|
|||
public int PageSize { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 总页数
|
|||
/// </summary>
|
|||
public int TotalPages { get; set; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 测试场景数据传输对象
|
|||
/// </summary>
|
|||
public class TestScenarioDto |
|||
{ |
|||
/// <summary>
|
|||
/// 场景ID
|
|||
/// </summary>
|
|||
public string TestScenarioId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景编码
|
|||
/// </summary>
|
|||
public string ScenarioCode { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景名称
|
|||
/// </summary>
|
|||
public string ScenarioName { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景类型
|
|||
/// </summary>
|
|||
public string Type { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 场景描述
|
|||
/// </summary>
|
|||
public string? Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建时间
|
|||
/// </summary>
|
|||
public DateTime CreatedAt { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建人
|
|||
/// </summary>
|
|||
public string CreatedBy { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 更新时间
|
|||
/// </summary>
|
|||
public DateTime UpdatedAt { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 更新人
|
|||
/// </summary>
|
|||
public string UpdatedBy { get; set; } = null!; |
|||
} |
|||
@ -0,0 +1,231 @@ |
|||
using X1.Domain.Entities.TestCase; |
|||
using System.ComponentModel; |
|||
using System.Reflection; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace X1.Domain.Common; |
|||
|
|||
/// <summary>
|
|||
/// 测试流程类型转换器
|
|||
/// </summary>
|
|||
public static class TestFlowTypeConverter |
|||
{ |
|||
/// <summary>
|
|||
/// 根据测试流程类型获取推荐的表单类型
|
|||
/// </summary>
|
|||
/// <param name="testFlowType">测试流程类型</param>
|
|||
/// <returns>推荐的表单类型</returns>
|
|||
public static FormType GetRecommendedFormType(TestFlowType testFlowType) |
|||
{ |
|||
return testFlowType switch |
|||
{ |
|||
TestFlowType.Registration => FormType.DeviceRegistrationForm, |
|||
TestFlowType.Voice => FormType.VoiceCallForm, |
|||
TestFlowType.Data => FormType.NetworkPerformanceForm, |
|||
_ => FormType.NoForm |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据测试流程类型获取推荐的步骤类型
|
|||
/// </summary>
|
|||
/// <param name="testFlowType">测试流程类型</param>
|
|||
/// <returns>推荐的步骤类型</returns>
|
|||
public static CaseStepType GetRecommendedStepType(TestFlowType testFlowType) |
|||
{ |
|||
return testFlowType switch |
|||
{ |
|||
TestFlowType.Registration => CaseStepType.Process, |
|||
TestFlowType.Voice => CaseStepType.Process, |
|||
TestFlowType.Data => CaseStepType.Process, |
|||
_ => CaseStepType.Process |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取测试流程类型与表单类型的映射关系
|
|||
/// </summary>
|
|||
/// <returns>测试流程类型到表单类型的映射字典</returns>
|
|||
public static Dictionary<TestFlowType, FormType> GetTestFlowTypeToFormTypeMapping() |
|||
{ |
|||
return new Dictionary<TestFlowType, FormType> |
|||
{ |
|||
{ TestFlowType.Registration, FormType.DeviceRegistrationForm }, |
|||
{ TestFlowType.Voice, FormType.VoiceCallForm }, |
|||
{ TestFlowType.Data, FormType.NetworkPerformanceForm } |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取测试流程类型与步骤类型的映射关系
|
|||
/// </summary>
|
|||
/// <returns>测试流程类型到步骤类型的映射字典</returns>
|
|||
public static Dictionary<TestFlowType, CaseStepType> GetTestFlowTypeToStepTypeMapping() |
|||
{ |
|||
return new Dictionary<TestFlowType, CaseStepType> |
|||
{ |
|||
{ TestFlowType.Registration, CaseStepType.Process }, |
|||
{ TestFlowType.Voice, CaseStepType.Process }, |
|||
{ TestFlowType.Data, CaseStepType.Process } |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取表单类型支持的测试流程类型列表
|
|||
/// </summary>
|
|||
/// <param name="formType">表单类型</param>
|
|||
/// <returns>支持的测试流程类型列表</returns>
|
|||
public static List<TestFlowType> GetSupportedTestFlowTypes(FormType formType) |
|||
{ |
|||
return formType switch |
|||
{ |
|||
FormType.NoForm => new List<TestFlowType> { TestFlowType.Registration, TestFlowType.Voice, TestFlowType.Data }, |
|||
FormType.DeviceRegistrationForm => new List<TestFlowType> { TestFlowType.Registration }, |
|||
FormType.VoiceCallForm => new List<TestFlowType> { TestFlowType.Voice }, |
|||
FormType.NetworkPerformanceForm => new List<TestFlowType> { TestFlowType.Data }, |
|||
FormType.NetworkConnectivityForm => new List<TestFlowType> { TestFlowType.Data }, |
|||
_ => new List<TestFlowType> { TestFlowType.Registration, TestFlowType.Voice, TestFlowType.Data } |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取步骤类型支持的测试流程类型列表
|
|||
/// </summary>
|
|||
/// <param name="stepType">步骤类型</param>
|
|||
/// <returns>支持的测试流程类型列表</returns>
|
|||
public static List<TestFlowType> GetSupportedTestFlowTypes(CaseStepType stepType) |
|||
{ |
|||
return stepType switch |
|||
{ |
|||
CaseStepType.Start => new List<TestFlowType> { TestFlowType.Registration, TestFlowType.Voice, TestFlowType.Data }, |
|||
CaseStepType.End => new List<TestFlowType> { TestFlowType.Registration, TestFlowType.Voice, TestFlowType.Data }, |
|||
CaseStepType.Process => new List<TestFlowType> { TestFlowType.Registration, TestFlowType.Voice, TestFlowType.Data }, |
|||
CaseStepType.Decision => new List<TestFlowType> { TestFlowType.Registration, TestFlowType.Voice, TestFlowType.Data }, |
|||
_ => new List<TestFlowType> { TestFlowType.Registration, TestFlowType.Voice, TestFlowType.Data } |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查测试流程类型是否与表单类型兼容
|
|||
/// </summary>
|
|||
/// <param name="testFlowType">测试流程类型</param>
|
|||
/// <param name="formType">表单类型</param>
|
|||
/// <returns>是否兼容</returns>
|
|||
public static bool IsCompatibleWithFormType(TestFlowType testFlowType, FormType formType) |
|||
{ |
|||
var supportedTestFlowTypes = GetSupportedTestFlowTypes(formType); |
|||
return supportedTestFlowTypes.Contains(testFlowType); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查测试流程类型是否与步骤类型兼容
|
|||
/// </summary>
|
|||
/// <param name="testFlowType">测试流程类型</param>
|
|||
/// <param name="stepType">步骤类型</param>
|
|||
/// <returns>是否兼容</returns>
|
|||
public static bool IsCompatibleWithStepType(TestFlowType testFlowType, CaseStepType stepType) |
|||
{ |
|||
var supportedTestFlowTypes = GetSupportedTestFlowTypes(stepType); |
|||
return supportedTestFlowTypes.Contains(testFlowType); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取所有测试流程类型及其描述
|
|||
/// </summary>
|
|||
/// <returns>测试流程类型描述字典</returns>
|
|||
public static Dictionary<TestFlowType, string> GetTestFlowTypeDescriptions() |
|||
{ |
|||
return new Dictionary<TestFlowType, string> |
|||
{ |
|||
{ TestFlowType.Registration, TestFlowType.Registration.GetDisplayName() }, |
|||
{ TestFlowType.Voice, TestFlowType.Voice.GetDisplayName() }, |
|||
{ TestFlowType.Data, TestFlowType.Data.GetDisplayName() } |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取所有测试流程类型
|
|||
/// </summary>
|
|||
/// <returns>测试流程类型列表</returns>
|
|||
public static List<EnumValueObject> GetTestFlowTypes() |
|||
{ |
|||
var testFlowTypes = new List<EnumValueObject>(); |
|||
|
|||
foreach (TestFlowType testFlowType in Enum.GetValues(typeof(TestFlowType))) |
|||
{ |
|||
var fieldInfo = typeof(TestFlowType).GetField(testFlowType.ToString()); |
|||
if (fieldInfo != null) |
|||
{ |
|||
var displayAttribute = fieldInfo.GetCustomAttribute<DisplayAttribute>(); |
|||
var descriptionAttribute = fieldInfo.GetCustomAttribute<DescriptionAttribute>(); |
|||
|
|||
var name = displayAttribute?.Name ?? testFlowType.ToString(); |
|||
var description = descriptionAttribute?.Description ?? testFlowType.ToString(); |
|||
|
|||
testFlowTypes.Add(new EnumValueObject |
|||
{ |
|||
Value = (int)testFlowType, |
|||
Name = name, |
|||
Description = description |
|||
}); |
|||
} |
|||
} |
|||
|
|||
return testFlowTypes; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据测试流程类型获取推荐的步骤映射
|
|||
/// </summary>
|
|||
/// <param name="testFlowType">测试流程类型</param>
|
|||
/// <returns>推荐的步骤映射列表</returns>
|
|||
public static List<StepMapping> GetRecommendedStepMappings(TestFlowType testFlowType) |
|||
{ |
|||
return testFlowType switch |
|||
{ |
|||
TestFlowType.Registration => new List<StepMapping> |
|||
{ |
|||
StepMapping.StartFlow, |
|||
StepMapping.ImsiRegistration, |
|||
StepMapping.EndFlow |
|||
}, |
|||
TestFlowType.Voice => new List<StepMapping> |
|||
{ |
|||
StepMapping.StartFlow, |
|||
StepMapping.MoCall, |
|||
StepMapping.MtCall, |
|||
StepMapping.HangUpCall, |
|||
StepMapping.EndFlow |
|||
}, |
|||
TestFlowType.Data => new List<StepMapping> |
|||
{ |
|||
StepMapping.StartFlow, |
|||
StepMapping.PingTest, |
|||
StepMapping.IperfTest, |
|||
StepMapping.EndFlow |
|||
}, |
|||
_ => new List<StepMapping> { StepMapping.None } |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据步骤映射获取对应的测试流程类型
|
|||
/// </summary>
|
|||
/// <param name="mapping">步骤映射</param>
|
|||
/// <returns>对应的测试流程类型</returns>
|
|||
public static TestFlowType GetTestFlowTypeByStepMapping(StepMapping mapping) |
|||
{ |
|||
return mapping switch |
|||
{ |
|||
StepMapping.StartFlow => TestFlowType.Registration, |
|||
StepMapping.EndFlow => TestFlowType.Registration, |
|||
StepMapping.ImsiRegistration => TestFlowType.Registration, |
|||
StepMapping.MoCall => TestFlowType.Voice, |
|||
StepMapping.MtCall => TestFlowType.Voice, |
|||
StepMapping.HangUpCall => TestFlowType.Voice, |
|||
StepMapping.PingTest => TestFlowType.Data, |
|||
StepMapping.IperfTest => TestFlowType.Data, |
|||
_ => TestFlowType.Registration |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.Base; |
|||
|
|||
namespace X1.Domain.Repositories.TestCase |
|||
{ |
|||
/// <summary>
|
|||
/// 场景测试用例仓储接口
|
|||
/// </summary>
|
|||
public interface IScenarioTestCaseRepository : IBaseRepository<ScenarioTestCase> |
|||
{ |
|||
/// <summary>
|
|||
/// 根据场景ID获取测试用例列表
|
|||
/// </summary>
|
|||
/// <param name="scenarioId">场景ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>测试用例列表</returns>
|
|||
Task<IEnumerable<ScenarioTestCase>> GetByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据测试用例流程ID获取场景测试用例列表
|
|||
/// </summary>
|
|||
/// <param name="testCaseFlowId">测试用例流程ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>场景测试用例列表</returns>
|
|||
Task<IEnumerable<ScenarioTestCase>> GetByTestCaseFlowIdAsync(string testCaseFlowId, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID获取启用的测试用例列表
|
|||
/// </summary>
|
|||
/// <param name="scenarioId">场景ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>启用的测试用例列表</returns>
|
|||
Task<IEnumerable<ScenarioTestCase>> GetEnabledByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID和测试用例流程ID获取场景测试用例
|
|||
/// </summary>
|
|||
/// <param name="scenarioId">场景ID</param>
|
|||
/// <param name="testCaseFlowId">测试用例流程ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>场景测试用例</returns>
|
|||
Task<ScenarioTestCase?> GetByScenarioAndTestCaseFlowAsync(string scenarioId, string testCaseFlowId, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 检查场景中是否已存在指定的测试用例
|
|||
/// </summary>
|
|||
/// <param name="scenarioId">场景ID</param>
|
|||
/// <param name="testCaseFlowId">测试用例流程ID</param>
|
|||
/// <param name="excludeId">排除的ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>是否存在</returns>
|
|||
Task<bool> ExistsInScenarioAsync(string scenarioId, string testCaseFlowId, string? excludeId = null, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID获取包含完整信息的测试用例列表
|
|||
/// </summary>
|
|||
/// <param name="scenarioId">场景ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>包含完整信息的测试用例列表</returns>
|
|||
Task<IEnumerable<ScenarioTestCase>> GetWithDetailsByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID删除所有测试用例
|
|||
/// </summary>
|
|||
/// <param name="scenarioId">场景ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>删除的记录数</returns>
|
|||
Task<int> DeleteByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID获取测试用例数量
|
|||
/// </summary>
|
|||
/// <param name="scenarioId">场景ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>测试用例数量</returns>
|
|||
Task<int> GetCountByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 批量检查场景中已存在的测试用例流程ID
|
|||
/// </summary>
|
|||
/// <param name="scenarioId">场景ID</param>
|
|||
/// <param name="testCaseFlowIds">要检查的测试用例流程ID列表</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>已存在的测试用例流程ID集合</returns>
|
|||
Task<HashSet<string>> GetExistingTestCaseFlowIdsAsync(string scenarioId, IEnumerable<string> testCaseFlowIds, CancellationToken cancellationToken = default); |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.Base; |
|||
|
|||
namespace X1.Domain.Repositories.TestCase |
|||
{ |
|||
/// <summary>
|
|||
/// 测试场景仓储接口
|
|||
/// </summary>
|
|||
public interface ITestScenarioRepository : IBaseRepository<TestScenario> |
|||
{ |
|||
/// <summary>
|
|||
/// 根据场景编码获取测试场景
|
|||
/// </summary>
|
|||
/// <param name="scenarioCode">场景编码</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>测试场景</returns>
|
|||
Task<TestScenario?> GetByScenarioCodeAsync(string scenarioCode, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据场景类型获取测试场景列表
|
|||
/// </summary>
|
|||
/// <param name="type">场景类型</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>测试场景列表</returns>
|
|||
Task<IEnumerable<TestScenario>> GetByTypeAsync(ScenarioType type, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 获取启用的测试场景列表
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>启用的测试场景列表</returns>
|
|||
Task<IEnumerable<TestScenario>> GetEnabledAsync(CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 检查场景编码是否存在
|
|||
/// </summary>
|
|||
/// <param name="scenarioCode">场景编码</param>
|
|||
/// <param name="excludeId">排除的ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>是否存在</returns>
|
|||
Task<bool> ExistsByScenarioCodeAsync(string scenarioCode, string? excludeId = null, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID获取包含测试用例的完整场景信息
|
|||
/// </summary>
|
|||
/// <param name="scenarioId">场景ID</param>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>包含测试用例的场景</returns>
|
|||
Task<TestScenario?> GetWithTestCasesAsync(string scenarioId, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 获取所有包含测试用例的场景列表
|
|||
/// </summary>
|
|||
/// <param name="cancellationToken">取消令牌</param>
|
|||
/// <returns>包含测试用例的场景列表</returns>
|
|||
Task<IEnumerable<TestScenario>> GetAllWithTestCasesAsync(CancellationToken cancellationToken = default); |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Metadata.Builders; |
|||
using X1.Domain.Entities.TestCase; |
|||
|
|||
namespace X1.Infrastructure.Configurations.TestCase |
|||
{ |
|||
/// <summary>
|
|||
/// 场景测试用例实体配置
|
|||
/// </summary>
|
|||
public class ScenarioTestCaseConfiguration : IEntityTypeConfiguration<ScenarioTestCase> |
|||
{ |
|||
public void Configure(EntityTypeBuilder<ScenarioTestCase> builder) |
|||
{ |
|||
// 表名
|
|||
builder.ToTable("tb_scenariotestcases"); |
|||
|
|||
// 主键
|
|||
builder.HasKey(x => x.Id); |
|||
|
|||
// 属性配置
|
|||
builder.Property(x => x.Id) |
|||
.IsRequired() |
|||
.HasMaxLength(50); |
|||
|
|||
builder.Property(x => x.ScenarioId) |
|||
.IsRequired() |
|||
.HasMaxLength(50); |
|||
|
|||
builder.Property(x => x.TestCaseFlowId) |
|||
.IsRequired() |
|||
.HasMaxLength(50); |
|||
|
|||
builder.Property(x => x.IsEnabled) |
|||
.IsRequired() |
|||
.HasDefaultValue(true); |
|||
|
|||
builder.Property(x => x.ExecutionOrder) |
|||
.IsRequired() |
|||
.HasDefaultValue(0); |
|||
|
|||
builder.Property(x => x.LoopCount) |
|||
.IsRequired() |
|||
.HasDefaultValue(1); |
|||
|
|||
// 审计字段
|
|||
builder.Property(x => x.CreatedAt) |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.UpdatedAt) |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.CreatedBy) |
|||
.IsRequired() |
|||
.HasMaxLength(50); |
|||
|
|||
builder.Property(x => x.UpdatedBy) |
|||
.IsRequired() |
|||
.HasMaxLength(50); |
|||
|
|||
// 索引
|
|||
builder.HasIndex(x => x.ScenarioId); |
|||
|
|||
builder.HasIndex(x => x.TestCaseFlowId); |
|||
|
|||
builder.HasIndex(x => new { x.ScenarioId, x.TestCaseFlowId }) |
|||
.IsUnique(); |
|||
|
|||
builder.HasIndex(x => new { x.ScenarioId, x.ExecutionOrder }); |
|||
|
|||
// 关系配置
|
|||
builder.HasOne(x => x.Scenario) |
|||
.WithMany(x => x.ScenarioTestCases) |
|||
.HasForeignKey(x => x.ScenarioId) |
|||
.OnDelete(DeleteBehavior.Cascade); |
|||
|
|||
builder.HasOne(x => x.TestCaseFlow) |
|||
.WithMany(x => x.TestScenarioTestCases) |
|||
.HasForeignKey(x => x.TestCaseFlowId) |
|||
.OnDelete(DeleteBehavior.Restrict); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Metadata.Builders; |
|||
using X1.Domain.Entities.TestCase; |
|||
|
|||
namespace X1.Infrastructure.Configurations.TestCase |
|||
{ |
|||
/// <summary>
|
|||
/// 测试场景实体配置
|
|||
/// </summary>
|
|||
public class TestScenarioConfiguration : IEntityTypeConfiguration<TestScenario> |
|||
{ |
|||
public void Configure(EntityTypeBuilder<TestScenario> builder) |
|||
{ |
|||
// 表名
|
|||
builder.ToTable("tb_testscenarios"); |
|||
|
|||
// 主键
|
|||
builder.HasKey(x => x.Id); |
|||
|
|||
// 属性配置
|
|||
builder.Property(x => x.Id) |
|||
.IsRequired() |
|||
.HasMaxLength(50); |
|||
|
|||
builder.Property(x => x.ScenarioCode) |
|||
.IsRequired() |
|||
.HasMaxLength(50); |
|||
|
|||
builder.Property(x => x.ScenarioName) |
|||
.IsRequired() |
|||
.HasMaxLength(200); |
|||
|
|||
builder.Property(x => x.Type) |
|||
.IsRequired() |
|||
.HasConversion<string>(); |
|||
|
|||
builder.Property(x => x.Description) |
|||
.HasMaxLength(1000); |
|||
|
|||
builder.Property(x => x.IsEnabled) |
|||
.IsRequired() |
|||
.HasDefaultValue(true); |
|||
|
|||
// 审计字段
|
|||
builder.Property(x => x.CreatedAt) |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.UpdatedAt) |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.CreatedBy) |
|||
.IsRequired() |
|||
.HasMaxLength(50); |
|||
|
|||
builder.Property(x => x.UpdatedBy) |
|||
.IsRequired() |
|||
.HasMaxLength(50); |
|||
|
|||
// 索引
|
|||
builder.HasIndex(x => x.ScenarioCode) |
|||
.IsUnique(); |
|||
|
|||
builder.HasIndex(x => x.Type); |
|||
|
|||
builder.HasIndex(x => x.IsEnabled); |
|||
|
|||
// 关系配置
|
|||
builder.HasMany(x => x.ScenarioTestCases) |
|||
.WithOne(x => x.Scenario) |
|||
.HasForeignKey(x => x.ScenarioId) |
|||
.OnDelete(DeleteBehavior.Cascade); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,135 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Extensions.Logging; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.Base; |
|||
using X1.Domain.Repositories.TestCase; |
|||
using X1.Infrastructure.Repositories.Base; |
|||
|
|||
namespace X1.Infrastructure.Repositories.TestCase |
|||
{ |
|||
/// <summary>
|
|||
/// 场景测试用例仓储实现
|
|||
/// </summary>
|
|||
public class ScenarioTestCaseRepository : BaseRepository<ScenarioTestCase>, IScenarioTestCaseRepository |
|||
{ |
|||
private readonly ILogger<ScenarioTestCaseRepository> _logger; |
|||
|
|||
public ScenarioTestCaseRepository( |
|||
ICommandRepository<ScenarioTestCase> commandRepository, |
|||
IQueryRepository<ScenarioTestCase> queryRepository, |
|||
ILogger<ScenarioTestCaseRepository> logger) |
|||
: base(commandRepository, queryRepository, logger) |
|||
{ |
|||
_logger = logger; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID获取测试用例列表
|
|||
/// </summary>
|
|||
public async Task<IEnumerable<ScenarioTestCase>> GetByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var testCases = await QueryRepository.FindAsync(x => x.ScenarioId == scenarioId, cancellationToken:cancellationToken); |
|||
return testCases.OrderBy(x => x.ExecutionOrder); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据测试用例流程ID获取场景测试用例列表
|
|||
/// </summary>
|
|||
public async Task<IEnumerable<ScenarioTestCase>> GetByTestCaseFlowIdAsync(string testCaseFlowId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var testCases = await QueryRepository.FindAsync(x => x.TestCaseFlowId == testCaseFlowId, cancellationToken: cancellationToken); |
|||
return testCases.OrderBy(x => x.ExecutionOrder); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID获取启用的测试用例列表
|
|||
/// </summary>
|
|||
public async Task<IEnumerable<ScenarioTestCase>> GetEnabledByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var testCases = await QueryRepository.FindAsync(x => x.ScenarioId == scenarioId && x.IsEnabled, cancellationToken: cancellationToken); |
|||
return testCases.OrderBy(x => x.ExecutionOrder); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID和测试用例流程ID获取场景测试用例
|
|||
/// </summary>
|
|||
public async Task<ScenarioTestCase?> GetByScenarioAndTestCaseFlowAsync(string scenarioId, string testCaseFlowId, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await QueryRepository.FirstOrDefaultAsync(x => x.ScenarioId == scenarioId && x.TestCaseFlowId == testCaseFlowId, cancellationToken: cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查场景中是否已存在指定的测试用例
|
|||
/// </summary>
|
|||
public async Task<bool> ExistsInScenarioAsync(string scenarioId, string testCaseFlowId, string? excludeId = null, CancellationToken cancellationToken = default) |
|||
{ |
|||
if (string.IsNullOrEmpty(excludeId)) |
|||
{ |
|||
return await QueryRepository.AnyAsync(x => x.ScenarioId == scenarioId && x.TestCaseFlowId == testCaseFlowId, cancellationToken: cancellationToken); |
|||
} |
|||
else |
|||
{ |
|||
return await QueryRepository.AnyAsync(x => x.ScenarioId == scenarioId && x.TestCaseFlowId == testCaseFlowId && x.Id != excludeId, cancellationToken: cancellationToken); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID获取包含完整信息的测试用例列表
|
|||
/// </summary>
|
|||
public async Task<IEnumerable<ScenarioTestCase>> GetWithDetailsByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var testCases = await QueryRepository.FindAsync( |
|||
x => x.ScenarioId == scenarioId, |
|||
query => query.Include(x => x.Scenario).Include(x => x.TestCaseFlow), |
|||
cancellationToken); |
|||
return testCases.OrderBy(x => x.ExecutionOrder); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID删除所有测试用例
|
|||
/// </summary>
|
|||
public async Task<int> DeleteByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var testCases = await QueryRepository.FindAsync(x => x.ScenarioId == scenarioId, cancellationToken: cancellationToken); |
|||
var testCaseList = testCases.ToList(); |
|||
|
|||
if (testCaseList.Any()) |
|||
{ |
|||
CommandRepository.DeleteRange(testCaseList); |
|||
} |
|||
|
|||
return testCaseList.Count; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID获取测试用例数量
|
|||
/// </summary>
|
|||
public async Task<int> GetCountByScenarioIdAsync(string scenarioId, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await QueryRepository.CountAsync(x => x.ScenarioId == scenarioId, cancellationToken: cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 批量检查场景中已存在的测试用例流程ID
|
|||
/// </summary>
|
|||
public async Task<HashSet<string>> GetExistingTestCaseFlowIdsAsync(string scenarioId, IEnumerable<string> testCaseFlowIds, CancellationToken cancellationToken = default) |
|||
{ |
|||
var testCaseFlowIdList = testCaseFlowIds.ToList(); |
|||
if (!testCaseFlowIdList.Any()) |
|||
{ |
|||
return new HashSet<string>(); |
|||
} |
|||
|
|||
var existingTestCases = await QueryRepository.FindAsync( |
|||
x => x.ScenarioId == scenarioId && testCaseFlowIdList.Contains(x.TestCaseFlowId), |
|||
cancellationToken: cancellationToken); |
|||
|
|||
return existingTestCases.Select(x => x.TestCaseFlowId).ToHashSet(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Extensions.Logging; |
|||
using X1.Domain.Entities.TestCase; |
|||
using X1.Domain.Repositories.Base; |
|||
using X1.Domain.Repositories.TestCase; |
|||
using X1.Infrastructure.Repositories.Base; |
|||
|
|||
namespace X1.Infrastructure.Repositories.TestCase |
|||
{ |
|||
/// <summary>
|
|||
/// 测试场景仓储实现
|
|||
/// </summary>
|
|||
public class TestScenarioRepository : BaseRepository<TestScenario>, ITestScenarioRepository |
|||
{ |
|||
private readonly ILogger<TestScenarioRepository> _logger; |
|||
|
|||
public TestScenarioRepository( |
|||
ICommandRepository<TestScenario> commandRepository, |
|||
IQueryRepository<TestScenario> queryRepository, |
|||
ILogger<TestScenarioRepository> logger) |
|||
: base(commandRepository, queryRepository, logger) |
|||
{ |
|||
_logger = logger; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据场景编码获取测试场景
|
|||
/// </summary>
|
|||
public async Task<TestScenario?> GetByScenarioCodeAsync(string scenarioCode, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await QueryRepository.FirstOrDefaultAsync(x => x.ScenarioCode == scenarioCode, cancellationToken: cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据场景类型获取测试场景列表
|
|||
/// </summary>
|
|||
public async Task<IEnumerable<TestScenario>> GetByTypeAsync(ScenarioType type, CancellationToken cancellationToken = default) |
|||
{ |
|||
var scenarios = await QueryRepository.FindAsync(x => x.Type == type, cancellationToken: cancellationToken); |
|||
return scenarios.OrderBy(x => x.ScenarioCode); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取启用的测试场景列表
|
|||
/// </summary>
|
|||
public async Task<IEnumerable<TestScenario>> GetEnabledAsync(CancellationToken cancellationToken = default) |
|||
{ |
|||
var scenarios = await QueryRepository.FindAsync(x => x.IsEnabled, cancellationToken: cancellationToken); |
|||
return scenarios.OrderBy(x => x.ScenarioCode); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查场景编码是否存在
|
|||
/// </summary>
|
|||
public async Task<bool> ExistsByScenarioCodeAsync(string scenarioCode, string? excludeId = null, CancellationToken cancellationToken = default) |
|||
{ |
|||
if (string.IsNullOrEmpty(excludeId)) |
|||
{ |
|||
return await QueryRepository.AnyAsync(x => x.ScenarioCode == scenarioCode, cancellationToken: cancellationToken); |
|||
} |
|||
else |
|||
{ |
|||
return await QueryRepository.AnyAsync(x => x.ScenarioCode == scenarioCode && x.Id != excludeId, cancellationToken: cancellationToken); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据场景ID获取包含测试用例的完整场景信息
|
|||
/// </summary>
|
|||
public async Task<TestScenario?> GetWithTestCasesAsync(string scenarioId, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await QueryRepository.GetByIdAsync(scenarioId, |
|||
query => query.Include(x => x.ScenarioTestCases).ThenInclude(stc => stc.TestCaseFlow), |
|||
cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取所有包含测试用例的场景列表
|
|||
/// </summary>
|
|||
public async Task<IEnumerable<TestScenario>> GetAllWithTestCasesAsync(CancellationToken cancellationToken = default) |
|||
{ |
|||
var scenarios = await QueryRepository.GetAllAsync( |
|||
query => query.Include(x => x.ScenarioTestCases).ThenInclude(stc => stc.TestCaseFlow), |
|||
cancellationToken: cancellationToken); |
|||
return scenarios.OrderBy(x => x.ScenarioCode); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue