1. 程式人生 > >Magicodes.IE編寫多框架版本支援和執行單元測試

Magicodes.IE編寫多框架版本支援和執行單元測試

背景

很多情況下,我們編寫了一些工具庫之後,往往在某些框架版本中會出現一些問題,比如本人最近寫的一個匯入匯出的工具庫Magicodes.IE(GitHub:https://github.com/xin-lai/Magicodes.IE)就出現了以下問題:

 

 

雖然支援標準庫2.0,但是通過編寫單元測試,確實發現如此:

因此,單元測試確實需要針對各個框架版本進行測試,並且相關程式碼需要針對框架進行相容修改。那麼如何實現呢?接下來我們一步步實踐。

.NET框架版本說明

最新目標框架版本

下表定義了最常見的目標框架、如何引用這些框架,以及它們實現的 .NET Standard 版本。 這些目標框架版本是最新的穩定版本。 預覽版不會顯示。 目標框架名字物件 (TFM) 是一個標準化令牌格式,用於指定 .NET 應用或庫的目標框架。

目標 Framework最新 穩定版本目標框架名字物件 (TFM)已實現 .NET Standard 版本
.NET Standard 2.1 netstandard2.1 不可用
.NET Core 3.0 netcoreapp3.0 2.1
.NET Framework 4.8 net48 2.0

支援的目標框架版本

目標框架通常由 TFM 引用。 下表顯示 .NET Core SDK 和 NuGet 客戶端支援的目標框架。 等效項顯示在括號內。 例如,win81 對於 netcore451 來說等效於 TFM。

目標 FrameworkTFM
.NET Standard netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0 netstandard2.1
.NET Core netcoreapp1.0 netcoreapp1.1 netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0
.NET Framework net11 net20 net35 net40 net403 net45 net451 net452 net46 net461 net462 net47 net471 net472 net48
Windows 應用商店 netcore [netcore45] netcore45 [win] [win8] netcore451 [win81]
.NET Micro Framework netmf
Silverlight sl4 sl5
Windows Phone wp [wp7] wp7 wp75 wp8 wp81 wpa81
通用 Windows 平臺 uap [uap10.0] uap10.0 [win10] [netcore50]

如何讓工程支援多個框架?

以單元測試工程為例:

<PropertyGroup>
    <TargetFrameworks>netcoreapp3.0;netcoreapp2.2;netcoreapp3.1;net461</TargetFrameworks>
    <IsPackable>false</IsPackable>
  </PropertyGroup>

如上述程式碼所示,我們可以通過“TargetFrameworks”元素來定義多個框架。那麼如何在工程裡面新增條件判斷以進行編譯呢?

<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
  </ItemGroup>

除了工程裡面,我們程式碼中如何針對不同的框架版本編寫程式碼呢?

#if NET461
            return excelPackage.Workbook.Worksheets[typeof(T).GetDisplayName()] ??
                   excelPackage.Workbook.Worksheets[ExcelImporterSettings.SheetName] ??
                   excelPackage.Workbook.Worksheets[1];
#else
            return excelPackage.Workbook.Worksheets[typeof(T).GetDisplayName()] ??
                   excelPackage.Workbook.Worksheets[ExcelImporterSettings.SheetName] ??
                   excelPackage.Workbook.Worksheets[0];
#endif

這些“NET461”的符號都有哪些呢?如下所示:

完整的 .NET Core 目標框架的前處理器符號列表

目標框架符號
.NET Framework NETFRAMEWORKNET20NET35NET40NET45NET451NET452NET46NET461NET462NET47NET471NET472NET48
.NET Standard NETSTANDARDNETSTANDARD1_0NETSTANDARD1_1NETSTANDARD1_2NETSTANDARD1_3NETSTANDARD1_4NETSTANDARD1_5NETSTANDARD1_6NETSTANDARD2_0NETSTANDARD2_1
.NET Core NETCOREAPPNETCOREAPP1_0NETCOREAPP1_1NETCOREAPP2_0NETCOREAPP2_1NETCOREAPP2_2NETCOREAPP3_0NETCOREAPP3_1

Magicodes.IE之多框架版本測試

瞭解了這些知識,我們就可以編寫多框架版本的實現和單元測試了。

單元測試新增多框架支援

  1. 修改TargetFramework為TargetFrameworks

     

  2. 設定分組

    根據目標框架分組:

  3. 修復編譯錯誤

  4. 執行單元測試

    單元測試結果如下圖所示:

    針對具體的單元測試,我們還可以指定目標框架進行執行和除錯:

     

總結和經驗分享

結合整改的過程,我們可以得出以下經驗:

  1. 單元測試編寫時的異常訊息判斷儘量使用字串包含判斷,而不判斷完整格式。

 

如上面所示,左側程式碼在net461、netcoreapp2.2都是無法通過的,格式化的引數模板不一致。

  1. 特定框架、平臺程式碼需新增符號判斷

    如下面示例,預設情況下,.NET Core 不提供除內碼表 28591 以外的其他任何內碼表編碼和 Unicode 編碼,例如 UTF-8 和 UTF-16,所以我們可以使用以下程式碼進行新增,但是需要排除.NET Framework:

    除了特定程式碼之外,有時還有特定依賴的包:

  2. 慎用新語法糖

    比如以下程式碼:

精力有限,暫不適配過多框架版本,有興趣的朋友可以參與進來。

&n