咨询C#自动化测试脚本多平台切换最优方案(新增平台无需编译)
最优平台切换方案:策略模式+配置驱动(无需重新编译)
嘿,这个场景我太熟悉了——用一堆if/else或者全局常量硬编码切换平台,初期快是快,但扩展性简直噩梦,新增平台就得改核心测试代码,还得重新编译,完全违反了开闭原则。给你几个生产环境验证过的最优方案,都能实现新增平台无需修改原有代码、不用重新编译的要求:
一、首选方案:策略模式+配置驱动(易维护、结构清晰)
核心思路是把每个平台的测试逻辑封装成独立的策略类,通过配置文件指定当前使用的平台,运行时动态加载对应的策略实现。
步骤1:定义统一的测试策略接口
先把所有测试用例抽象成接口,确保每个平台的实现都遵循统一规范:
public interface IPlayerTestStrategy { bool TestCase1(); bool TestCase2(); // 其他需要的测试用例方法... }
步骤2:为每个平台实现策略类
把通用逻辑和平台特有逻辑分离,通用逻辑可以抽成公共方法或类,避免重复代码:
// PlatformA的测试策略实现 public class PlatformATestStrategy : IPlayerTestStrategy { public bool TestCase1() { // 先执行所有平台通用的逻辑(比如从SQLite读取测试数据) RunCommonTestCase1Logic(); // PlatformA专属的测试逻辑 // 示例:模拟PlatformA的播放操作验证 // ... return true; } public bool TestCase2() { RunCommonTestCase2Logic(); // PlatformA专属逻辑 // ... return true; } // 通用逻辑可以抽成私有方法,或者单独的公共类 private void RunCommonTestCase1Logic() { // 从SQLite读取测试用例1的验证数据 // ... } private void RunCommonTestCase2Logic() { // 通用的前置操作 // ... } }
// PlatformB的测试策略实现 public class PlatformBTestStrategy : IPlayerTestStrategy { public bool TestCase1() { RunCommonTestCase1Logic(); // PlatformB专属的测试逻辑 // 示例:模拟PlatformB的收藏操作验证 // ... return true; } public bool TestCase2() { RunCommonTestCase2Logic(); // PlatformB专属逻辑 // ... return true; } // 复用通用逻辑(也可以抽成公共类,比如CommonTestUtilities) private void RunCommonTestCase1Logic() { // 从SQLite读取测试用例1的验证数据 // ... } private void RunCommonTestCase2Logic() { // 通用的前置操作 // ... } }
步骤3:配置驱动加载策略
用配置文件(比如appsettings.json或app.config)指定当前要使用的平台策略类型全称:
// appsettings.json示例 { "TestSettings": { "CurrentPlatformStrategy": "YourTestProject.PlatformATestStrategy, YourTestProject" } }
然后在测试初始化时,根据配置动态创建策略实例:
public class TestRunner { private readonly IPlayerTestStrategy _currentStrategy; public TestRunner() { // 从配置读取策略类型(这里用ConfigurationManager,也可以用.NET Core的IConfiguration) var strategyTypeFullName = ConfigurationManager.AppSettings["CurrentPlatformStrategy"]; // 加载类型并创建实例 var strategyType = Type.GetType(strategyTypeFullName); if (strategyType == null) throw new InvalidOperationException($"无法找到平台策略类型:{strategyTypeFullName}"); _currentStrategy = (IPlayerTestStrategy)Activator.CreateInstance(strategyType); } public void ExecuteAllTests() { var test1Result = _currentStrategy.TestCase1(); var test2Result = _currentStrategy.TestCase2(); // 记录测试结果到SQLite等操作 // ... } }
新增平台的操作
只需要:
- 新建一个实现
IPlayerTestStrategy的类(比如PlatformCTestStrategy) - 修改配置文件中的
CurrentPlatformStrategy值为新类的类型全称 - 把新类的编译产物(如果是单独类库的话)放到运行目录
完全不用修改原有测试代码,也不用重新编译主程序!
二、进阶方案:插件式架构(适合平台逻辑独立维护)
如果每个平台的测试逻辑复杂,需要单独开发、版本管理,可以把每个平台的策略做成独立的类库(DLL),作为插件加载。
核心步骤
- 把
IPlayerTestStrategy接口放到一个公共类库中,所有平台插件都引用这个类库 - 每个平台的策略实现单独编译成DLL,放到指定的插件目录
- 主程序启动时扫描插件目录,自动加载所有实现
IPlayerTestStrategy的类型 - 根据配置选择要使用的平台插件
扫描插件的代码示例
public static List<IPlayerTestStrategy> LoadAllPlatformStrategies(string pluginDir) { var strategyList = new List<IPlayerTestStrategy>(); var strategyInterfaceType = typeof(IPlayerTestStrategy); // 遍历插件目录下的所有DLL foreach (var dllPath in Directory.GetFiles(pluginDir, "*.dll")) { try { var assembly = Assembly.LoadFrom(dllPath); // 查找所有实现了IPlayerTestStrategy的非抽象类 var strategyTypes = assembly.GetTypes() .Where(t => strategyInterfaceType.IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); foreach (var type in strategyTypes) { var strategy = (IPlayerTestStrategy)Activator.CreateInstance(type); strategyList.Add(strategy); } } catch (Exception ex) { Console.WriteLine($"加载插件失败:{dllPath},错误:{ex.Message}"); } } return strategyList; }
使用插件
// 加载所有插件 var allStrategies = LoadAllPlatformStrategies("./Plugins"); // 根据配置的平台名称选择策略(比如配置里写"PlatformC") var currentPlatform = ConfigurationManager.AppSettings["CurrentPlatform"]; var currentStrategy = allStrategies.FirstOrDefault(s => s.GetType().Name.Equals($"{currentPlatform}TestStrategy", StringComparison.OrdinalIgnoreCase)); if (currentStrategy == null) throw new InvalidOperationException($"未找到指定平台:{currentPlatform}"); // 执行测试 currentStrategy.TestCase1();
这种方案下,新增平台只需要编译出对应的插件DLL放到插件目录,修改配置即可,完全和主测试程序解耦。
三、通用逻辑复用建议
为了避免各个策略类重复写通用代码,建议把所有平台共享的逻辑抽成单独的公共类,比如:
public static class CommonTestUtilities { public static void LoadTestDataFromSQLite(string testCaseName) { // 从SQLite读取指定测试用例的验证数据 // ... } public static void LogTestResultToSQLite(string testCaseName, bool result) { // 把测试结果写入SQLite // ... } // 其他通用操作... }
然后在策略类里直接调用:
public bool TestCase1() { CommonTestUtilities.LoadTestDataFromSQLite("TestCase1"); // 平台特有逻辑 // ... var result = true; CommonTestUtilities.LogTestResultToSQLite("TestCase1", result); return result; }
总结一下:如果是中小型项目,策略模式+配置驱动足够好用,代码清晰易维护;如果平台逻辑需要独立管理,就用插件式架构。两种方案都能完美满足你“新增平台无需重新编译、通用性强”的要求。
内容的提问来源于stack exchange,提问作者DevSay
相关产品推荐
相关产品推荐

