精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

測試驅(qū)動開發(fā)上的五大錯誤

開發(fā) 測試
作為一個自由職業(yè)者,我經(jīng)常有機(jī)會能看到各種不同的公司內(nèi)部是如何做開發(fā)工作的,我經(jīng)常吃驚于如此多的公司仍然沒有使用測試驅(qū)動開發(fā)(TDD)。當(dāng)我問“為什么”,回答通常是歸咎于下面的一個或多個常見的錯誤做法,這些錯誤是我在實施驅(qū)動測試開發(fā)中經(jīng)常遇到的。這樣的錯誤很容易犯,我也是受害者。

測試驅(qū)動開發(fā)

我曾經(jīng)寫過很多的糟糕的單元測試程序。很多。但我堅持著寫,現(xiàn)在我已經(jīng)喜歡上了些單元測試。我編寫單元測試的速度越來越快,當(dāng)開發(fā)完程序,我現(xiàn)在有更多的信心相信它們能按照設(shè)計的預(yù)期來運(yùn)行。我不希望我的程序里有bug,很多次,單元測試在很多***的小bug上挽救了我。如果我能這樣并帶來好處,我相信所有的人都應(yīng)該寫單元測試!

作為一個自由職業(yè)者,我經(jīng)常有機(jī)會能看到各種不同的公司內(nèi)部是如何做開發(fā)工作的,我經(jīng)常吃驚于如此多的公司仍然沒有使用測試驅(qū)動開發(fā)(TDD)。當(dāng)我問“為什么”,回答通常是歸咎于下面的一個或多個常見的錯誤做法,這些錯誤是我在實施驅(qū)動測試開發(fā)中經(jīng)常遇到的。這樣的錯誤很容易犯,我也是受害者。我曾合作過的很多公司因為這些錯誤做法而放棄了測試驅(qū)動開發(fā),他們會持有這樣一種觀點(diǎn):驅(qū)動測試開發(fā)“增加了不必要的代碼維護(hù)量”,或“把時間浪費(fèi)在寫測試上是不值得的”。

人們會很合理的推斷出這樣的結(jié)論:

寫了單元測試但沒有起到任何作用,那還不如不寫。

但根據(jù)我的經(jīng)驗,我可以很有信心的說:

單元測試能讓我的開發(fā)更有效率,讓我的代碼更有保障。

帶著這樣的認(rèn)識,下面讓我們看看一些我遇到過/犯過的最常見的在測試驅(qū)動開發(fā)中的錯誤做法,以及我從中學(xué)到的教訓(xùn)。

1、不使用模擬框架

我在驅(qū)動測試開發(fā)上學(xué)到***件事情就是應(yīng)該在獨(dú)立的環(huán)境中進(jìn)行測試。這意味著我們需要對測試中所需要的外部依賴條件進(jìn)行模擬,偽造,或者進(jìn)行短路,讓測試的過程不依賴外部條件。

假設(shè)我們要測試下面這個類中的GetByID方法:

  1. public class ProductService : IProductService  
  2. {  
  3.     private readonly IProductRepository _productRepository;  
  4.      
  5.     public ProductService(IProductRepository productRepository)  
  6.     {  
  7.         this._productRepository = productRepository;  
  8.     }  
  9.      
  10.     public Product GetByID(string id)  
  11.     {  
  12.         Product product =  _productRepository.GetByID(id);  
  13.      
  14.         if (product == null)  
  15.         {  
  16.             throw new ProductNotFoundException();  
  17.         }  
  18.      
  19.         return product;  
  20.     }  

為了讓測試能夠進(jìn)行,我們需要寫一個IProductRepository的臨時模擬代碼,這樣ProductService.GetByID就能在獨(dú)立的環(huán)境中運(yùn)行。模擬出的IProductRepository臨時接口應(yīng)該是下面這樣:

  1. [TestMethod]  
  2. public void GetProductWithValidIDReturnsProduct()  
  3. {  
  4.     // Arrange  
  5.     IProductRepository productRepository = new StubProductRepository();  
  6.     ProductService productService = new ProductService(productRepository);  
  7.      
  8.     // Act  
  9.     Product product = productService.GetByID("spr-product");  
  10.      
  11.     // Assert  
  12.     Assert.IsNotNull(product);  
  13. }  
  14.      
  15. public class StubProductRepository : IProductRepository  
  16. {  
  17.     public Product GetByID(string id)  
  18.     {  
  19.         return new Product()  
  20.         {  
  21.             ID = "spr-product",  
  22.             Name = "Nice Product" 
  23.         };  
  24.     }  
  25.      
  26.     public IEnumerable<Product> GetProducts()  
  27.     {  
  28.         throw new NotImplementedException();  
  29.     }  

現(xiàn)在讓我們用一個無效的產(chǎn)品ID來測試這個方法的報錯效果。

  1. [TestMethod]  
  2. public void GetProductWithInValidIDThrowsException()  
  3. {  
  4.     // Arrange  
  5.     IProductRepository productRepository = new StubNullProductRepository();  
  6.     ProductService productService = new ProductService(productRepository);  
  7.      
  8.     // Act & Assert  
  9.     Assert.Throws<ProductNotFoundException>(() => productService.GetByID("invalid-id"));  
  10. }  
  11.      
  12. public class StubNullProductRepository : IProductRepository  
  13. {  
  14.     public Product GetByID(string id)  
  15.     {  
  16.         return null;  
  17.     }  
  18.      
  19.     public IEnumerable<Product> GetProducts()  
  20.     {  
  21.         throw new NotImplementedException();  
  22.     }  

在這個例子中,我們?yōu)槊總€測試都做了一個獨(dú)立的Repository。但我們也可在一個Repository上添加額外的邏輯,例如:

  1. public class StubProductRepository : IProductRepository   
  2. {   
  3.     public Product GetByID(string id)   
  4.     {   
  5.         if (id == "spr-product")   
  6.         {   
  7.             return new Product()   
  8.             {   
  9.                 ID = "spr-product",   
  10.                 Name = "Nice Product" 
  11.             };   
  12.         }   
  13.      
  14.         return null;   
  15.     }   
  16.      
  17.     public IEnumerable<Product> GetProducts()   
  18.     {   
  19.         throw new NotImplementedException();   
  20.     }   

在***種方法里,我們寫了兩個不同的IProductRepository模擬方法,而在第二種方法里,我們的邏輯變得有些復(fù)雜。如果我們在這些邏輯中犯了錯,那我們的測試就沒法得到正確的結(jié)果,這又為我們的調(diào)試增加了額外的負(fù)擔(dān),我們需要找到是業(yè)務(wù)代碼出來錯還是測試代碼不正確。

你也許還會質(zhì)疑這些模擬代碼中的這個沒有任何用處的 GetProducts()方法,它是干什么的?因為IProductRepository接口里有這個方法,我們不得不加入這個方法以讓程序能編譯通過——盡管在我們的測試中這個方法根本不是我們考慮到對象。

使用這樣的測試方法,我們不得不寫出大量的臨時模擬類,這無疑會讓我們在維護(hù)時愈加頭痛。這種時候,使用一個模擬框架,比如JustMock,將會節(jié)省我們大量的工作。

讓我們重新看一下之前的這個測試?yán)樱@次我們將使用一個模擬框架:

  1. [TestMethod]  
  2. public void GetProductWithValidIDReturnsProduct()  
  3. {  
  4.     // Arrange  
  5.     IProductRepository productRepository = Mock.Create<IProductRepository>();  
  6.     Mock.Arrange(() => productRepository.GetByID("spr-product")).Returns(new Product());  
  7.     ProductService productService = new ProductService(productRepository);  
  8.      
  9.     // Act  
  10.     Product product = productService.GetByID("spr-product");  
  11.      
  12.     // Assert  
  13.     Assert.IsNotNull(product);  
  14. }  
  15.      
  16. [TestMethod]  
  17. public void GetProductWithInValidIDThrowsException()  
  18. {  
  19.     // Arrange  
  20.     IProductRepository productRepository = Mock.Create<IProductRepository>();  
  21.     ProductService productService = new ProductService(productRepository);  
  22.      
  23.     // Act & Assert  
  24.     Assert.Throws<ProductNotFoundException>(() => productService.GetByID("invalid-id"));  

有沒有注意到我們寫的代碼的減少量?在這個例子中代碼量減少49%,更準(zhǔn)確的說,使用模擬框架測試時代碼是28行,而沒有使用時是57行。我們還看到了整個測試方法變得可讀性更強(qiáng)了!

#p#

2、測試代碼組織的太松散

模擬框架讓我們在模擬測試中的生成某個依賴類的工作變得非常簡單,但有時候太輕易實現(xiàn)也容易產(chǎn)生壞處。為了說明這個觀點(diǎn),請觀察下面兩個單元測試,看看那一個容易理解。這兩個測試程序是測試一個相同的功能:

Test #1

  1. TestMethod]  
  2. public void InitializeWithValidProductIDReturnsView()  
  3. {  
  4.     // Arrange  
  5.     IProductView productView = Mock.Create<IProductView>();  
  6.     Mock.Arrange(() => productView.ProductID).Returns("spr-product");  
  7.      
  8.     IProductService productService = Mock.Create<IProductService>();  
  9.     Mock.Arrange(() => productService.GetByID("spr-product")).Returns(new Product()).OccursOnce();  
  10.      
  11.     INavigationService navigationService = Mock.Create<INavigationService>();  
  12.     Mock.Arrange(() => navigationService.GoTo("/not-found"));  
  13.      
  14.     IBasketService basketService = Mock.Create<IBasketService>();  
  15.     Mock.Arrange(() => basketService.ProductExists("spr-product")).Returns(true);  
  16.          
  17.     var productPresenter = new ProductPresenter(  
  18.                                             productView,  
  19.                                             navigationService,  
  20.                                             productService,   
  21.                                             basketService);  
  22.      
  23.     // Act  
  24.     productPresenter.Initialize();  
  25.      
  26.     // Assert  
  27.     Assert.IsNotNull(productView.Product);  
  28.     Assert.IsTrue(productView.IsInBasket);  

Test #2

  1. [TestMethod]  
  2. public void InitializeWithValidProductIDReturnsView()  
  3. {  
  4.     // Arrange     
  5.     var view = Mock.Create<IProductView>();  
  6.     Mock.Arrange(() => view.ProductID).Returns("spr-product");  
  7.      
  8.     var mock = new MockProductPresenter(view);  
  9.      
  10.     // Act  
  11.     mock.Presenter.Initialize();  
  12.      
  13.     // Assert  
  14.     Assert.IsNotNull(mock.Presenter.View.Product);  
  15.     Assert.IsTrue(mock.Presenter.View.IsInBasket);  

我相信Test #2是更容易理解的,不是嗎?而Test #1的可讀性不那么強(qiáng)的原因就是有太多的創(chuàng)建測試的代碼。在Test #2中,我把復(fù)雜的構(gòu)建測試的邏輯提取到了ProductPresenter類里,從而使測試代碼可讀性更強(qiáng)。

為了把這個概念說的更清楚,讓我們來看看測試中引用的方法:

  1. public void Initialize()  
  2. {  
  3.     string productID = View.ProductID;  
  4.     Product product = _productService.GetByID(productID);  
  5.      
  6.     if (product != null)  
  7.     {  
  8.         View.Product = product;  
  9.         View.IsInBasket = _basketService.ProductExists(productID);  
  10.     }  
  11.     else 
  12.     {  
  13.        NavigationService.GoTo("/not-found");  
  14.     }  

這個方法依賴于View, ProductService, BasketService and NavigationService等類,這些類都要模擬或臨時構(gòu)造出來。當(dāng)遇到這樣有太多的依賴關(guān)系時,這種需要寫出準(zhǔn)備代碼的副作用就會顯現(xiàn)出來,正如上面的例子。

請注意,這還只是個很保守的例子。更多的我看到的是一個類里有模擬一、二十個依賴的情況。

下面就是我在測試中提取出來的模擬ProductPresenter的MockProductPresenter類:

  1. public class MockProductPresenter  
  2. {  
  3.     public IBasketService BasketService { get; set; }  
  4.     public IProductService ProductService { get; set; }  
  5.     public ProductPresenter Presenter { get; private set; }  
  6.      
  7.     public MockProductPresenter(IProductView view)  
  8.     {  
  9.         var productService = Mock.Create<IProductService>();  
  10.         var navigationService = Mock.Create<INavigationService>();  
  11.         var basketService = Mock.Create<IBasketService>();  
  12.      
  13.         // Setup for private methods  
  14.         Mock.Arrange(() => productService.GetByID("spr-product")).Returns(new Product());  
  15.         Mock.Arrange(() => basketService.ProductExists("spr-product")).Returns(true);  
  16.         Mock.Arrange(() => navigationService.GoTo("/not-found")).OccursOnce();  
  17.      
  18.         Presenter = new ProductPresenter(  
  19.                                    view,  
  20.                                         navigationService,  
  21.                                         productService,  
  22.                                         basketService);  
  23.     }  

因為View.ProductID的屬性值決定著這個方法的邏輯走向,我們向MockProductPresenter類的構(gòu)造器里傳入了一個模擬的View實例。這種做法保證了當(dāng)產(chǎn)品ID改變時自動判斷需要模擬的依賴。

我們也可以用這種方法處理測試過程中的細(xì)節(jié)動作,就像我們在第二個單元測試?yán)锏腎nitialize方法里處理product==null的情況:

  1. [TestMethod]  
  2. public void InitializeWithInvalidProductIDRedirectsToNotFound()  
  3. {  
  4.     // Arrange  
  5.     var view = Mock.Create<IProductView>();  
  6.     Mock.Arrange(() => view.ProductID).Returns("invalid-product");  
  7.      
  8.     var mock = new MockProductPresenter(view);  
  9.      
  10.     // Act  
  11.     mock.Presenter.Initialize();  
  12.      
  13.     // Assert  
  14.     Mock.Assert(mock.Presenter.NavigationService);  

這隱藏了一些ProductPresenter實現(xiàn)上的細(xì)節(jié)處理,測試方法的可讀性是***重要的。

#p#

3、一次測試太多的項目

看看下面的單元測試,請在不使用“和”這個詞的情況下描述它:

  1. [TestMethod]  
  2. public void ProductPriceTests()  
  3. {  
  4.     // Arrange  
  5.     var product = new Product()  
  6.     {  
  7.         BasePrice = 10m  
  8.     };  
  9.      
  10.     // Act  
  11.     decimal basePrice = product.CalculatePrice(CalculationRules.None);  
  12.     decimal discountPrice = product.CalculatePrice(CalculationRules.Discounted);  
  13.     decimal standardPrice = product.CalculatePrice(CalculationRules.Standard);  
  14.      
  15.     // Assert  
  16.     Assert.AreEqual(10m, basePrice);  
  17.     Assert.AreEqual(11m, discountPrice);  
  18.     Assert.AreEqual(12m, standardPrice);  

我只能這樣描述這個方法:

“測試中計算基價,打折價和標(biāo)準(zhǔn)價是都能否返回正確的值。”

這是一個簡單的方法來判斷你是否一次測試了過多的內(nèi)容。上面這個測試會有三種情況導(dǎo)致它失敗。如果測試失敗,我們需要去找到那個/哪些出了錯。

理想情況下,每一個方法都應(yīng)該有它自己的測試,例如:

  1. [TestMethod]  
  2. public void CalculateDiscountedPriceReturnsAmountOf11()  
  3. {  
  4.     // Arrange  
  5.     var product = new Product()  
  6.     {  
  7.         BasePrice = 10m  
  8.     };  
  9.      
  10.     // Act  
  11.     decimal discountPrice = product.CalculatePrice(CalculationRules.Discounted);  
  12.      
  13.     // Assert  
  14.     Assert.AreEqual(11m, discountPrice);  
  15. }  
  16.      
  17. [TestMethod]  
  18. public void CalculateStandardPriceReturnsAmountOf12()  
  19. {  
  20.     // Arrange  
  21.     var product = new Product()  
  22.     {  
  23.         BasePrice = 10m  
  24.     };  
  25.      
  26.     // Act  
  27.     decimal standardPrice = product.CalculatePrice(CalculationRules.Standard);  
  28.      
  29.     // Assert  
  30.     Assert.AreEqual(12m, standardPrice);  
  31. }  
  32.      
  33. [TestMethod]  
  34. public void NoDiscountRuleReturnsBasePrice()  
  35. {  
  36.     // Arrange  
  37.     var product = new Product()  
  38.     {  
  39.         BasePrice = 10m  
  40.     };  
  41.      
  42.     // Act  
  43.     decimal basePrice = product.CalculatePrice(CalculationRules.None);  
  44.      
  45.     // Assert  
  46.     Assert.AreEqual(10m, basePrice);  

注意這些非常具有描述性的測試名稱。如果一個項目里有500個測試,其中一個失敗了,你能根據(jù)名稱就能知道哪個測試應(yīng)該為此承擔(dān)責(zé)任。

這樣我們可能會有更多的方法,但換來的好處是清晰。我在《代碼大全(第2版)》里看到了這句經(jīng)驗之談:

為方法里的每個IF,And,Or,Case,F(xiàn)or,While等條件寫出獨(dú)立的測試方法。

驅(qū)動測試開發(fā)純粹主義者可能會說每個測試?yán)镏粦?yīng)該有一個斷言。我想這個原則有時候可以靈活處理,就像下面測試一個對象的屬性值時:

  1. public Product Map(ProductDto productDto)  
  2. {  
  3.     var product = new Product()  
  4.     {   
  5.         ID = productDto.ID,  
  6.         Name = productDto.ProductName,  
  7.         BasePrice = productDto.Price  
  8.     };  
  9.      
  10.     return product;  
  11. }  

我不認(rèn)為為每個屬性寫一個獨(dú)立的測試方法進(jìn)行斷言是有必要的。下面是我如何寫這個測試方法的:

  1. [TestMethod]  
  2. public void ProductMapperMapsToExpectedProperties()  
  3. {  
  4.     // Arrange  
  5.     var mapper = new ProductMapper();  
  6.     var productDto = new ProductDto()  
  7.     {  
  8.         ID = "sp-001",  
  9.         Price = 10m,  
  10.         ProductName = "Super Product" 
  11.     };  
  12.      
  13.     // Act  
  14.     Product product = mapper.Map(productDto);  
  15.      
  16.     // Assert  
  17.     Assert.AreEqual(10m, product.BasePrice);  
  18.     Assert.AreEqual("sp-001", product.ID);  
  19.     Assert.AreEqual("Super Product", product.Name);  

#p#

4、先寫程序后寫測試

我堅持認(rèn)為,驅(qū)動測試開發(fā)的意義遠(yuǎn)高于測試本身。正確的實施驅(qū)動測試開發(fā)能巨大的提高開發(fā)效率,這是一種良性循環(huán)。我看到很多開發(fā)人員在開發(fā)完某個功能后才去寫測試方法,把這當(dāng)成一種在提交代碼前需要完成的行政命令來執(zhí)行。事實上,補(bǔ)寫測試代碼只是驅(qū)動測試開發(fā)的一個內(nèi)容。

如果不是按照先寫測試后寫被測試程序的紅,綠,重構(gòu)方法原則,測試編寫很可能會變成一種體力勞動。

如果想培養(yǎng)你的單元測試習(xí)慣,你可以看一些關(guān)于TDD的材料,比如The String Calculator Code Kata。

5、測試的過細(xì)

請檢查下面的這個方法:

  1. public Product GetByID(string id)  
  2. {  
  3.     return _productRepository.GetByID(id);  

這個方法真的需要測試嗎?不,我也認(rèn)為不需要。

驅(qū)動測試純粹主義者可能會堅持認(rèn)為所有的代碼都應(yīng)該被測試覆蓋,而且有這樣的自動化工具能掃描并報告程序的某部分內(nèi)容沒有被測試覆蓋,然而,我們要當(dāng)心,不要落入這種給自己制造工作量的陷阱。

很多我交談過的反對驅(qū)動測試開發(fā)的人都會引用這點(diǎn)來作為不寫任何測試代碼的主要理由。我對他們的回復(fù)是:只測試你需要測試的代碼。我的觀點(diǎn)是,構(gòu)造器,geter,setter等方法沒必要特意的測試。讓我們來加深記憶一下我前面提到的經(jīng)驗論:

為方法里的每個IF,And,Or,Case,F(xiàn)or,While等條件寫出獨(dú)立的測試方法。

如果一個方法里沒有任何一個上面提到的條件語句,那它真的需要測試嗎?

祝測試愉快!

獲取文中的代碼

文中例子的代碼你可以從這里找到。

英文原文:Top 5 TDD Mistakes

譯文鏈接:http://www.aqee.net/top-5-tdd-mistakes/

責(zé)任編輯:林師授 來源: 外刊IT評論
相關(guān)推薦

2024-07-16 08:00:00

Kubernetes開發(fā)

2012-12-18 10:09:26

虛擬化應(yīng)用錯誤

2009-09-14 19:23:45

敏捷開發(fā)

2012-08-02 09:05:59

移動應(yīng)用設(shè)計錯誤

2022-03-15 14:55:34

Kubernetes

2010-07-21 08:51:26

Perl錯誤

2012-02-20 16:45:40

Android開發(fā)新手

2017-12-27 11:48:57

IT管理數(shù)據(jù)中心錯誤

2011-07-28 09:42:14

IT安全虛擬化數(shù)據(jù)泄漏

2019-06-04 10:40:07

2019-03-27 08:27:32

物聯(lián)網(wǎng)IOT技術(shù)

2009-03-05 09:21:04

敏捷開發(fā)XP開源

2023-03-10 09:00:49

Swift開發(fā)者工具

2023-09-12 09:47:38

云計算云管理

2013-08-06 14:20:51

Web

2015-01-14 09:29:35

2011-07-27 10:37:28

IT安全安全錯誤

2019-08-22 10:24:04

物聯(lián)網(wǎng)物聯(lián)網(wǎng)安全IoT

2024-01-03 07:52:10

趨勢云測試驅(qū)動

2018-10-26 08:59:17

Linux開發(fā)工具
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

夜夜爽www精品| 97国产精品久久| 黄色永久免费网站| gogo在线高清视频| 大美女一区二区三区| 91精品国产777在线观看| 88久久精品无码一区二区毛片| 欧美大片1688网站| 亚洲欧美另类综合偷拍| 国产精品一区二区三区不卡 | 91夜夜蜜桃臀一区二区三区| 午夜精品久久久久久久久久久 | 亚洲av无码乱码国产麻豆| 欧美性久久久| 亚洲精品xxx| 国产一级做a爰片久久| 欧美巨大xxxx做受沙滩| 久久久久久久综合色一本| 91九色视频在线| 国产精品一区二区三区四| 天天天综合网| 亚洲毛片一区二区| 中文字幕乱妇无码av在线| 在线天堂新版最新版在线8| 亚洲人成精品久久久久久| 久久综合中文色婷婷| 国产又粗又猛又爽| 久久这里只有| 免费不卡在线观看av| 国产激情在线免费观看| 亚洲男女网站| 色嗨嗨av一区二区三区| 日本黄大片在线观看| 尤物在线视频| 久久久久久99久久久精品网站| 99re在线视频观看| 一区二区视频在线免费观看| 一区二区久久| 欧美激情免费观看| 成人免费毛片xxx| 精品国产视频| 亚洲精品日韩丝袜精品| 成年女人免费视频| 日韩欧美中文字幕一区二区三区| 欧美色网站导航| 国产午夜福利视频在线观看| 2001个疯子在线观看| 亚洲乱码国产乱码精品精的特点| 亚洲mv在线看| 成人午夜影视| 国产日韩精品一区| 欧美在线播放一区二区| 四虎国产精品永远| 97se狠狠狠综合亚洲狠狠| 99理论电影网| 性猛交富婆╳xxx乱大交天津| 久久er精品视频| 国产精品女主播| 一级特黄免费视频| 日韩av在线播放中文字幕| 国产成人综合精品| 国产精品自拍第一页| 久久精品综合| 欧美专区在线播放| 91视频久久久| 日本亚洲天堂网| 国产精品视频成人| 国产精品欧美亚洲| 国产很黄免费观看久久| 亚洲最大福利网| 精品人妻伦一区二区三区久久| 国产在线播精品第三| 亚洲伊人久久大香线蕉av| 国产视频手机在线观看| 岛国一区二区在线观看| 精品国产aⅴ麻豆| 伦理片一区二区三区| 欧美国产精品专区| 亚洲欧美一二三| 欧美videosex性极品hd| 精品成人在线视频| 熟妇人妻无乱码中文字幕真矢织江| 51一区二区三区| 欧美一区二区在线观看| 中文字幕一区二区三区乱码不卡| 人人精品亚洲| 中文字幕日韩综合av| 国产少妇在线观看| 99亚洲视频| 国产成人免费av电影| 国产又爽又黄免费软件| 成人av电影免费在线播放| 欧美精品人人做人人爱视频| 在线播放麻豆| 香蕉乱码成人久久天堂爱免费| 农村妇女精品一二区| 青青在线精品| 亚洲成人网在线观看| 成人午夜福利一区二区| 亚洲大全视频| 欧美在线视频一区二区| 国产精品久久久久久久免费| 成人三级伦理片| 日韩免费av电影| 手机av免费在线| 色婷婷久久久亚洲一区二区三区| 九九九九九伊人| 欧美国产极品| 久久精品国产99国产精品澳门| 日韩精品人妻中文字幕| 久久国产欧美日韩精品| 久久99精品久久久久久久久久| 91在线看片| 午夜一区二区三区视频| 色噜噜狠狠一区二区三区狼国成人| 美女呻吟一区| 美女性感视频久久久| 无码免费一区二区三区| 成人精品在线视频观看| 中文字幕一区二区三区乱码| 玖玖在线播放| 日韩免费成人网| 网站永久看片免费| 久色成人在线| 韩国成人一区| 五月婷婷视频在线观看| 精品婷婷伊人一区三区三| 亚洲调教欧美在线| 国产一区视频在线观看免费| 国产日韩欧美在线视频观看| 午夜国产在线观看| 一区二区三区在线视频免费 | 极品尤物av久久免费看| 欧美日韩系列| 一本大道色婷婷在线| 精品久久久久久最新网址| 一区二区三区四区五区| 久久国内精品视频| 亚洲丰满在线| 欧美性片在线观看| 亚洲视频专区在线| www.欧美色| 久久伊99综合婷婷久久伊| 国产a级片网站| xvideos.蜜桃一区二区| 欧美激情18p| 国产高清精品软件丝瓜软件| 国产精品久久久久久久浪潮网站| 欧美日韩大尺度| 国产精品美女久久久久久不卡| 97香蕉久久超级碰碰高清版| 欧美视频xxx| 午夜伦欧美伦电影理论片| 高清中文字幕mv的电影| 99精品久久| 精品午夜一区二区| 丝袜诱惑一区二区| 亚洲视频免费一区| 毛片在线免费播放| 国产精品第五页| 日本一二区免费| 亚洲高清影视| 99re在线| 亚洲少妇视频| 国产小视频91| 一本色道久久综合熟妇| 1024成人网色www| 在线视频观看一区二区| 午夜精品网站| 国产日韩精品推荐| 色老头在线一区二区三区| 国产婷婷成人久久av免费高清| av一级在线观看| 国产精品网站在线| 五月天丁香花婷婷| 黑人一区二区| 欧美精品尤物在线| 欧美亚洲人成在线| 欧美精品中文字幕一区| 人妻与黑人一区二区三区| 狠狠色狠色综合曰曰| 欧美人与性囗牲恔配| 久久国产精品区| 佐佐木明希av| 任你弄精品视频免费观看| 国产精品久久久久久久7电影| 麻豆视频在线观看免费| 精品国产3级a| 99久久久无码国产精品免费蜜柚| 中文字幕一区二| 亚洲色偷偷色噜噜狠狠99网| 三级在线观看一区二区| 中文字幕日韩精品久久| 国产劲爆久久| 国产精品普通话| 青青青草视频在线| 亚洲人在线观看| 性一交一乱一乱一视频| 一本大道久久a久久精二百| 三级av在线免费观看| www.激情成人| 亚洲涩涩在线观看| 99精品视频免费| 中文字幕欧美人与畜| 欧美亚洲大陆| 成人欧美一区二区三区在线湿哒哒| 国产免费拔擦拔擦8x高清在线人| 中文字幕亚洲自拍| 婷婷开心激情网| 欧美疯狂做受xxxx富婆| 天堂网中文字幕| 亚洲欧美日韩国产综合| 日本爱爱爱视频| 成人av在线一区二区三区| 69久久久久久| 国产日韩免费| 国产一二三四五| 国产一区二区三区四区五区传媒| 国产99在线免费| 欧美成人黄色| 日本一本a高清免费不卡| 日本高清成人vr专区| 曰本色欧美视频在线| 视频二区在线| 欧美成人免费网站| 国产又粗又长又大视频| 欧美亚洲一区三区| 久久黄色精品视频| 亚洲国产日韩综合久久精品| 尤物在线免费视频| 国产精品久久久久久久久久久免费看 | 久久亚洲中文字幕无码| 日韩成人三级| 日本成人黄色免费看| 久久久亚洲欧洲日产| 91精品国产一区二区三区动漫| 涩涩涩在线视频| 久久久久久中文字幕| 中文字幕中文字幕在线中高清免费版 | 这里只有精品视频| 欧美日韩在线中文字幕| 亚洲精品久久久一区二区三区| 国产精品久久久久久免费| 欧美日韩激情一区二区| 中文文字幕一区二区三三| 日本国产一区二区| 成年人av网站| 91国偷自产一区二区使用方法| 中文字幕在线观看视频网站| 亚洲妇熟xx妇色黄| 国产在线一二区| 亚洲大片精品永久免费| 久久亚洲AV无码| 亚洲香肠在线观看| 国产无套在线观看| 天天综合日日夜夜精品| 精品成人久久久| 姬川优奈aav一区二区| 日韩精品――中文字幕| 精品国产成人在线| 国产精品人人人人| 色欧美片视频在线观看在线视频| 一级久久久久久| 欧美日韩精品一区二区| 国产精品无码一区二区桃花视频| 欧美高清一级片在线| 国产欧美一级片| 日韩精品影音先锋| 天堂在线观看视频| 亚洲精品一区二三区不卡| 国产区av在线| 日韩在线观看免费高清| aa在线视频| 97国产精品人人爽人人做| 日韩成人动漫| 成人av资源在线播放| 日韩视频一区二区三区四区| 精品久久蜜桃| 精品视频黄色| 视频一区二区视频| 亚洲韩日在线| 欧美伦理视频在线观看| 国内精品国产成人| 中国xxxx性xxxx产国| 国产日韩欧美综合在线| 国产精品白丝喷水在线观看| 亚洲午夜影视影院在线观看| 美日韩一二三区| 欧美年轻男男videosbes| 性欧美8khd高清极品| 国产婷婷色综合av蜜臀av| 麻豆视频在线| 91精品国产91久久久| 久久亚洲精品人成综合网| 国产麻豆乱码精品一区二区三区 | 亚洲成人a级网| 日本电影一区二区在线观看 | av软件在线观看| 97视频免费看| 亚洲香蕉久久| 久久久久久久久久久久久久一区| 99久久这里只有精品| 欧美日韩黄色一级片| 经典一区二区三区| 中文字幕狠狠干| 亚洲免费色视频| 激情视频网站在线观看| 日韩欧美www| h视频网站在线观看| 欧美精品久久久久久久| 欧美xxxx性| 久久影院理伦片| 亚洲色图网站| www.超碰com| 99re8在线精品视频免费播放| 免费成人深夜蜜桃视频| 狠狠躁天天躁日日躁欧美| 精品人妻一区二区三区日产乱码| 国产亚洲精品久久久久动| 91av久久| 99re在线观看| 亚洲色图插插| av污在线观看| 久久久99久久| 精品成人av一区二区在线播放| 日韩欧美一级二级| 黄色网页在线免费看| 国产精品福利无圣光在线一区| 激情亚洲另类图片区小说区| 国内外成人激情免费视频| 秋霞电影一区二区| 亚洲熟妇无码av| 婷婷久久综合九色综合伊人色| 精品国产亚洲av麻豆| 久久精品人人做人人爽| 成人亚洲免费| 日韩三级电影| 日韩制服丝袜av| av无码av天天av天天爽| 婷婷综合在线观看| 色综合久久久久久| 国内精品模特av私拍在线观看| 中文一区二区三区四区| 亚洲小视频在线播放| 久久99精品久久只有精品| 久久精品三级视频| 在线免费视频一区二区| 国产美女性感在线观看懂色av| 91精品国产沙发| 欧美亚洲色图校园春色| 女人天堂av手机在线| 不卡av电影在线播放| 日本网站免费观看| 亚洲电影在线观看| 咪咪网在线视频| 精品九九九九| 另类天堂av| 亚洲最大成人综合网| 欧美日韩中文国产| gogo在线观看| 国产精品久久久久免费| 一区免费视频| 欧美亚一区二区三区| 91成人免费在线| 2021av在线| 91精品天堂| 亚洲欧洲日本mm| 国产精品亚洲无码| 欧美这里有精品| 日本最新在线视频| 97视频热人人精品| 亚洲伦伦在线| 一色道久久88加勒比一| 欧美色成人综合| 污视频免费在线观看| 国产亚洲一区在线播放 | 一区在线观看免费| 草逼视频免费看| 97香蕉超级碰碰久久免费的优势| 精品国产不卡| 久久发布国产伦子伦精品| 狠狠躁18三区二区一区| 色影视在线观看| 国产高清精品一区| 日韩在线观看一区二区| 亚洲欧美精品aaaaaa片| 亚洲精品国偷自产在线99热| 91精品店在线| 成人免费看片'免费看| 久久精品在这里| aaa级黄色片| 1769国产精品| 天天影视综合| 欧美深性狂猛ⅹxxx深喉| 精品污污网站免费看| 91福利在线免费| 亚洲电影免费| av亚洲产国偷v产偷v自拍| 中文字幕第99页| 国模视频一区二区|