解剖SQLSERVER 第十一篇 对SQLSERVER的多个版本进行自动化测试(译) http://improve.dk/automated-testing-of-orcamdf-against-multiple-sql-server-versions/ 自从我发布了OrcaMDF Studio,我已经意识到SQL2005和SQL2008之间的一些系统表的差异。 这些差异
解剖SQLSERVER 第十一篇 对SQLSERVER的多个版本进行自动化测试(译)
http://improve.dk/automated-testing-of-orcamdf-against-multiple-sql-server-versions/
自从我发布了OrcaMDF Studio,我已经意识到SQL2005和SQL2008之间的一些系统表的差异。
这些差异导致OrcaMDF 解析失败因为代码是针对 2008 R2的格式的
当需要做SQL2005的兼容时,我渐渐意识到我需要扩大多个SQLSERVER版本的测试覆盖,替代之前的只对一个版本的测试。
而且,我也需要对一些特定版本功能进行特定的测试(例如:稀疏列测试只能运行在SQLSERVER2008及以上版本)
NUnit TestCaseSourceAttribute 解决问题
NUnit支持通过TestCase属性进行内联参数测试。更好的是,对于动态测试用例我们还可以提供参数数据,使用TestCaseSource属性,使用TestCaseSource attribute。
首先,我实现了一个简单的枚举来覆盖我目前工作所支持的版本:
<span>public</span> <span>enum</span><span> DatabaseVersion { SqlServer2005, SqlServer2008, SqlServer2008R2, }</span>
然后我创建SqlServerTestAttribute类,直接继承自TestCaseSourceAttribute,就像这样:
<span>public</span> <span>class</span><span> SqlServerTestAttribute : TestCaseSourceAttribute { </span><span>private</span> <span>static</span> IEnumerable<testcasedata><span> versions { </span><span>get</span><span> { </span><span>foreach</span> (<span>var</span> value <span>in</span> Enum.GetValues(<span>typeof</span><span>(DatabaseVersion))) </span><span>yield</span> <span>return</span> <span>new</span><span> TestCaseData(value).SetCategory(value.ToString()); } } </span><span>public</span> SqlServerTestAttribute() : <span>base</span>(<span>typeof</span>(SqlServerTestAttribute), <span>"</span><span>versions</span><span>"</span><span>) { } }</span></testcasedata>
这个SqlServerTestAttribute类告诉TestCaseSourceAttribute 在私有静态的版本属性(private static)里去找测试用例的源数据。
版本属性里枚举出所有的DatabaseVersion值并一个接一个的返回它们——确保将测试类别设置到DatabaseVersion值的名称
接下来,我将当前的测试转换为使用新的SqlServerTest attribute,替代先前的vanilla NUnit Test attribute:
<span>[SqlServerTest] </span><span>public</span> <span>void</span><span> HeapForwardedRecord(DatabaseVersion version) { ... }</span>
这将导致我所有的测试都需要根据DatabaseVersion枚举里面的每个枚举值都运行一次,自动获取输入的版本参数里面的每一个值
支持不同的开发环境
现在,我不想强迫每个人都安装所有版本的SQL Server--他们可能只是想软件支持SQL Server 2005 & 2008R2就够了。在OrcaMDF.Core.Tests项目里,我定义了每种受支持的测试数据库的连接字符串,就像这样
<connectionstrings> <clear></clear> <add name="<span">"<span>SqlServer2005</span><span>"</span> connectionString=<span>"</span><span>Data Source=.SQL2005;Integrated Security=SSPI</span><span>"</span>/> <add name="<span">"<span>SqlServer2008R2</span><span>"</span> connectionString=<span>"</span><span>Data Source=.;Integrated Security=SSPI</span><span>"</span>/> </add></add></connectionstrings>
如果一个数据库没有相应的连接字符串(名称对应的DatabaseVersion 枚举值)那么该版本的测试就不会运行。因为这个,我目前忽略SQL Server 2008 并且在我的机器上只安装了SQL 2005 和SQL 2008R2
为了对当前可用数据库进行过滤,我修改了我的测试用例让基类去运行实际的测试,使用lambda表达式:
<span>[SqlServerTest] </span><span>public</span> <span>void</span><span> HeapForwardedRecord(DatabaseVersion version) { RunDatabaseTest(version, db </span>=><span> { </span><span>var</span> scanner = <span>new</span><span> DataScanner(db); </span><span>var</span> rows = scanner.ScanTable(<span>"</span><span>HeapForwardedRecord</span><span>"</span><span>).ToList(); Assert.AreEqual(</span><span>25</span>, rows[<span>0</span>].Fieldint>(<span>"</span><span>A</span><span>"</span><span>)); Assert.AreEqual(</span><span>""</span>.PadLeft(<span>5000</span>, <span>'</span><span>A</span><span>'</span>), rows[<span>0</span>].Fieldstring>(<span>"</span><span>B</span><span>"</span><span>)); Assert.AreEqual(</span><span>28</span>, rows[<span>1</span>].Fieldint>(<span>"</span><span>A</span><span>"</span><span>)); Assert.AreEqual(</span><span>""</span>.PadLeft(<span>4000</span>, <span>'</span><span>B</span><span>'</span>), rows[<span>1</span>].Fieldstring>(<span>"</span><span>B</span><span>"</span><span>)); }); }</span>
这个RunDatabase 方法在SqlServerSystemTestBase类里面声明
<span>protected</span> <span>void</span> RunDatabaseTest(DatabaseVersion version, Action<database><span> test) { </span><span>string</span> versionConnectionName =<span> version.ToString(); </span><span>//</span><span> Only run test for this version if a connection string has been provided</span> <span>if</span> (ConfigurationManager.ConnectionStrings[versionConnectionName] == <span>null</span><span>) Assert.Inconclusive(); </span><span>//</span><span> Setup database and store file paths, if we haven't done so already</span> <span> ensureDatabaseIsSetup(version); </span><span>//</span><span> Run actual test</span> <span>using</span> (<span>var</span> db = <span>new</span><span> Database(databaseFiles[version])) test(db); }</span></database>
如果对应的连接字符串没有在配置文件里面声明,我们会放弃测试并且会将他标记为不确定的- 根据当前的配置情况我们根本不能运行他。
接下来,ensureDatabaseIsSetup()执行通常的配置代码(详细内容可以参考先前的文章)
尽管这一次每个数据库版本,每个测试固件都需要执行。最后 一个OrcaMDF实例将会被创建并传入实际的测试参数
支持不同SQLSERVER版本的特性
正如前面提到的,我需要针对特定SQLSERVER版本的执行的测试方法。
标准的SqlServerTestAttribute 自动枚举所有的DatabaseVersion enumeration里面的值,不过我没有理由再单独创建一个SqlServer2005TestAttribute 就像这样
<span>public</span> <span>class</span><span> SqlServer2005TestAttribute : TestCaseSourceAttribute { </span><span>private</span> <span>static</span> IEnumerable<testcasedata><span> versions { </span><span>get</span><span> { </span><span>yield</span> <span>return</span> <span>new</span><span> TestCaseData(DatabaseVersion.SqlServer2005).SetCategory(DatabaseVersion.SqlServer2005.ToString()); } } </span><span>public</span> SqlServer2005TestAttribute() : <span>base</span>(<span>typeof</span>(SqlServer2005TestAttribute), <span>"</span><span>versions</span><span>"</span><span>) { } }</span></testcasedata>
那如果需要将测试运行在SQL Server 2008上呢?
<span>public</span> <span>class</span><span> SqlServer2008PlusTestAttribute : TestCaseSourceAttribute { </span><span>private</span> <span>static</span> IEnumerable<testcasedata><span> versions { </span><span>get</span><span> { </span><span>foreach</span> (<span>var</span> value <span>in</span> Enum.GetValues(<span>typeof</span><span>(DatabaseVersion))) </span><span>if</span>((DatabaseVersion)value >=<span> DatabaseVersion.SqlServer2008) </span><span>yield</span> <span>return</span> <span>new</span><span> TestCaseData(value).SetCategory(value.ToString()); } } </span><span>public</span><span> SqlServer2008PlusTestAttribute() : </span><span>base</span>(<span>typeof</span>(SqlServer2008PlusTestAttribute), <span>"</span><span>versions</span><span>"</span><span>) { } }</span></testcasedata>
一旦我们有attributes,那么将会比较容易的对于我们的版本运行单独的测试
<span>[SqlServer2008PlusTest] </span><span>public</span> <span>void</span><span> ScanAllNullSparse(DatabaseVersion version) { RunDatabaseTest(version, db </span>=><span> { </span><span>var</span> scanner = <span>new</span><span> DataScanner(db); </span><span>var</span> rows = scanner.ScanTable(<span>"</span><span>ScanAllNullSparse</span><span>"</span><span>).ToList(); //稀疏列 Assert.AreEqual(</span><span>null</span>, rows[<span>0</span>].Fieldint?>(<span>"</span><span>A</span><span>"</span><span>)); Assert.AreEqual(</span><span>null</span>, rows[<span>0</span>].Fieldint?>(<span>"</span><span>B</span><span>"</span><span>)); }); }</span>
对于ReSharper test runner 的支持
为了运行测试,我们需要ReSharper 6.0 因为ReSharper 5.1不支持TestCaseSource attribute。
一旦你执行了测试,你将会看到下面的测试结果(已经支持SQL Server 2005 & 2008 R2 测试)
每一个测试用例都会自动对多个版本的DatabaseVersion 进行测试(除了解析测试,因为他没有实现SqlServerSystemTestBase 因此不能运行多版本测试)。
因为我没有对 SQL Server 2005作出支持所以大部分对 SQL Server 2005的测试都失败。当我运行测试的时候所有SQL2008的测试都是inconclusive 。
最后,所有对于SQL2008R2的测试都通过了
测试过滤
很明显,我们不能总是对所有版本的SQLSERVER进行测试,那太浪费时间了。其中一种禁用对特定版本的测试的方法就是删除连接字符串。
然而,这样依然会产生不明确的输出,而且总是修改配置文件会很麻烦
不幸的是,ReSharper test runner不支持对使用TestCaseSourceAttribute创建的参数化测试的category 过滤。
我已经在 YouTRACK上面开了一个特性要求,我希望ReSharper团队会考虑将这个特性添加到ReSharper6.1。如果你也觉得这个特性很棒,请考虑投票支持
幸运的是,NUnit test runner 不支持这种过滤。在NUnit test runner里打开OrcaMDF.Core.Tests程序集会给你以下结果
注意在我们运行测试之前,Nunit怎么知道参数化的测试参数的!同时也需要注意Nunit怎么让DifferingRecordFormats 测试只运行在SQL2008或以上 ,
而FGSpecificClusteredAllocation测试只让运行在SQL2005或以上
通过显式选择特定的版本类别,我们可以选择运行某些版本,一旦运行了,没有被选择的类别类别头部的小圆点会变成灰色
可以注意到 运行时间用了89秒,基本上1秒一个测试,98%的时间花费在了lob类型特性的测试上。
由于类别格式,我能够在主要的测试类别上进行选择,从而轻松过滤掉长时间运行的测试项目并只关注快速完成的那些类别。
lob 类型特别需要进行测试因为在数据库启动之前他们涉及大量的磁盘活动,配置表和配置行的创建
展望未来
添加新版本就犹如安装SQLSERVER那样简单,在配置项里添加一个连接字符串,最后,添加SQLSERVER版本名字进去DatabaseVersion 枚举里。就这么多了。
进一步,在某种程度上我需要按顺序测试多种升级途径。基于我自己做的一些测试,一个从SQL Server 2005升级到SQLSERVER2008 R2之后的数据库
可能跟在SQLSERVER2008 R2本地创建的数据库有不同,或者从SQL2008升级到SQL2008R2。因此,我需要测试多种不同的升级途径确保完全的兼容性。
然而,兼容性测试的优先级在我的测试优先级列表里比较低,因为这些兼容性测试会花费很多时间
第十一篇完

MySQL在數據庫和編程中的地位非常重要,它是一個開源的關係型數據庫管理系統,廣泛應用於各種應用場景。 1)MySQL提供高效的數據存儲、組織和檢索功能,支持Web、移動和企業級系統。 2)它使用客戶端-服務器架構,支持多種存儲引擎和索引優化。 3)基本用法包括創建表和插入數據,高級用法涉及多表JOIN和復雜查詢。 4)常見問題如SQL語法錯誤和性能問題可以通過EXPLAIN命令和慢查詢日誌調試。 5)性能優化方法包括合理使用索引、優化查詢和使用緩存,最佳實踐包括使用事務和PreparedStatemen

MySQL適合小型和大型企業。 1)小型企業可使用MySQL進行基本數據管理,如存儲客戶信息。 2)大型企業可利用MySQL處理海量數據和復雜業務邏輯,優化查詢性能和事務處理。

InnoDB通過Next-KeyLocking機制有效防止幻讀。 1)Next-KeyLocking結合行鎖和間隙鎖,鎖定記錄及其間隙,防止新記錄插入。 2)在實際應用中,通過優化查詢和調整隔離級別,可以減少鎖競爭,提高並發性能。

MySQL不是一門編程語言,但其查詢語言SQL具備編程語言的特性:1.SQL支持條件判斷、循環和變量操作;2.通過存儲過程、觸發器和函數,用戶可以在數據庫中執行複雜邏輯操作。

MySQL是一種開源的關係型數據庫管理系統,主要用於快速、可靠地存儲和檢索數據。其工作原理包括客戶端請求、查詢解析、執行查詢和返回結果。使用示例包括創建表、插入和查詢數據,以及高級功能如JOIN操作。常見錯誤涉及SQL語法、數據類型和權限問題,優化建議包括使用索引、優化查詢和分錶分區。

MySQL是一個開源的關係型數據庫管理系統,適用於數據存儲、管理、查詢和安全。 1.它支持多種操作系統,廣泛應用於Web應用等領域。 2.通過客戶端-服務器架構和不同存儲引擎,MySQL高效處理數據。 3.基本用法包括創建數據庫和表,插入、查詢和更新數據。 4.高級用法涉及復雜查詢和存儲過程。 5.常見錯誤可通過EXPLAIN語句調試。 6.性能優化包括合理使用索引和優化查詢語句。

選擇MySQL的原因是其性能、可靠性、易用性和社區支持。 1.MySQL提供高效的數據存儲和檢索功能,支持多種數據類型和高級查詢操作。 2.採用客戶端-服務器架構和多種存儲引擎,支持事務和查詢優化。 3.易於使用,支持多種操作系統和編程語言。 4.擁有強大的社區支持,提供豐富的資源和解決方案。

InnoDB的鎖機制包括共享鎖、排他鎖、意向鎖、記錄鎖、間隙鎖和下一個鍵鎖。 1.共享鎖允許事務讀取數據而不阻止其他事務讀取。 2.排他鎖阻止其他事務讀取和修改數據。 3.意向鎖優化鎖效率。 4.記錄鎖鎖定索引記錄。 5.間隙鎖鎖定索引記錄間隙。 6.下一個鍵鎖是記錄鎖和間隙鎖的組合,確保數據一致性。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

WebStorm Mac版
好用的JavaScript開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Dreamweaver Mac版
視覺化網頁開發工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。