mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-08 10:54:50 +00:00
Tests/ 根层原有 138 个平铺测试文件,无法从目录读出测试覆盖的功能领域。 按功能领域重组为 17 个目录(Catalog/Workflow 与 Rules/Custom 两处嵌套,分别 对应 App/Application/CatalogWorkflow 与 Domain/Rules/Custom):Architecture / Support / Agent / Activation / Catalog / Subscription / Rules / ProxyRuntime / ProxyControl / Runtime / Settings / SystemProxy / Plugin / Diagnostics / Credentials / Workspace / Servers;Smoke/ 保持独立 target 不动。138 个移动中 132 个是 100% 相似度的纯重命名,其余 6 个在重命名之上带路径反推改写(见下)。 本次不是纯搬移:测试代码比生产代码多一层位置耦合,有 7 处用固定层数的 deletingLastPathComponent() 从 #filePath 反推仓库路径(都假定文件就在 Tests/ 根层)。这 7 处改走新增的 Tests/Support/TestSourceTree.swift——从调用点沿父 目录上溯找到含 project.yml 的目录,因此不再依赖父目录层数,以后移动测试文件 也不会静默指错。 配套改动: - 新增 Tests 布局守卫 TestsLayoutTests,断言 Tests/ 根层无平铺 .swift。比 Domain 那条弱一档——根层的 Info.plist(info.path 生成物)与 Fixtures/RuleSnapshots 下的 JSON(folder resource)都必须保留,不能用 「树下只有 .swift」覆盖。 - project.yml:Smoke target 按文件引用的 Tests/AppArtifact.swift 改指 Tests/Support/;两处注释里写死的 Tests/SkeletonTests.swift 随移动更新。 excludes 的裸名 "Smoke" / "Fixtures" 仍匹配 Tests/ 直属子目录,无需改动。 - README 的 Tests 条目展开为目录说明,并修掉 Domain 条目里写死的 Tests/SkeletonTests.swift。 - 顺带删去 DomainLayoutTests 文档注释里「整理前 62 个文件」这类易漂移的数字。 验证:xcodegen generate 后单测 target 为 139 个源文件(全部非 Smoke 文件,0 个 Smoke 文件混入)且仍以 Fixtures/RuleSnapshots 为资源,Smoke target 为 8 个 Smoke 文件加 AppArtifact;依赖路径反推的 6 个测试类全绿(路径指错即失败); task format 未改写任何被移动文件;task lint 与整理前同为 21 条内容型 warning; build 0 error;task test 1025 用例全通过(整理前 1024,+1 为新守卫); TestsLayoutTests 经变异验证(根层投放探针即失败);packaging-gate ALL CHECKS PASSED。
36 lines
1.6 KiB
Swift
36 lines
1.6 KiB
Swift
import Foundation
|
||
|
||
/// 构建产物定位:从测试 bundle 落盘位置向上逐层查找 app 产物。覆盖两种布局
|
||
/// ——TEST_HOST 过渡期 `.xctest` 嵌于 app bundle 的 `Contents/PlugIns/`(app
|
||
/// 是祖先),去宿主化后 `.xctest` 与 `.app` 平级同在 `Build/Products/<config>/`
|
||
/// (app 是某层祖先的子项)。测试需要 app 产物(嵌入二进制、Info.plist 打包面
|
||
/// 断言)时一律经此定位,不得用 `Bundle.main`(去宿主化后它是 xctest runner
|
||
/// 的 bundle)。
|
||
enum AppArtifact {
|
||
static let bundleURL: URL = {
|
||
let testBundleURL = Bundle(for: Marker.self).bundleURL
|
||
var directory = testBundleURL
|
||
while directory.path != "/" {
|
||
if directory.lastPathComponent == "ShadowsocksX-NG2.app" {
|
||
return directory
|
||
}
|
||
directory.deleteLastPathComponent()
|
||
let candidate = directory.appendingPathComponent(
|
||
"ShadowsocksX-NG2.app", isDirectory: true)
|
||
if FileManager.default.fileExists(atPath: candidate.path) {
|
||
return candidate
|
||
}
|
||
}
|
||
// 定位失败时返回原目录让用例以「产物缺失」失败并暴露实际路径,不炸进程。
|
||
return testBundleURL
|
||
}()
|
||
|
||
/// `bundleURL` 的 Bundle 形态:注入按 Bundle 取资源的生产缝(如
|
||
/// ProxyRuntimeController 的内置规则快照 bundle)。定位失败时退回测试
|
||
/// bundle,让资源缺失以用例失败呈现。
|
||
static let bundle: Bundle = Bundle(url: bundleURL) ?? Bundle(for: Marker.self)
|
||
|
||
/// `Bundle(for:)` 需要类对象;marker 只为取得测试 bundle 的落盘位置。
|
||
private final class Marker {}
|
||
}
|