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

Go項目實戰-學會對代碼邏輯層進行BDD測試

開發 項目管理
通過這幾節單元測試實戰的內容大家應該能體會到,我們為項目做好分層設計的一個優點--好測試。每個分層都有具體的職責,每塊代碼的邊界不至于過大,這樣我們做單元測試代碼寫起來會更簡單。

前面兩節我們的單元測試主要集中在對項目基礎設施層的代碼進行單元測試,針對Dao數據操作層我們講解了如何在不實際對項目數據庫進行CURD的情況下使用了sqlmock的方式進行單元測試。而對于外部API對接層則是教會大家用gock實現無侵入的HTTP Mock,對有API請求的代碼進行單元測試。

今天我們更進一步,從項目代碼的基礎設施層來到邏輯層和用戶接口層。邏輯層的代碼肯定更注重邏輯,所以我們在這里會引入goconvey 這個庫實現,讓它幫助我們實現BDD(行為驅動測試),goconvey支持樹形結構方便構造各種場景,讓我們能更容易地基于 goconvey 來組織的單測。本文大綱如下:

圖片圖片

goconvey 的 安裝命令如下:

go get github.com/smartystreets/goconvey

輸入命令后,安裝過程如下所示:

圖片圖片

關于goconvey的使用方法詳解,這里就不在給大家舉簡單的例子進行說明了,還是按照前面幾篇的風格,給大家提供一個我在公眾號上寫的 goconvey 入門詳解。

  • 使用 Go Convey 做BDD測試的入門指南

邏輯層單元測試實戰

我們項目各業務的核心邏輯都主要集中在領域服務 domainservice 中,按照我們為項目做的的單元測試目錄規劃,它的單元測試_test.go 文件都應該放在test/domainservice 目錄中。

.
|---test
|     |---controller    # controller 的測試用例
|     |---dao    # dao 的測試用例
|     |---domainservice # 邏輯層領域服務的測試用例
|     |---library # 外部API對接的測試用例

TestMain 入口設置

依照慣例,在每個要寫單元測試的package中,我門都需要在包內測試的統一入口TestMain中做一些公共基礎性的工作。

我們在TestMain中加上Convey 的SuppressConsoleStatistics和PrintConsoleStatistics,用于在測試完成后輸出測試結果。

package domainservice

import (
    "testing"
    . "github.com/smartystreets/goconvey/convey"
)

func TestMain(m *testing.M) {
// convey在TestMain場景下的入口
 SuppressConsoleStatistics()
 result := m.Run()
// convey在TestMain場景下的結果打印
 PrintConsoleStatistics()
 os.Exit(result)
}

這么設置后,輸出的測試結果會按照單測中Convey書寫的層級分層級顯示,這個輸出結果我會在下面的實戰案例中展示給大家。

注意這里convey包的導入方式使用了 import . 的語法,import . "github.com/smartystreets/goconvey/convey",這樣是為了方便大家直接使用 convey 包中的各種定義,無需再像 convey.Convey 這樣加包前綴。

實戰案例一:密碼復雜度的BDD測試

在案例一種我們找一個相對簡單的工具函數來演示怎么用convey幫助我們組織用例。我們在用戶注冊和重設密碼種使用過一個檢查用戶密碼復雜度的工具函數。

func PasswordComplexityVerify(s string) bool {
var (
  hasMinLen  = false
  hasUpper   = false
  hasLower   = false
  hasNumber  = false
  hasSpecial = false
 )
iflen(s) >= 8 {
  hasMinLen = true
 }
for _, char := range s {
switch {
case unicode.IsUpper(char):
   hasUpper = true
case unicode.IsLower(char):
   hasLower = true
case unicode.IsNumber(char):
   hasNumber = true
case unicode.IsPunct(char) || unicode.IsSymbol(char):
   hasSpecial = true
  }
 }
return hasMinLen && hasUpper && hasLower && hasNumber && hasSpecial
}

接下來我們就給 PasswordComplexityVerify 函數編寫測試用例。

func TestPasswordComplexityVerify(t *testing.T) {
 Convey("Given a simple password", t, func() {
  password := "123456"
  Convey("When run it for password complexity checking", func() {
   result := util.PasswordComplexityVerify(password)
   Convey("Then the checking result should be false", func() {
    So(result, ShouldBeFalse)
   })
  })
 })

 Convey("Given a complex password", t, func() {
  password := "123@1~356Wrx"
  Convey("When run it for password complexity checking", func() {
   result := util.PasswordComplexityVerify(password)
   Convey("Then the checking result should be true", func() {
    So(result, ShouldBeTrue)
   })
  })
 })
}

在這個測試函數中,首先我們從正向和負向兩個方面對函數進行單元測試,正向測試和負向測試都是什么呢,用通俗易懂的文字解釋就是:

  • 正向測試:提供正確的入參,期待被測對象返回正確的結果。
  • 負向測試:提供錯誤的入慘,期待被測對象返回錯誤的結果或者對應的異常。

通過這個例子,正好說一下在使用goconvy的過程中需要注意的幾個點:

  • Convey 可以嵌套的,這樣我們就可以構造出來一條測試的場景路徑,幫助我們寫出BDD風格的單測。
  • Convey 嵌套使用時函數的參數有區別。

最上層Convey 為Convey(description string, t *testing.T, action func())

其他層級的嵌套 Convey 不需要傳入 *testing.T,為Convey(description string, action func())

結合我們在 description 參數中的描述,我們就可以建立起來類似 BDD (行為驅動測試)的語義:

  • Given【給定某些初始條件】

Given a simple passowrd 給定一個簡單密碼

  • When 【當一些動作發生后】
  • When run it for password complexity checking 當對它進行復雜度檢查時
  • Then 【結果應該是】
  • Then the checking result should be false 結果應該是 false

BDD測試中的描述信息通常使用的是Given、When、Then引導的狀語從句,如果喜歡用中文寫描述信息也要記得使用類似語境的句子。

咱們用 go test -v 命令來看看測試運行的效果,我們可以看到輸出的測試結果會按照單測中Convey書寫的層級,分層級顯示。

圖片圖片

實戰案例二:用戶注冊的BDD測試

通過上面一個相對簡單的例子,相信大家對goconvey庫的使用已經有所了解,那么接下來我們再來看一下,怎么為邏輯層中那些復雜的代碼邏輯編寫單元測試。

我選用的是用戶注冊的領域服務方法,來給大家展示為業務邏輯代碼編寫單元測試,整個測試用 goconvey 組織用例的行為路徑,使用 gomonkey 對 RegisterUser 方法中依賴的其他方法進行Mock,整個測試方法的代碼如下:

func TestUserDomainSvc_RegisterUser(t *testing.T) {
 Convey("Given a user for RegisterUser of UserDomainSvc", t, func() {
  givenUser := &do.UserBaseInfo{
   Nickname:  "Kevin",
   LoginName: "kevin@go-mall.com",
   Verified:  0,
   Avatar:    "",
   Slogan:    "Keep tang ping",
   IsBlocked: 0,
   CreatedAt: time.Date(2025, 1, 31, 23, 28, 0, 0, time.Local),
   UpdatedAt: time.Date(2025, 1, 31, 23, 28, 0, 0, time.Local),
  }
  planPassword := "123@1~356Wrx"
var s *dao.UserDao
// 讓UserDao的CreateUser返回Mock數據
  gomonkey.ApplyMethod(s, "CreateUser", func(_ *dao.UserDao, user *do.UserBaseInfo, password string) (*model.User, error) {
   passwordHash, _ := util.BcryptPassword(planPassword)
   userResult := &model.User{
    ID:        1,
    Nickname:  givenUser.Nickname,
    LoginName: givenUser.LoginName,
    Verified:  givenUser.Verified,
    Password:  passwordHash,
    Avatar:    givenUser.Avatar,
    Slogan:    givenUser.Slogan,
    CreatedAt: givenUser.CreatedAt,
    UpdatedAt: givenUser.UpdatedAt,
   }
   return userResult, nil
  })

  Convey("When the login name of user is not occupied", func() {
   gomonkey.ApplyMethod(s, "FindUserByLoginNam", func(_ *dao.UserDao, loginName string) (*model.User, error) {
    returnnew(model.User), nil
   })
   Convey("Then user should be created successfully", func() {
    user, err := domainservice.NewUserDomainSvc(context.TODO()).RegisterUser(givenUser, planPassword)
    So(err, ShouldBeNil)
    So(user.ID, ShouldEqual, 1)
    So(user, ShouldEqual, givenUser)
   })
  })

  Convey("When the login name of user has already been occupied by other users", func() {
   gomonkey.ApplyMethod(s, "FindUserByLoginNam", func(_ *dao.UserDao, loginName string) (*model.User, error) {
    return &model.User{LoginName: givenUser.LoginName}, nil
   })
   Convey("Then the user's registration should be unsuccessful", func() {
    user, err := domainservice.NewUserDomainSvc(context.TODO()).RegisterUser(givenUser, planPassword)
    So(user, ShouldBeNil)
    So(err, ShouldNotBeNil)
    So(err, ShouldEqual, errcode.ErrUserNameOccupied)
   })
  })
 })
}

在這個測試方法中,我在頂層Convey中嵌套了兩個并列的Convey方法來組織正向和負向的單元測試,之所以不跟上面那個案例一樣寫兩個并列的頂層Convey方法是因為被測方法 RegisterUser 的入參數太難構造,這也正好給大家展示了我們使用Convey設計單元測試的行為路徑時的靈活性。

這里我們提供了兩個測試用例,正向用例中讓 RegisterUser 依賴的Dao方法 CreateUser 返回創建成功的結果,預期 RegisterUser 返回正確的結果。

而負向用例中則讓 CreateUser 返回用戶名在數據庫中已存在時返回的結果,同時預期 RegisterUser 會返回用戶名已被占用的錯誤 errcode.ErrUserNameOccupied 。

最后咱們用 go test -v命令來看看測試運行的效果:

圖片圖片

Controller 的單元測試

到現在為止我們的單元測試實戰案例已經覆蓋了數據訪問Dao層、API對接層和領域服務層。還剩下一個用戶接口層沒有涉及到,即項目的Controller方法該怎么做單元測試呢?

首先我覺得,按照我們項目的分層架構來說Controller是負責接受和驗證請求和調用下層拿到結果返回響應的,在這里包含核心業務邏輯。如果我們能把它依賴的下層的單元測試做到位,Controller的單元測試可以不做。

不過我們知道有個驗證項目質量的數據指標叫:測試覆蓋率,這個指標肯定越高越好,所以這里我在簡單地把Controller 處理函數的單元測試給大家過一下。

在 Web 項目中 Controller 里都是API接口的請求處理函數,為它們編寫單元測試需要用到Go自帶的net/http/httptest包, 它可以mock一個HTTP請求和響應記錄器,讓我們的 server 端接收并處理我們 mock 的HTTP請求,同時使用響應記錄器來記錄 server 端返回的響應內容。

這里我們那用戶登陸這個接口給大家演示它的Controller函數是怎么做單元測試的,它的單元測試如下。

func TestLoginUser(t *testing.T) {
 Convey("Given right login name and password", t, func() {
  loginName := "yourName@go-mall.com"
  password := "12Qa@6783Wxf3~!45"

  Convey("When use them to Login through API /user/login", func() {
   var s *appservice.UserAppSvc
   gomonkey.ApplyMethod(s, "UserLogin", func(_ *appservice.UserAppSvc, _ *request.UserLogin) (*reply.TokenReply, error) {
    LoginReply := &reply.TokenReply{
     AccessToken:   "70624d19b6644b0bbf8169f51fb5a91f132edebc",
     RefreshToken:  "d16e22fef5cb7f6c69355c9a3c6ce8d1d3b37a84",
     Duration:      7200,
     SrvCreateTime: "2025-02-01 15:34:35",
    }
    return LoginReply, nil
   })

   var b bytes.Buffer
   json.NewEncoder(&b).Encode(map[string]string{"login_name": loginName, "password": password})
   req := httptest.NewRequest(http.MethodPost, "/user/login", &b)
   req.Header.Set("platform", "H5")
   gin.SetMode(gin.ReleaseMode) // 不讓它在控制臺里輸出路由信息
   g := gin.New()
   router.RegisterRoutes(g)
   // mock一個響應記錄器
   w := httptest.NewRecorder()
   // 讓server端處理mock請求并記錄返回的響應內容
   g.ServeHTTP(w, req)

   Convey("Then the user will login successfully", func() {
    So(w.Code, ShouldEqual, http.StatusOK)
    // 檢驗響應內容是否復合預期
    var resp map[string]interface{}
    json.Unmarshal([]byte(w.Body.String()), &resp)
    respData := resp["data"].(map[string]interface{})
    So(respData["access_token"], ShouldNotBeEmpty)
   })
  })
 })

在這個單元測試中我們還是會用 goconvey來組織測試的行為路徑,用 gomonkey 給Controller函數調用的應用服務方法做打樁返回Mock結果,不然就跟用POSTMAN 請求接口一樣咧,那樣的話如果下層代碼里有數據庫CURD更新之類操作的話還是會去實際訪問數據庫的,這顯然不是我們想要的。

對于Controller方法的驗證主要聚焦于請求參數的驗證以及響應結果的驗證,因為 Controller 在我們項目的分層設計中就只干這兩件事。

總結

通過這幾節單元測試實戰的內容大家應該能體會到,我們為項目做好分層設計的一個優點--好測試。每個分層都有具體的職責,每塊代碼的邊界不至于過大,這樣我們做單元測試代碼寫起來會更簡單。如果把所有邏輯都耦合在Controller 函數那種代碼,寫單元測試的難度先不說,有效性也很難保證,因為測試的顆粒度太大必然導致很難測出代碼內部的問題。

責任編輯:武曉燕 來源: 網管叨bi叨
相關推薦

2025-04-28 01:55:00

工具sqlmockSQL

2024-12-05 09:13:55

Go項目模塊

2025-05-07 09:06:03

2021-07-28 08:53:53

GoGDB調試

2024-02-21 19:02:05

Go模板化方式

2022-09-27 09:21:34

SOLID開閉原則Go

2023-04-26 00:41:36

A/B測試郵件數量

2022-01-17 07:50:37

Go代碼規范

2023-05-26 00:06:05

2015-06-15 11:45:55

2021-11-29 22:59:34

Go Dockertest集成

2025-03-20 07:01:40

2025-03-28 07:50:00

端到端測試Go語言

2020-09-27 14:00:44

代碼

2021-07-02 17:22:50

前端TDDBDD

2024-02-21 19:56:48

??filterA并發計算

2022-11-09 07:18:18

驅動測試BDD

2022-08-30 09:57:28

項目傳統對象訪問

2022-07-19 08:01:55

函數Go格式化

2016-08-31 09:19:57

點贊
收藏

51CTO技術棧公眾號

国产精品久久精品国产| 国产在线日韩精品| 黄色工厂这里只有精品| 欧美性猛xxx| 亚洲综合日韩在线| 污污视频网站在线免费观看| 亚洲国产精彩视频| 波多野结衣的一区二区三区 | 蜜臀av一级做a爰片久久| 欧美xxxx在线观看| 色中文字幕在线观看| 精品一区二三区| 欧美黄色录像| 亚洲成人精品在线观看| 粉嫩精品一区二区三区在线观看| 国产精品久久久免费看| 日韩欧美一区二区三区在线观看| 91色九色蝌蚪| 91av在线播放| 成人免费无码大片a毛片| 8x8ⅹ拨牐拨牐拨牐在线观看| 99久久99热这里只有精品 | 黄色成人在线免费观看| 99久久久久久久| 99re6这里只有精品| 在线精品亚洲一区二区不卡| 玖玖玖精品中文字幕| 日韩av在线播| 啪啪激情综合网| 8x8x8国产精品| www.黄色网址.com| 国产欧美第一页| 日韩成人一级大片| 日韩在线小视频| 国产又黄又猛的视频| 黄色在线免费看| 国产精品主播直播| 久久久久久999| a视频免费观看| 日韩电影免费观看高清完整版| 久久久美女毛片| 国产精品久久久久久久久久| 青青青手机在线视频| 妖精视频一区二区三区免费观看| 欧美性xxxx极品高清hd直播| 久久人人爽人人爽人人av| 色欲av伊人久久大香线蕉影院| 国产午夜久久| 在线观看视频亚洲| 6080国产精品| 成人免费图片免费观看| 久久青草国产手机看片福利盒子 | 日韩中文一区| 一区二区不卡视频在线观看| 欧美在线二区| 亚洲精品ady| www.超碰com| 毛片av在线| av中文字幕一区| 国产精品久久久久久影视| 国产精品白丝喷水在线观看| 国产精品高潮呻吟久久久久| 91国偷自产一区二区使用方法| 影音先锋在线亚洲| 三级网站在线看| 懂色中文一区二区在线播放| 国产成人欧美在线观看| 精品国产精品国产精品| 色天下一区二区三区| 欧美日韩高清一区二区三区| 天天夜碰日日摸日日澡性色av| 韩国三级在线观看久| 国产在线播放一区| 日本国产高清不卡| 免看一级a毛片一片成人不卡| 国产日产一区 | 欧美成人xxx| 亚洲三级视频在线观看| 精品一卡二卡三卡四卡日本乱码| 在线免费看毛片| 一区二区三区导航| 欧美精品在线看| 日本一二三不卡视频| 国产精品17p| 亚洲男人第一av网站| 免费观看黄网站| 成人精品电影在线| 亚洲天堂2016| 国产曰肥老太婆无遮挡| 五月天av在线| 亚洲一区二区精品久久av| 日本精品一区| 少妇人妻精品一区二区三区| 久久亚洲一区二区三区四区| 中文字幕久久一区| a√中文在线观看| 欧美色网站导航| 欧美 日本 亚洲| 久久免费电影| 亚洲激情网站免费观看| 在线国产精品网| 黑森林国产精品av| 欧美人xxxx| 欧美视频亚洲图片| 蜜桃成人av| 日韩精品极品在线观看播放免费视频| 97免费公开视频| 国产欧美日韩影院| 久久久久久尹人网香蕉| 亚洲图片视频小说| 99re这里只有精品6| 国内一区在线| 天天摸天天干天天操| 中文欧美字幕免费| 日本一区二区精品视频| av色综合久久天堂av色综合在| 国产精品久久免费看| 亚洲不卡1区| 亚洲成人精品女人久久久| 久久精品欧美日韩精品| 日韩在线导航| av蜜臀在线| 日韩一区二区三区在线观看| 免费看91视频| 粉嫩精品导航导航| 日韩中文字幕在线| 一区视频免费观看| 日本午夜精品视频在线观看| 国产精品一区久久久| 91在线公开视频| 性高潮久久久久久| 日韩久久综合| 欧美成人合集magnet| 国产裸体美女永久免费无遮挡| 91原创在线视频| 男女啪啪免费视频网站| 在线高清av| 亚洲第一中文字幕在线观看| 特大黑人巨人吊xxxx| 欧美女激情福利| 97香蕉超级碰碰久久免费软件| 欧美性猛交bbbbb精品| 日韩1区2区3区| 久久涩涩网站| 在线观看h片| 中文字幕二三区不卡| 日日鲁鲁鲁夜夜爽爽狠狠视频97| 桃色一区二区| 亚洲欧美国产精品| 日本中文字幕第一页| 精品制服美女久久| 韩国成人一区| аⅴ资源天堂资源库在线| 精品国产乱码久久| 久久久久久国产精品无码| 欧美r级电影| 国产精品免费久久久| 成年人视频在线免费观看| 亚洲欧美激情小说另类| 黄色免费视频大全| 欧美亚洲色图校园春色| 2025国产精品视频| 中文在线最新版天堂| 国产成人免费视频一区| 欧美性bbwbbwbbwhd| 国产美女福利在线| 91精品国产综合久久福利| 国产精品亚洲无码| 视频在线在亚洲| 成人精品一二区| 国产区av在线| 亚洲曰韩产成在线| 中国黄色片免费看| 狼人精品一区二区三区在线 | av一区二区在线看| 菠萝蜜视频在线观看www入口| 色婷婷久久久久swag精品| 女人扒开双腿让男人捅 | 欧美人与性动交a欧美精品| 毛片毛片女人毛片毛片| 91麻豆国产香蕉久久精品| 激情综合网俺也去| 亚洲精品网址| 国产精品久久网| 成人在线观看免费网站| 在线精品国精品国产尤物884a| 国产精品成人在线视频| 国产经典欧美精品| 欧美性大战久久久久xxx| 大片网站久久| 国产精品三区www17con| 怡红院成人在线| 不卡伊人av在线播放| 日本一区二区三区久久| 1000精品久久久久久久久| 精品久久久噜噜噜噜久久图片| 91日韩免费| 国产在线欧美日韩| 九九热这里有精品| 中文亚洲视频在线| 中文字幕手机在线视频| 26uuu国产日韩综合| 日本肉体xxxx裸体xxx免费| 国产一区二区三区四区二区| 亚洲精品免费在线视频| 亚洲精品一区| 久久97精品久久久久久久不卡| 精品乱码一区二区三四区视频 | 中文字幕av不卡在线| 在线看片一区| 国产精品日韩高清| 欧美爱爱视频| 97视频在线播放| 国产二区三区在线| 一区二区三区 在线观看视| 人成网站在线观看| 黄色成人在线播放| 国产美女喷水视频| 日日夜夜精品免费视频| 欧美国产视频一区| 久久夜色电影| 99免费在线观看视频| 国产成人午夜性a一级毛片| 一本色道久久88综合日韩精品| 不卡的日韩av| 五月婷婷综合网| 国产熟妇久久777777| 粉嫩嫩av羞羞动漫久久久| 免费av不卡在线| 天堂蜜桃91精品| 男人操女人逼免费视频| 欧美久久一区| 白白操在线视频| 欧美一区二区三区另类| 正在播放一区| 日韩激情一区| 亚洲电影网站| 日本久久精品| 亚洲二区三区四区| 日韩三级在线| 一本色道久久综合亚洲精品婷婷| 精品入口麻豆88视频| 欧美激情a在线| 日本大片在线观看| 欧美人妇做爰xxxⅹ性高电影| 91porny九色| 日本韩国一区二区| wwwwww在线观看| 欧美性生交片4| 久久久久久久久久久网 | 日韩一级视频免费观看在线| 国产精品午夜福利| 激情av一区二区| 日韩精品一卡二卡| 欧美日韩一区二区免费在线观看| 91网站免费视频| 国产亚洲一二三区| 亚洲午夜精品久久久久久高潮| 国产高清精品网站| aaaaa黄色片| 粉嫩av亚洲一区二区图片| 亚洲成a人无码| 日韩av中文字幕一区二区 | 国产麻豆精品theporn| 99国产精品免费视频| 懂色av中文一区二区三区 | 高清精品xnxxcom| 粉嫩av四季av绯色av第一区| 三级小说欧洲区亚洲区| 日韩欧美亚洲精品| 午夜国产一区二区| av日韩在线看| 久久精品男女| 欧美日韩视频免费| 99热这里只有成人精品国产| 欧美少妇性生活视频| 亚洲精品123区| 五月天男人天堂| 国模一区二区三区| 日韩毛片在线免费看| 麻豆国产一区二区| 男人天堂999| 老司机精品视频导航| 在线免费黄色小视频| 欧美aaaaa成人免费观看视频| 亚洲综合激情视频| 99视频有精品| gv天堂gv无码男同在线观看| 亚洲激情自拍视频| 国产亚洲欧美在线精品| 欧美一区二区三区四区在线观看| 无码精品黑人一区二区三区| 精品免费国产二区三区 | 日本在线视频一区二区三区| 国产精品精品视频| 91久久偷偷做嫩草影院电| 国产精品wwwwww| 美女精品久久| 视频一区二区三区免费观看| 欧美精品国产| 亚洲人辣妹窥探嘘嘘| av电影在线观看一区| 女人18毛片毛片毛片毛片区二| 国产精品美女久久久久aⅴ| 精品97人妻无码中文永久在线| 色菇凉天天综合网| 六月婷婷综合网| 亚洲国产成人久久| 97人人在线| 日本久久久a级免费| av资源亚洲| 国产成人+综合亚洲+天堂| 日韩精品视频一区二区三区| 少妇免费毛片久久久久久久久| 亚洲成色精品| 精品人妻一区二区三区免费| 欧美激情综合在线| 奇米网一区二区| 精品国产31久久久久久| a天堂中文在线观看| 日韩视频在线永久播放| 高清在线观看av| 4388成人网| 超碰97久久| 国风产精品一区二区| 欧美三级网页| 国产5g成人5g天天爽| 国产精品福利影院| 2025国产精品自拍| 欧美亚洲一区三区| 欧美女同网站| 日韩中文在线不卡| 惠美惠精品网| 久久久久久久有限公司| 亚洲狼人精品一区二区三区| 色欲欲www成人网站| 亚洲欧美日韩在线播放| 91午夜交换视频| 俺去了亚洲欧美日韩| 欧美黑粗硬大| 正在播放久久| 国产一区在线不卡| 欧美手机在线观看| 欧美一区二区私人影院日本| 麻豆传媒在线完整视频| 91精品久久久久久久久久入口| 亚洲日本va中文字幕| 黄色录像特级片| 国产河南妇女毛片精品久久久| 久久精品一级片| 337p日本欧洲亚洲大胆精品| av人人综合网| 欧美成人免费在线| 日韩国产精品久久久| 山东少妇露脸刺激对白在线| 欧美日韩国产不卡| 91小视频xxxx网站在线| 春色成人在线视频| 伊人精品视频| 亚洲理论片在线观看| 一区二区三区免费在线观看| 精品人妻一区二区三区三区四区| 欧美日韩国产二区| 麻豆一区二区| 国产第一页视频| 国产精品久久久久久久岛一牛影视 | 精品人人视频| 日本在线一区| 国产一区二区三区久久久| 久久久久97国产| 国产丝袜一区二区| 日本在线观看高清完整版| 国产精品成人国产乱一区| 成人3d动漫在线观看| 婷婷中文字幕在线观看| 亚洲一级二级三级| 三级在线视频| 91精品啪aⅴ在线观看国产| 免费久久精品| 亚洲一区二区福利视频| 国产亚洲一本大道中文在线| 在线视频1卡二卡三卡| 欧美激情精品久久久久久大尺度| 日韩欧美黄色| 911福利视频| 午夜精品视频一区| av影片免费在线观看| 成人av免费看| 蜜桃一区二区三区在线| 久久久久亚洲AV成人| 欧美日韩国产综合视频在线观看| av片在线观看免费| 蜜桃视频在线观看91| 国内精品久久久久影院色| 美女福利视频网| 亚洲激情国产精品| 亚洲国产91视频| 影音先锋在线亚洲| 91丨porny丨中文| 国产特级黄色片|