using Microsoft.Extensions.Configuration;
namespace Yh.SchClass.OpenApi.Tests;
///
/// 联调调试用的环境配置。地址来源优先级:
///
/// 1. 环境变量(YH_SCHCLASS_DEBUG_HOST / YH_SCHCLASS_DEBUG_PATH);
/// 2. appsettings.json:先独立节 yh:schclass:open,再共享节 yh:open 的
/// BaseHost + SchClassPath;
/// 3. 内置默认 + 。
///
///
/// 关闭联调:置 YH_SCHCLASS_DEBUG_OFF=1,用例全部空跑通过(CI 用)。
///
///
internal static class SchClassLiveDebug
{
public const string HostVar = "YH_SCHCLASS_DEBUG_HOST";
public const string PathVar = "YH_SCHCLASS_DEBUG_PATH";
public const string SchVar = "YH_SCHCLASS_DEBUG_SCH";
public const string ClassVar = "YH_SCHCLASS_DEBUG_CLASS";
public const string TeaVar = "YH_SCHCLASS_DEBUG_TEA";
public const string GroupVar = "YH_SCHCLASS_DEBUG_GROUP";
public const string OffVar = "YH_SCHCLASS_DEBUG_OFF";
/// 配置与配置文件都未提供时的兜底联调主机。
public const string DefaultHost = "http://base.yunhaixingtong.com";
/// 配置与配置文件都未提供时的兜底应用路径。
public const string DefaultPath = "/userclass";
private static readonly IConfiguration? Config;
static SchClassLiveDebug()
{
var file = System.IO.Path.Combine(AppContext.BaseDirectory, "appsettings.json");
if (File.Exists(file))
{
Config = new ConfigurationBuilder().AddJsonFile(file, optional: true).Build();
}
}
/// 是否开启联调(默认开启;置 YH_SCHCLASS_DEBUG_OFF=1 可关闭,CI 用它空跑)。
public static bool Enabled
{
get
{
var off = Environment.GetEnvironmentVariable(OffVar);
return !(off == "1" || "true".Equals(off, StringComparison.OrdinalIgnoreCase));
}
}
private static string? Env(string name)
{
var value = Environment.GetEnvironmentVariable(name);
return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
}
private static string? Configured(string path)
{
var value = Config?[path];
return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
}
/// 联调主机:环境变量 → yh:schclass:open:BaseHost → yh:open:BaseHost → 内置默认。
public static string Host =>
Env(HostVar)
?? Configured("yh:schclass:open:BaseHost")
?? Configured("yh:open:BaseHost")
?? DefaultHost;
/// 联调基础路径:环境变量 → yh:schclass:open:BasePath → yh:open:SchClassPath → 内置默认。
public static string? Path =>
Env(PathVar)
?? Configured("yh:open:SchClassPath")
?? DefaultPath;
/// 按当前配置构建门面。
public static SchClassOpenApi Create()
{
var options = new SchClassOpenApiOptions { BaseHost = Host, BasePath = Path };
return SchClassOpenApiFactory.Create(options);
}
/// 联调目标地址(用于日志输出)。
public static string Target()
{
var options = new SchClassOpenApiOptions { BaseHost = Host, BasePath = Path };
return options.ResolveBaseUrl();
}
public static string? Sch => Env(SchVar);
public static string? ClassId => Env(ClassVar);
public static int? TeaSerId => int.TryParse(Env(TeaVar), out var id) ? id : null;
/// DbClass 分组号,缺省 3(对联调环境真实有效的分组)。
public static int? Group => int.TryParse(Env(GroupVar), out var g) ? g : null;
///
/// 一键跑通全部端点(测试用例与 DebugMain.Main 调试入口共用)。
/// 缺省 ID 一律从真实数据推导:用捏造的 ID 会让端点恒成立 0 条,把真实问题伪装成"接口空"。
/// 返回失败端点名列表; 输出进度。
///
public static async Task> RunAllAsync(Action log, string? only = null)
{
var api = Create();
var sch = Sch
?? (await api.SchInfo.AllListAsync()).FirstOrDefault()?.SchSerId ?? "S001";
var group = Group ?? 3;
var classId = ClassId;
if (classId == null)
{
var cls = (await api.VClass.GetVClassListAsync(sch)).FirstOrDefault();
classId = cls != null && cls.TryGetValue("ClassID", out var cid)
? cid.ToString()
: "1001";
}
var teaId = TeaSerId;
if (teaId == null)
{
var tea = (await api.DbClass.GetSchteaListAsync(group)).FirstOrDefault();
teaId = tea != null
&& tea.TryGetValue("UserTeaSerID", out var tid)
&& int.TryParse(tid.ToString(), out var parsed)
? parsed
: 77;
}
var cases = new List<(string Name, Func> Call)>
{
// Group=3 对应联调环境真实存在的分组;可用 YH_SCHCLASS_DEBUG_GROUP 覆盖
("DbClass.GetSchteaList", async () => (await api.DbClass.GetSchteaListAsync(group)).Count),
("VSchClass.GetVClassList", async () => (await api.VClass.GetVClassListAsync(sch)).Count),
("VSchClass.GetSchArrVClassListAll", async () => (await api.VClass.GetSchArrVClassListAllAsync()).Count),
("VSchClass.GetSchArrVClassListPost", async () => (await api.VClass.GetSchArrVClassListPostAsync(sch)).Count),
("Schoolen.GetSchLenLevellist", async () => (await api.Schooling.GetSchLenLevelListAsync(sch)).Count),
("Schoolen.GetSchLenlist", async () => (await api.Schooling.GetSchLenListAsync(sch)).Count),
("UserInfo.GetUserList", async () => (await api.UserInfo.GetUserListAsync(sch)).Count),
("SchInfo.AllList", async () => (await api.SchInfo.AllListAsync()).Count),
("SchInfo.GetSchlist", async () => (await api.SchInfo.GetSchListAsync(null)).Count),
("OATea.GetSchTeainfo", async () => (await api.TeaInfo.GetSchTeaInfoAsync(sch, null)).Count),
("OATea.GetArrTeainfo", async () => (await api.TeaInfo.GetArrTeaInfoAsync(teaId.Value.ToString())).Count),
("SchGroup.GetTeaTree", async () => (await api.SchTree.GetTeaTreeAsync(sch, null)).Count),
("OAStu.GetAllStulist", async () => (await api.StuInfo.GetAllStuListAsync()).Count),
("OAStu.GetSchStulist", async () => (await api.StuInfo.GetSchStuListAsync(sch, null)).Count),
("OAStu.GetClaStulist", async () => (await api.StuInfo.GetClaStuListAsync(classId, null)).Count),
("TeachInfo.GetSchTeachlist", async () => (await api.TeachInfo.GetSchTeachListAsync(sch, teaId)).Count),
("TeachInfo.GetSchClaTeachlist", async () => (await api.TeachInfo.GetSchClaTeachListAsync(classId)).Count),
("SubInfo.GetSchTeachSublist", async () => (await api.SubInfo.GetSchTeachSubListAsync(sch)).Count),
("SubInfo.GetSchSublist", async () => (await api.SubInfo.GetSchSubListAsync(sch, null, null)).Count),
("FamCom.GetStuUserFamIDList", async () => (await api.FamilyCompat.GetStuUserFamIdListAsync("1,2")).Count),
("FamCom.GetAllStuFamMem", async () => (await api.FamilyCompat.GetAllStuFamMemAsync("1,2")).Count),
};
if (only != null)
{
cases = cases.Where(c => c.Name.Contains(only, StringComparison.OrdinalIgnoreCase)).ToList();
if (cases.Count == 0)
{
log($"--only={only} 未匹配任何端点");
return new List { "--only" };
}
}
var failures = new List();
log($"联调目标:{Target()} sch={sch} classId={classId} teaId={teaId} group={group}");
foreach (var (name, call) in cases)
{
try
{
var count = await call();
log($" OK {name} -> {count} 条");
}
catch (Exception e)
{
failures.Add(name);
log($" FAIL {name} -> {e.GetType().Name}: {e.Message}");
}
}
log($"汇总:{cases.Count - failures.Count}/{cases.Count} 通过");
return failures;
}
}