成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

單元測試和集成測試業(yè)務(wù)應(yīng)用程序

Godtoy / 2655人閱讀

摘要:本文主要通過小例子介紹下單元測試,集成測試,測試驅(qū)動(dòng)開發(fā)等概念。在一個(gè)單元測試中,一次只能測試一個(gè)類。在單元測試的基礎(chǔ)上,將所有模塊按照設(shè)計(jì)要求如根據(jù)結(jié)構(gòu)圖組裝成為子系統(tǒng)或系統(tǒng),進(jìn)行集成測試。

本文主要通過小例子介紹下單元測試,集成測試,測試驅(qū)動(dòng)開發(fā)等概念。

切入正文:

單元測試是通過寫代碼來測試代碼的一個(gè)小單位測試方式。在一個(gè)單元測試中,一次只能測試一個(gè)類。例如,如果你正在測試一個(gè)使用類File,而另一個(gè)測試類DummyFile是用來消除對(duì)物理文件系統(tǒng)的需要,單元測試的測試類邏輯應(yīng)該被測試。為了使class實(shí)現(xiàn)從真實(shí)到虛/存根之間切換,接口代替真正的類使用。所以,你的類應(yīng)使用IFile或IDatabase而不是直接使用File和Database。

集成測試,也叫組裝測試或聯(lián)合測試。在單元測試的基礎(chǔ)上,將所有模塊按照設(shè)計(jì)要求(如根據(jù)結(jié)構(gòu)圖)組裝成為子系統(tǒng)或系統(tǒng),進(jìn)行集成測試。例如:正在測試CunsomerData,它依賴于LINQ to SQL數(shù)據(jù)庫連接,在集成測試中,確保能正常調(diào)動(dòng)所有相關(guān)類的方法。

測試驅(qū)動(dòng)開發(fā)(TDD)是單元測試的極端形式??偟脑瓌t是先寫單元測試,然后編寫實(shí)際的代碼。例如,先寫單元測試,測試CustomerData與在沒有真正的代碼類CustomerData。該CustomerData類可能包含類似功能InsertCustomer ,DeleteCustomer , GetCustomer等,它們做的不外乎返回一些虛擬Customer對(duì)象,以滿足單元測試。 一旦單元測試都與虛擬數(shù)據(jù)相連,然后你開始寫的CustomerData實(shí)際代碼,它就會(huì)訪問數(shù)據(jù)庫做真正的處理。編寫真正的代碼后,單元測試并沒有改變測試代碼。TDD要求類被設(shè)計(jì)在沒有直接依賴于其他類中。所有的依賴關(guān)系通過接口。例如,CustomerData不直接使用SqlConnection,而是使用ISqlConnection ,所有的依賴提供給CustomerData構(gòu)造。

使用行為驅(qū)動(dòng)開發(fā)測試

測試的單一方法用于單個(gè)期望是麻煩的。你必須寫更多的測試方法來測試每個(gè)方法的整體行為。此外,在每個(gè)測試方法中,你必須在適當(dāng)環(huán)境下建立測試類,只是為了驗(yàn)證一個(gè)特定的期望方式。
例如:給定一個(gè)空Stack 當(dāng)一個(gè)項(xiàng)目被壓入堆棧和Pop被稱為對(duì)象然后壓入堆棧中的最后一項(xiàng)被返回時(shí),該項(xiàng)目從堆棧中移除,以及任何額外調(diào)用Pop都拋出異常。這里定義完整行為的Pop方法。測試這種行為方法的所有預(yù)期和相關(guān)行為Pop 。

使用BDD單元測試

在第一個(gè)例子中,我們將進(jìn)行單元測試數(shù)據(jù)訪問層。使用LINQ到SQL對(duì)象持久化數(shù)據(jù)訪問層交易緩存在實(shí)體層面。例如,當(dāng)你要加載一個(gè)用戶,它首先檢查高速緩存,看看用戶是否已經(jīng)緩存,如果沒有,它從數(shù)據(jù)庫中加載用戶,然后緩存它。我們來看看PageRepository ,其中所涉及Page實(shí)體持久性。共同創(chuàng)建,讀取,更新和銷毀(CRUD)方法。舉一個(gè)例子方法GetPageById ,需要一個(gè)PageId并加載該P(yáng)age從數(shù)據(jù)庫中。

public class PageRepository : IPageRepository
{
    #region Fields
    private readonly IDropthingsDataContext _database;
    private readonly ICache _cacheResolver;
    #endregion Fields

    #region Constructors
    public PageRepository(IDropthingsDataContext database, ICache cacheResolver)
    {
        this._database = database;
        this._cacheResolver = cacheResolver;
    }
    #endregion Constructors

    #region Methods
    public Page GetPageById(int pageId)
    {
        string cacheKey = CacheSetup.CacheKeys.PageId(pageId);
        object cachedPage = _cacheResolver.Get(cacheKey);

        if (null == cachedPage)
        {
            var page = _database.GetSingle(
                   DropthingsDataContext.SubsystemEnum.Page, 
                    pageId, 
                    LinqQueries.CompiledQuery_GetPageById);
            page.Detach();
            _cacheResolver.Add(cacheKey, page);
            return page;
        }
        else
        {
            return cachedPage as Page;
        }
    } 
}

PageRepository需要IDropthingsDataContext ,這是測試與LINQ to SQL的一個(gè)單位DataContext 。默認(rèn)情況下,LINQ到SQL不會(huì)生成DataContext就是單元測試。你將不得不嘗試做一個(gè)DataContext單元測試。接著,它需要一個(gè)ICache其是與緩存涉及的接口。在這個(gè)例子中,假設(shè)有一個(gè)名為類EnterpriseLibraryCache它將實(shí)現(xiàn)ICache 。

測試及預(yù)期結(jié)果確保:鑒于新PageRepository和一個(gè)空的緩存,當(dāng) GetPageById是帶一個(gè)PageId 。它首先檢查緩存,如果發(fā)現(xiàn)沒有,它從數(shù)據(jù)庫中的網(wǎng)頁中加載,并返回預(yù)期頁面。

public void GetPage_Should_Return_A_Page_from_database_when_cache_is_empty_and_then_caches_it()
{
    var cache = new Mock();
    var database = new Mock();
    IPageRepository pageRepository = new PageRepository(database.Object, cache.Object);
    const int pageId = 1;
    var page = default(Page);
    var samplePage = new Page() { ID = pageId, Title = "Test Page", ...};
    database
        .Expect(d => d.GetSingle(
                              DropthingsDataContext.SubsystemEnum.Page,
                               1, LinqQueries.CompiledQuery_GetPageById))
        .Returns(samplePage);
    "Given PageRepository and empty cache".Context(() =>
        {
            // cache is empty
            cache.Expect(c => c.Get(It.IsAny())).Returns(default(object));
            // It will cache the Page object afte loading from database
            cache.Expect(c =>
                 c.Add(It.Is(cacheKey =>
                       cacheKey == CacheSetup.CacheKeys.PageId(pageId)), 
                      It.Is(cachePage =>
                          object.ReferenceEquals(cachePage, samplePage))))
                .AtMostOnce().Verifiable();
        });
    "when GetPageById is called".Do(() =>
        page = pageRepository.GetPageById(1));
    "it checks in the cache first and finds nothing and then caches it".Assert(() =>
        cache.VerifyAll());
    "it loads the page from database".Assert(() =>
        database.VerifyAll());
    "it returns the page as expected".Assert(() =>
        {
            Assert.Equal(pageId, page.ID);
        });  
}

單元測試的意義何在?

我覺得寫單元測試時(shí),所測試的方法不只是在調(diào)用測試方法。單元測試已經(jīng)確切地知道什么其它的類和方法將被調(diào)用。在上面的例子中,是否使用cache或database是在方法中決定的,所以,可以進(jìn)行邏輯測試。例如,我改變了代碼來使用AspectF庫。這需要代碼變更PageRepository 。更改代碼后,我需要確保PageRepository還是按照預(yù)期的行為。不管我用什么方法的緩存,它不應(yīng)該改變緩存行為:檢查緩存,以確保所請(qǐng)求的對(duì)象是不是已經(jīng)在緩存中,然后從數(shù)據(jù)庫中加載并緩存它。改變方法GetPageById,實(shí)施后AspectF ,如下所示:

public Page GetPageById(int pageId)
{
    return AspectF.Define
        .Cache(_cacheResolver, CacheSetup.CacheKeys.PageId(pageId))
        .Return(() =>
            _database.GetSingle(DropthingsDataContext.SubsystemEnum.Page,
                pageId, LinqQueries.CompiledQuery_GetPageById).Detach());
}

現(xiàn)在,當(dāng)我運(yùn)行單元測試,它表示通過。

它確認(rèn)行為PageRepository沒有改變,盡管它的代碼急劇變化。有了正確的單元測試,即使你在代碼中改變了,只要你的單元測試全部通過,你的系統(tǒng)是沒有問題。接下來讓我們來測試,當(dāng)緩存滿了,它正確地從緩存中返回一個(gè)對(duì)象,而不是不必要的查詢數(shù)據(jù)庫。下面的試驗(yàn)將確保:

[Specification]
public void GetPage_Should_Return_A_Page_from_cache_when_it_is_already_cached()
{
    var cache = new Mock();
    var database = new Mock();
    IPageRepository pageRepository = new PageRepository(database.Object, cache.Object);
    const int pageId = 1;
    var page = default(Page);
    var samplePage = new Page() { ID = pageId, Title = "Test Page",
            ColumnCount = 3, LayoutType = 3, UserId = Guid.Empty, VersionNo = 1,
            PageType = Enumerations.PageTypeEnum.PersonalPage,
            CreatedDate = DateTime.Now };
    "Given PageRepository and the requested page in cache".Context(() =>
    {
        cache.Expect(c => c.Get(CacheSetup.CacheKeys.PageId(samplePage.ID)))
            .Returns(samplePage);
    });
    "when GetPageById is called".Do(() =>
        page = pageRepository.GetPageById(1));            
    "it checks in the cache first and finds the object is in cache".Assert(() => 
    {
        cache.VerifyAll();
    });
    "it returns the page as expected".Assert(() =>
    {
        Assert.Equal(pageId, page.ID);
    });
}

這個(gè)試驗(yàn)是很簡單的。唯一的區(qū)別是在設(shè)置Context ,我們?cè)O(shè)定一個(gè)期望,從緩存請(qǐng)求特定的頁面時(shí),它將返回samplePage對(duì)象。只要其中任何被調(diào)用函數(shù)中有沒有期望設(shè)置,Mock將拋出一個(gè)異常。如果代碼試圖調(diào)用任何database對(duì)象或任何東西上的其他cache對(duì)象時(shí),它會(huì)拋出一個(gè)異常,從而表明它沒有做什么不應(yīng)該做的。

集成測試使用BDD

集成測試意味著你要測試的一些類,它與其它類和基礎(chǔ)設(shè)施集成,如數(shù)據(jù)庫,文件系統(tǒng),郵件服務(wù)器等,當(dāng)你寫一個(gè)集成測試,測試組件的行為應(yīng)該是沒有任何實(shí)物模型。此外,它們提供額外的信心代碼工作,因?yàn)樗斜匦璧慕M件和依賴關(guān)系也被測試。

如何測試業(yè)務(wù)外觀層,業(yè)務(wù)外觀處理數(shù)據(jù)訪問組件和所有其他實(shí)用程序組件的編排。它封裝了用戶操作為一體的商業(yè)運(yùn)作。例如,在Dropthings ,當(dāng)?shù)谝淮稳碌挠脩粼L問,用戶獲得創(chuàng)建默認(rèn)的頁面和窗口小部件。這些頁面和小部件來自一個(gè)模板。有一個(gè)名為[email protected]的用戶擁有默認(rèn)的頁面和窗口小部件。特定用戶的頁面和窗口小部件被復(fù)制到每一個(gè)新用戶中。由于這是一個(gè)復(fù)雜的操作,適合做自動(dòng)化的集成測試。

當(dāng)用戶首次訪問該Default.aspx,該FirstVisitHomePage是呼吁Facade。它通過一個(gè)復(fù)雜的過程來克隆模板頁面、小部件和設(shè)置默認(rèn)用戶設(shè)置等集成測試,將確保如果FirstVisitHomePage被調(diào)用參數(shù)標(biāo)識(shí)一個(gè)新的用戶訪問的站點(diǎn),那么它將返回可以對(duì)用戶創(chuàng)建的默認(rèn)頁面和部件的一個(gè)對(duì)象。因此: 由于之前從來沒有誰訪問過該網(wǎng)站的匿名用戶, 當(dāng)用戶第一次訪問, 然后在準(zhǔn)確的列和位置作為anon_user的網(wǎng)頁新創(chuàng)建的頁面創(chuàng)建的小部件。

public class TestUserVisit
{
  public TestUserVisit()
  {
    Facade.BootStrap();
  }
  /// 
  /// Ensure the first visit produces the pages and widgets defined in the template user
  /// 
  [Specification]
  public void First_visit_should_create_same_pages_and_widgets_as_the_template_user()
  {
    MembershipHelper.UsingNewAnonUser((profile) =>
    {
      using (var facade = new Facade(new AppContext(string.Empty, profile.UserName)))
      {
        UserSetup userVisitModel = null;

        // Load the anonymous user pages and widgets
        string anonUserName = facade.GetUserSettingTemplate()
             .AnonUserSettingTemplate.UserName;
        var anonPages = facade.GetPagesOfUser(facade.GetUserGuidFromUserName(anonUserName));

        "Given anonymous user who has never visited the site before"
           .Context(() => { });

        "when the user visits for the first time".Do(() =>
        {
          userVisitModel = facade.FirstVisitHomePage(profile.UserName,
             string.Empty, true, false);
        });

        "it creates widgets on the newly created page at exact columns and
         positions as the anon user"s pages".Assert(() =>
        {
          anonPages.Each(anonPage =>
          {
            var userPage = userVisitModel.UserPages.First(page =>
                    page.Title == anonPage.Title
                    && page.OrderNo == anonPage.OrderNo
                    && page.PageType == anonPage.PageType);

            facade.GetColumnsInPage(anonPage.ID).Each(anonColumn =>
            {
              var userColumns = facade.GetColumnsInPage(userPage.ID);
              var userColumn = userColumns.First(column =>
                      column.ColumnNo == anonColumn.ColumnNo);
              var anonColumnWidgets = 
                facade.GetWidgetInstancesInZoneWithWidget(anonColumn.WidgetZoneId);
              var userColumnWidgets = 
                facade.GetWidgetInstancesInZoneWithWidget(userColumn.WidgetZoneId);
              // Ensure the widgets from the anonymous user template"s columns are 
              // in the same column and row.
              anonColumnWidgets.Each(anonWidget =>
                 Assert.True(userColumnWidgets.Where(userWidget =>
                  userWidget.Title == anonWidget.Title
                  && userWidget.Expanded == anonWidget.Expanded
                  && userWidget.State == anonWidget.State
                  && userWidget.Resized == anonWidget.Resized
                  && userWidget.Height == anonWidget.Height
                  && userWidget.OrderNo == anonWidget.OrderNo).Count() == 1));
            });
          });
        });
      }
    });
  }

需要進(jìn)一步的解釋:為從模板用戶發(fā)現(xiàn)每個(gè)頁面確保新用戶從模板用戶的頁面的部件獲得完全一樣的頁面。獲得來自新用戶的頁面的窗口小部件比較每個(gè)插件。當(dāng)在做業(yè)務(wù)層的變化對(duì)于每個(gè)插件確保具有相同的名稱,狀態(tài),位置等獨(dú)一無二的部件,我可以運(yùn)行集成測試,以確保關(guān)鍵功能是否按預(yù)期工作完成,而且在整個(gè)業(yè)務(wù)層沒有破損任何地方。 我用xunit.console.exe上運(yùn)行的集成測試測試并生成一個(gè)不錯(cuò)html報(bào)告:

該報(bào)告使用下面的命令行產(chǎn)生:
d:xunitxunit.console.exe
d:trunksrcDropthings.Business.Facade.TestsbinDebugDropthings.Business.Facade.Tests.dll

/html FacadeTest.html

您可以使用GUI xUnit:

使用BDD的單元測試測試驅(qū)動(dòng)開發(fā)
到目前為止,我們已經(jīng)通過代碼編寫測試,但如果你先代碼編寫測試有關(guān)驅(qū)動(dòng)開發(fā)?假設(shè)我們要添加行為:給定一個(gè)PageRepository ,當(dāng) Insert被調(diào)用時(shí),它應(yīng)該在數(shù)據(jù)庫中插入頁面,清除了得到的新頁面,用戶頁面任何緩存集合,返回新插入的頁面。
編寫測試代碼:

[Specification]
public void InsertPage_should_insert_a_page_in_database_and_cache_it()
{
  var cache = new Mock();
  var database = new Mock();
  IPageRepository pageRepository = new PageRepository(database.Object, cache.Object);
  const int pageId = 1;

  var page = default(Page);
  var samplePage = new Page() { ID = pageId, Title = "Test Page", ColumnCount = 3, 
    LayoutType = 3, UserId = Guid.NewGuid(), VersionNo = 1, 
    PageType = Enumerations.PageTypeEnum.PersonalPage, CreatedDate = DateTime.Now };

  database
      .Expect(d => d.Insert(DropthingsDataContext.SubsystemEnum.Page,
          It.IsAny>()))
      .Returns(samplePage);

  "Given PageRepository".Context(() =>
  {
    // It will clear items from cache
    cache.Expect(c => c.Remove(CacheSetup.CacheKeys.PagesOfUser(samplePage.UserId)));
  });

  "when Insert is called".Do(() =>
      page = pageRepository.Insert((newPage) =>
      {
        newPage.Title = samplePage.Title;
        newPage.ColumnCount = samplePage.ColumnCount;
        newPage.LayoutType = samplePage.LayoutType;
        newPage.UserId = samplePage.UserId;
        newPage.VersionNo = samplePage.VersionNo;
        newPage.PageType = samplePage.PageType;
      }));

  ("then it should insert the page in database" +
  "and clear any cached collection of pages for the user who gets the new page" +
  "and it returns the newly inserted page").Assert(() =>
  {
    database.VerifyAll();
    cache.VerifyAll();
    Assert.Equal(pageId, page.ID);
  });      
}

首先,我們將寫一些虛擬代碼PageRepository.Insert方法,返回一個(gè)新的Page。它應(yīng)該會(huì)fail,因?yàn)樗粷M足目前數(shù)據(jù)庫對(duì)象的期望集。如果沒有失敗,則表明我們的測試是錯(cuò)誤的。

public Page Insert(Action populate)
        {
                    return new Page();
        } 

運(yùn)行故障測試結(jié)果如預(yù)期:

TestCase "Given PageRepository when InsertPage is called, then it should insert the
page in databaseand clear any cached collection of pages for the user who gets the
new pageand it returns the newly inserted page"
failed: Moq.MockVerificationException : The following expectations were not met:
IDropthingsDataContext d => d.Insert(Page, null)

at Moq.Mock`1.VerifyAll()
PageRepositoryTest.cs(278,0): at 

Dropthings.DataAccess.UnitTest.PageRepositoryTest.<>c__DisplayClass35.
b__34()

這表明,沒有呼叫database.Insert ,所以測試失敗。我們實(shí)現(xiàn)了TDD的第一步,這是寫一個(gè)測試并使其失敗以來的第一期望沒有正確組件下檢驗(yàn)。
現(xiàn)在添加真正的代碼:

public Page Insert(Action populate)
       {
           var newPage = _database.Insert(
               DropthingsDataContext.SubsystemEnum.Page, populate);
           RemoveUserPagesCollection(newPage.UserId);
           return newPage.Detach();
       }

現(xiàn)在,當(dāng)單元測試是對(duì)的PageRepository ,它通過新的測試,與以往的測試一起:

使用BDD進(jìn)行集成測試測試驅(qū)動(dòng)開發(fā)

如果我們想為集成測試做TDD?我們?nèi)绾蜗葘憸y試代碼,然后寫它與其他組件集成業(yè)務(wù)層的代碼? 我們?nèi)绾螢閃eb層做TDD?方法是一樣的,首先你編寫測試代碼,給出正確的輸入,并期望從中活得輸出,然而,集成測試不應(yīng)該只調(diào)用多帶帶一個(gè)業(yè)務(wù)操作,以確保它能正常工作。集成測試還應(yīng)該確保執(zhí)行其它操作時(shí)出現(xiàn)正確的行為。例如,在測試FirstVisitHomePage 時(shí),期望的是,第一次訪問之后,用戶具有創(chuàng)建的正確頁面。測試代碼通過檢查返回的對(duì)象模型驗(yàn)證這一點(diǎn),但實(shí)際情況是,在第一次訪問后,根據(jù)用戶的返回,他們應(yīng)該看到相同的部件,再次確認(rèn)第一和復(fù)診返回相同的數(shù)據(jù)。

測試如下:

public void Revisit_should_load_the_pages_and_widgets_exactly_the_same()
{
  MembershipHelper.UsingNewAnonUser((profile) =>
  {
    using (var facade = new Facade(new AppContext(string.Empty, profile.UserName)))
    {
      UserSetup userVisitModel = null;
      UserSetup userRevisitModel = null;

      "Given an anonymous user who visited first".Context(() =>
      {
        userVisitModel = facade.FirstVisitHomePage(profile.UserName, ...);
      });

      "when the same user visits again".Do(() =>
      {
        userRevisitModel = facade.RepeatVisitHomePage(profile.UserName, ...);
      });

      "it should load the exact same pages, column and
         widgets as the first visit produced".Assert(() =>
      {
        userVisitModel.UserPages.Each(firstVisitPage =>
        {
          Assert.True(userRevisitModel.UserPages.Exists(page =>
                    page.ID == firstVisitPage.ID));
          var revisitPage = userRevisitModel.UserPages.First(page =>
                     page.ID == firstVisitPage.ID);
          var revisitPageColumns = facade.GetColumnsInPage(revisitPage.ID);
          facade.GetColumnsInPage(firstVisitPage.ID).Each(firstVisitColumn =>
          {
            var revisitColumn = revisitPageColumns.First(column =>
                 column.ID == firstVisitColumn.ID);
            var firstVisitWidgets = facade
               .GetWidgetInstancesInZoneWithWidget(firstVisitColumn.WidgetZoneId);
            var revisitWidgets = facade
               .GetWidgetInstancesInZoneWithWidget(revisitColumn.WidgetZoneId);
            firstVisitWidgets.Each(firstVisitWidget =>
                Assert.True(revisitWidgets.Where(revisitWidget =>
                    revisitWidget.Id == firstVisitWidget.Id).Count() == 1));
          });
        });
      });
    }
  });
}

做集成測試的正確方法是編寫單元測試的對(duì)立面。在單元測試中,這種方法是通過調(diào)用一種方法和存根。在集成測試,你應(yīng)該測試不僅只有一個(gè)操作,而且還執(zhí)行其它相關(guān)操作,以確保測試的操作確實(shí)是它應(yīng)該做的。概括了可能的測試用例分為以下類別:

當(dāng)測試創(chuàng)建新數(shù)據(jù)操作(例如,在數(shù)據(jù)庫中插入行或調(diào)用Web服務(wù)來創(chuàng)建一個(gè)實(shí)體),保證了操作通過適當(dāng)進(jìn)行:

  調(diào)用,通過再次讀取該行或調(diào)用另一個(gè)Web服務(wù),以獲得創(chuàng)建的實(shí)體讀取數(shù)據(jù)等操作。如果數(shù)據(jù)沒有被正確插入(例如,插入子行)應(yīng)該失敗。 這是一個(gè)積極的測試。        
  調(diào)用如果插入成功,例如再次插入同一行會(huì)產(chǎn)生一個(gè)違反約束,將失敗的其它操作。這是一種消極的考驗(yàn)。

當(dāng)測試的操作的更新數(shù)據(jù)(例如,更新數(shù)據(jù)庫中的行),保證了操作的數(shù)據(jù),通過適當(dāng)更新

  調(diào)用使用更新后的數(shù)據(jù),如果沒有正確的更新數(shù)據(jù)會(huì)失敗,例如其它的操作使余額不足的賬戶兩次連續(xù)的匯款后。這是一個(gè)積極的測試。
  如果調(diào)用更新成功,將是失敗的其它操作,例如嘗試使用更新后的相同值約束沖突在數(shù)據(jù)庫中插入新行。這是一種消極的考驗(yàn)。

當(dāng)你測試刪除一些數(shù)據(jù)的操作,保證適當(dāng)?shù)臄?shù)據(jù)刪除

  如果調(diào)用數(shù)據(jù)存在例如重新插入同一行產(chǎn)生一個(gè)違反約束將失敗,其它的操作。
  呼叫,如果數(shù)據(jù)被正確地刪除,例如插入的子行是不存在的行,將是失敗的操作。

在集成測試做正反兩方面的測試,即使你正在做單元測試,以確保測試涵蓋了系統(tǒng)的所有主要行為是很重要的。集成測試的一個(gè)好處是在假設(shè)你自己的代碼已經(jīng)單元測試的基礎(chǔ)設(shè)施不可預(yù)測性超過測試自己的代碼。重要的是盡可能多的從正和負(fù)兩方面盡可能覆蓋以排除基礎(chǔ)設(shè)施變量。

作者信息:
原文作者:Omar Al Zabir
原文鏈接:http://www.codeproject.com/Articles/44276/Unit-Testing-and-Integration-Testing-in-Business-A
翻譯來與Maxleap團(tuán)隊(duì)_云服務(wù)研發(fā)成員:Sunny Zhang
中文翻譯原鏈接:https://blog.maxleap.cn/archives/855

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/8727.html

相關(guān)文章

  • 隨行付微服務(wù)測試單元測試

    摘要:輸出結(jié)果需要人工檢查的測試不是一個(gè)好的單元測試。為了有效的進(jìn)行單元測試,需要遵循一定的方法,通常采用路徑覆蓋法設(shè)計(jì)單元測試用例。 在微服務(wù)架構(gòu)下高覆蓋率的單元測試是保障代碼質(zhì)量的第一道也是最重要的關(guān)口,應(yīng)該持之以恒。 背景 單元測試為代碼質(zhì)量保駕護(hù)航,是提高業(yè)務(wù)質(zhì)量的最直接手段,實(shí)踐證明,非常多的缺陷完全可以通過單元測試來發(fā)現(xiàn),測試金字塔提出者M(jìn)artin Fowler 強(qiáng)調(diào)如果一個(gè)高...

    xiguadada 評(píng)論0 收藏0
  • 詳解Gradle自動(dòng)實(shí)現(xiàn)Android組件化

    摘要:我們一般把自動(dòng)化測試劃分為三種分別是單元測試目的是測試代碼的最小單元。集成測試用來測試一個(gè)完成的組件或子系統(tǒng),確保多個(gè)類之間的交互是否按預(yù)期運(yùn)行。集成測試需要比單元測試需要更長的執(zhí)行時(shí)間,而且更加難以維護(hù),失敗的原因難以診斷。 前言;為什么我們要用Gradle管理組件呢?先來看看Android組件化需要實(shí)現(xiàn)的目標(biāo)按照業(yè)務(wù)邏輯劃分模塊項(xiàng)目模塊能夠單獨(dú)啟動(dòng)測試能夠根據(jù)需求引入或刪除某些業(yè)務(wù)模塊通...

    番茄西紅柿 評(píng)論0 收藏0
  • 再談自動(dòng)化測試——我們?cè)诰帉?em>測試時(shí),應(yīng)該注意什么

    摘要:原則具體包括自動(dòng)化獨(dú)立性可重復(fù)簡單的解釋一下三個(gè)原則單元測試應(yīng)該是全自動(dòng)執(zhí)行的。為了保證單元測試穩(wěn)定可靠且便于維護(hù),需要保證其獨(dú)立性。原則編寫單元測試用例時(shí)為了保證被測模塊的交付質(zhì)量需要符合原則。與設(shè)計(jì)文檔相結(jié)合來編寫單元測試。 本文首發(fā)于泊浮目的專欄:https://segmentfault.com/blog... 背景 最近項(xiàng)目在測試階段陸陸續(xù)續(xù)的測出了一些bug.這個(gè)情況剛出現(xiàn)...

    My_Oh_My 評(píng)論0 收藏0
  • 前端進(jìn)階之路: 前端架構(gòu)設(shè)計(jì)(3) - 測試核心

    摘要:而測試驅(qū)動(dòng)開發(fā)技術(shù)并不只是單純的測試工作。需求向來就是軟件開發(fā)過程中感覺最不好明確描述易變的東西。這里說的需求不只是指用戶的需求,還包括對(duì)代碼 可能很多人和我一樣, 首次聽到前端架構(gòu)這個(gè)詞, 第一反應(yīng)是: 前端還有架構(gòu)這一說呢? 在后端開發(fā)領(lǐng)域, 系統(tǒng)規(guī)劃和可擴(kuò)展性非常關(guān)鍵, 因此架構(gòu)師備受重視, 早在開發(fā)工作啟動(dòng)之前, 他們就被邀請(qǐng)加入到項(xiàng)目中, 而且他們會(huì)跟客戶討論即將建成的平臺(tái)的...

    Karuru 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<