溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》
  • 首頁 > 
  • 教程 > 
  • 開發(fā)技術(shù) > 
  • 編程語言 > 
  • .NET程序員項(xiàng)目開發(fā)必知必會(huì)—Dev環(huán)境中的集成測試用例執(zhí)行時(shí)上下文環(huán)境檢查(實(shí)戰(zhàn))

.NET程序員項(xiàng)目開發(fā)必知必會(huì)—Dev環(huán)境中的集成測試用例執(zhí)行時(shí)上下文環(huán)境檢查(實(shí)戰(zhàn))

發(fā)布時(shí)間:2020-06-22 04:59:52 來源:網(wǎng)絡(luò) 閱讀:2147 作者:王清培 欄目:編程語言

Microsoft.NET 解決方案,項(xiàng)目開發(fā)必知必會(huì)。

從這篇文章開始我將分享一系列我認(rèn)為在實(shí)際工作中很有必要的一些.NET項(xiàng)目開發(fā)的核心技術(shù)點(diǎn),所以我稱為必知必會(huì)。盡管這一些列是使用.NET/C#來展現(xiàn),但是同樣適用于其他類似的OO技術(shù)平臺(tái),這些技術(shù)點(diǎn)可能稱不上完整的技術(shù),但是它是經(jīng)驗(yàn)的總結(jié),是掉過多少坑之后的覺醒,所以有必要花幾分鐘時(shí)間記住它,在真實(shí)的項(xiàng)目開發(fā)中你就知道是多么的有幫助。好了,廢話不說了,進(jìn)入主題。

我們在開發(fā)服務(wù)時(shí)為了調(diào)試方便會(huì)在本地進(jìn)行一個(gè)基本的模塊測試,你也可以認(rèn)為是集成測試,只不過你的測試用例不會(huì)覆蓋到80%以上,而是一些我們認(rèn)為在開發(fā)時(shí)不是很放心的點(diǎn)才會(huì)編寫適當(dāng)?shù)挠美齺頊y試它。

集成測試用例通常有多個(gè)執(zhí)行上下文,對于我們開發(fā)人員來說我們的執(zhí)行上下文通常都在本地,測試人員的上下文在測試環(huán)境中。開發(fā)人員的測試用來是不能夠連接到其他環(huán)境中去的(當(dāng)然視具體情況而定,有些用例很危險(xiǎn)是不能夠亂連接的,本文會(huì)講如何解決),開發(fā)人員運(yùn)行的集成測試用例所要訪問的所有資源、服務(wù)都是在開發(fā)環(huán)境中的。這里依然存在但是,但是為了調(diào)試方便,我們還是需要能夠在必要的時(shí)候連接到其他環(huán)境中去調(diào)試問題,為了能夠真實(shí)的模擬出問題的環(huán)境、可真實(shí)的數(shù)據(jù),我們需要能有一個(gè)這樣的機(jī)制,在需要的時(shí)候我能夠打開某個(gè)設(shè)置讓其能夠切換集成測試運(yùn)行的環(huán)境上下文,其實(shí)說白了就是你所要連接的環(huán)境、數(shù)據(jù)源的連接地址。

本篇文章我們將通過一個(gè)簡單的實(shí)例來了解如何簡單的處理這中情況,這其實(shí)基于對測試用來不斷重構(gòu)后的效果。

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace OrderManager.Test
{
    using ProductService.Contract; 

    /// <summary>
    /// Product service integration tests.
    /// </summary>
    [TestClass]
    public class ProductServiceIntegrationTest
    {
        /// <summary>
        /// service address.
        /// </summary>
        public const string ServiceAddress = "http://dev.service.ProductService/"; 

        /// <summary>
        /// Product service get product by pid test.
        /// </summary>
        [TestMethod]
        public void ProductService_GetProductByPid_Test()
        {
            var serviceInstance = ProductServiceClient.CreateClient(ServiceAddress);
            var testResult = serviceInstance.GetProductByPid(0393844); 

            Assert.AreNotEqual(testResult, null);
            Assert.AreEqual(testResult.Pid, 0393844);
        }
    }
}

這是一個(gè)實(shí)際的集成測試用例代碼,有一個(gè)當(dāng)前測試類共用的服務(wù)地址,這個(gè)地址是DEV環(huán)境的,當(dāng)然你也可以定義其他幾個(gè)環(huán)境的服務(wù)地址,前提是環(huán)境是允許你連接的,那才有實(shí)際意義。

我們來看測試用例,它是一個(gè)查詢方法測試用例,用來對ProductServiceClient.GetProductByPid服務(wù)方法進(jìn)行測試,由于面向查詢的操作是等幕的,不論我們查詢多少次這個(gè)ID的Product,都不會(huì)對數(shù)據(jù)造成影響,但是如果我們測試的是一個(gè)更新或者刪除就會(huì)帶來問題。

在DEV環(huán)境中,測試更新、刪除用例沒有問題,但是如果你的機(jī)器是能夠連接到遠(yuǎn)程某個(gè)生產(chǎn)或者PRD測試上時(shí)會(huì)帶來一定的危險(xiǎn)性,特別是在忙的時(shí)候,加班加點(diǎn)的干進(jìn)度,你很難記住你當(dāng)前的機(jī)器的host配置中是否還連接著遠(yuǎn)程的生產(chǎn)機(jī)器上,或者根本就不需要配置host就能夠連接到某個(gè)你不應(yīng)該連接的環(huán)境上。

這是目前的問題,那么我們?nèi)绾谓鉀Q這個(gè)問題呢 ,我們通過對測試代碼進(jìn)行一個(gè)簡單的重構(gòu)就可以避免由于連接到不該連接的環(huán)境中運(yùn)行危險(xiǎn)的測試用例。

其實(shí)很多時(shí)候,重構(gòu)真的能夠幫助我們找到出口,就好比俗話說的:"出口就在轉(zhuǎn)角處“,只有不斷重構(gòu)才能夠逐漸的保證項(xiàng)目的質(zhì)量,而這種效果是很難得的。

提取抽象基類,對測試要訪問的環(huán)境進(jìn)行明確的定義。

namespace OrderManager.Test
{
    public abstract class ProductServiceIntegrationBase
    {
        /// <summary>
        /// service address.
        /// </summary>
        protected const string ServiceAddressForDev = "http://dev.service.ProductService/"; 

        /// <summary>
        /// service address.
        /// </summary>
        protected const string ServiceAddressForPrd = "http://Prd.service.ProductService/"; 

        /// <summary>
        /// service address.
        /// </summary>
        protected const string ServiceAddressTest = "http://Test.service.ProductService/";
    }
}

對具體的測試類消除重復(fù)代碼,加入統(tǒng)一的構(gòu)造方法。

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace OrderManager.Test
{
    using ProductService.Contract; 

    /// <summary>
    /// Product service integration tests.
    /// </summary>
    [TestClass]
    public class ProductServiceIntegrationTest : ProductServiceIntegrationBase
    {
        /// <summary>
        /// product service client.
        /// </summary>
        private ProductServiceClient serviceInstance; 

        /// <summary>
        /// Initialization test instance.
        /// </summary>
        [TestInitialize]
        public void InitTestInstance()
        {
            serviceInstance = ProductServiceClient.CreateClient(ServiceAddressForDev/*for dev*/);
        } 

        /// <summary>
        /// Product service get product by pid test.
        /// </summary>
        [TestMethod]
        public void ProductService_GetProductByPid_Test()
        {
            var testResult = serviceInstance.GetProductByPid(0393844); 

            Assert.AreNotEqual(testResult, null);
            Assert.AreEqual(testResult.Pid, 0393844);
        } 

        /// <summary>
        /// Product service delete search index test.
        /// </summary>
        [TestMethod]
        public void ProductService_DeleteProductSearchIndex_Test()
        {
            var testResult = serviceInstance.DeleteProductSearchIndex(); 

            Assert.IsTrue(testResult);
        }
    }
}

消除重復(fù)代碼后,我們需要加入對具體測試用例檢查是否能夠連接到某個(gè)環(huán)境中去。我加入了一個(gè)DeleteProductSearchIndex測試用例,該用例是用來測試刪除搜索索引的,這個(gè)測試用例只能夠在本地DEV環(huán)境中運(yùn)行(你可能覺得這個(gè)刪除接口不應(yīng)該放在這個(gè)服務(wù)里,這里只是舉一個(gè)例子,無需糾結(jié))。

為了能夠有一個(gè)檢查機(jī)制能提醒開發(fā)人員你目前連接的地址是哪一個(gè),我們需要借助于測試上下文。

重構(gòu)后,我們看一下現(xiàn)在的測試代碼結(jié)構(gòu)。

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace OrderManager.Test
{
    using ProductService.Contract; 

    /// <summary>
    /// Product service integration tests.
    /// </summary>
    [TestClass]
    public class ProductServiceIntegrationTest : ProductServiceIntegrationBase
    {
        /// <summary>
        /// product service client.
        /// </summary>
        private ProductServiceClient serviceInstance; 

        /// <summary>
        /// Initialization test instance.
        /// </summary>
        [TestInitialize]
        public void InitTestInstance()
        {
            serviceInstance = ProductServiceClient.CreateClient(ServiceAddressForPrd/*for dev*/); 

            this.CheckCurrentTestCaseIsRun(this.serviceInstance);//check current test case .
        } 

        /// <summary>
        /// Product service get product by pid test.
        /// </summary>
        [TestMethod]
        public void ProductService_GetProductByPid_Test()
        {
            var testResult = serviceInstance.GetProductByPid(0393844); 

            Assert.AreNotEqual(testResult, null);
            Assert.AreEqual(testResult.Pid, 0393844);
        } 

        /// <summary>
        /// Product service delete search index test.
        /// </summary>
        [TestMethod]
        public void ProductService_DeleteProductSearchIndex_Test()
        {
            var testResult = serviceInstance.DeleteProductSearchIndex(); 

            Assert.IsTrue(testResult);
        }
    }
}

我們加入了一個(gè)很重要的測試實(shí)例運(yùn)行時(shí)方法InitTestInstance,該方法會(huì)在測試用例每次實(shí)例化時(shí)先執(zhí)行,在方法內(nèi)部有一個(gè)用來檢查當(dāng)前測試用例運(yùn)行的環(huán)境
this.CheckCurrentTestCaseIsRun(this.serviceInstance);//check current test case .,我們轉(zhuǎn)到基類中。

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace OrderManager.Test
{
    public abstract class ProductServiceIntegrationBase
    {
        /// <summary>
        /// service address.
        /// </summary>
        protected const string ServiceAddressForDev = "http://dev.service.ProductService/";

        /// <summary>
        /// get service address.
        /// </summary>
        protected const string ServiceAddressForPrd = "http://Prd.service.ProductService/";

        /// <summary>
        /// service address.
        /// </summary>
        protected const string ServiceAddressTest = "http://Test.service.ProductService/";

        /// <summary>
        /// Test context .
        /// </summary>
        public TestContext TestContext { get; set; } 

        /// <summary>
        /// is check is run for current test case.
        /// </summary>
        protected void CheckCurrentTestCaseIsRun(ProductService.Contract.ProductServiceClient testObject)
        {
            if (testObject.ServiceAddress.Equals(ServiceAddressForPrd))// Prd 環(huán)境,需要小心檢查
            {
                if (this.TestContext.TestName.Equals("ProductService_DeleteProductSearchIndex_Test"))
                    Assert.IsTrue(false, "當(dāng)前測試用例連接的環(huán)境為PRD,請停止當(dāng)前用例的運(yùn)行。");
            }
            else if (testObject.ServiceAddress.Equals(ServiceAddressTest))//Test 環(huán)境,檢查約定幾個(gè)用例
            {
                if (this.TestContext.TestName.Equals("ProductService_DeleteProductSearchIndex_Test"))
                    Assert.IsTrue(false, "當(dāng)前測試用例連接的環(huán)境為TEST,為了不破壞TEST環(huán)境,請停止用例的運(yùn)行。");
            }
        }
    }
    
}

在檢查方法中我們使用簡單的判斷某個(gè)用例不能夠在PRD、TEST環(huán)境下執(zhí)行,雖然判斷有點(diǎn)簡單,但是在真實(shí)的項(xiàng)目中足夠了,簡單有時(shí)候是一種設(shè)計(jì)思想。我們運(yùn)行所有的測試用例,查看各個(gè)狀態(tài)。

.NET程序員項(xiàng)目開發(fā)必知必會(huì)—Dev環(huán)境中的集成測試用例執(zhí)行時(shí)上下文環(huán)境檢查(實(shí)戰(zhàn))

一目了然,更為重要的是它不會(huì)影響你對其他用例的執(zhí)行。當(dāng)你在深夜12點(diǎn)排查問題的時(shí)候,你很難控制自己的眼花、體虛導(dǎo)致的用例執(zhí)行錯(cuò)誤帶來的大問題,甚至是無法挽回的的錯(cuò)誤。

此文獻(xiàn)給那些跟我一樣的.NET程序員們,通過簡單的重構(gòu),我們放開了自己。


作者:王清培

出處:http://wangqingpei557.blog.51cto.com/

本文版權(quán)歸作者和51CTO共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI