pytest測(cè)試框架(三)

pytest.fixture

  • setup和teardown函數(shù)能夠在測(cè)試用例之前或者之后添加一些操作靠抑,但這種是整個(gè)腳本全局生效的违施。
  • 如果我們想實(shí)現(xiàn)以下場(chǎng)景:用例1需要登錄,用例2不需要登錄,用例3需要登錄,這就無(wú)法直接用setup和teardown來(lái)同一個(gè)類中實(shí)現(xiàn)泡一,卻可以通過pytest.fixture實(shí)現(xiàn)。

fixture基本使用

fixture是pytest特有的功能觅廓,它以裝飾器形式定義在函數(shù)上面鼻忠, 在編寫測(cè)試函數(shù)的時(shí)候,可以將被fixture裝飾的函數(shù)的名字做為測(cè)試函數(shù)的參數(shù)杈绸,運(yùn)行測(cè)試腳本時(shí)帖蔓,執(zhí)行測(cè)試函數(shù)時(shí)就會(huì)自動(dòng)傳入被fixture裝飾的函數(shù)的返回值矮瘟。

import pytest
import requests

# 0.@pytest.fixture裝飾函數(shù)
@pytest.fixture()
def get_web_url():
    print('get_web_url')
    return 'https://www.baidu.com'

# 1. 把上面函數(shù)名作為測(cè)試用例的參數(shù)
def test_web(get_web_url):
    # 2. 測(cè)試用例調(diào)用前,需要先確定形參get_web_url塑娇,就是調(diào)用get_web_url
    print('test_web')
    print(get_web_url) # 測(cè)試用例內(nèi)部使用get_web_url澈侠,就是使用它返回值
    r = requests.get(get_web_url)
    assert r.status_code == 200, '測(cè)試成功'

運(yùn)行結(jié)果如下:

plugins: tavern-1.16.3, openfiles-0.3.2, arraydiff-0.3, allure-pytest-2.9.45, doctestplus-0.3.0, remotedata-0.3.1
collected 1 item                                                                                                                                          

pytest_code5.py get_web_url
test_web
https://www.baidu.com
.

==================================================================== 1 passed in 0.19s ====================================================================

conftest.py文件

共享fixture函數(shù)

  • 如果在測(cè)試中多個(gè)測(cè)試文件中用例用到同一個(gè)的fixture函數(shù),則可以將其移動(dòng)到conftest.py文件中埋酬,所需的fixture對(duì)象會(huì)自動(dòng)被pytest發(fā)現(xiàn)哨啃,而不需要再每次導(dǎo)入

  • conftest.py文件名固定

  • 在conftest.py文件中實(shí)現(xiàn)共用的fixture函數(shù)

conftest.py內(nèi)容如下:

# pytest_fixture/conftest.py 文件名不能改變,否則無(wú)效
import pytest

# 默認(rèn)是function級(jí)別的
@pytest.fixture()
def login_fixture():
    """可以把函數(shù)作為參數(shù)傳遞"""
    print("\n公用的登陸方法")

test_fixture1.py內(nèi)容如下:

# pytest_fixture/test_fixture1.py
import pytest

def test_get_carts():
    """購(gòu)物車不需要登陸"""
    print("\n測(cè)試查詢購(gòu)物車,無(wú)需登錄")


class TestFixtures(object):
    """需要登陸的信息"""
    def test_get_user_info(self, login_fixture):
        print("獲取用戶信息")

    def test_order_info(self, login_fixture):
        print("查詢訂單信息")

def test_logout(login_fixture):
    """登出"""
    print("退出登錄")

if __name__ == '__main__':
    pytest.main(['-s', 'test_fixture1.py'])

運(yùn)行結(jié)果如下:

test_fixture1.py .
測(cè)試查詢購(gòu)物車奇瘦,無(wú)需登錄

公用的登陸方法
.獲取用戶信息

公用的登陸方法
.查詢訂單信息

公用的登陸方法
.退出登錄
                                                    [100%]

============================== 4 passed in 0.03s ===============================

pytest.mark.usefixtures

  • 可以使用@pytest.mark.usefixtures('fixture函數(shù)名字符串')來(lái)裝飾測(cè)試類和測(cè)試方法
    test_fixture2.py內(nèi)容如下:
# pytest_fixture/test_fixture2.py
import pytest

def test_get_carts():
    """購(gòu)物車不需要登陸"""
    print("\n測(cè)試查詢購(gòu)物車棘催,無(wú)需登錄")

@pytest.mark.usefixtures('login_fixture')
class TestFixtures(object):
    """需要登陸的信息"""
    def test_get_user_info(self):
        print("獲取用戶信息")

    def test_order_info(self):
        print("查詢訂單信息")

@pytest.mark.usefixtures('login_fixture')
def test_logout():
    """登出"""
    print("退出登錄")

if __name__ == '__main__':
    pytest.main(['-s', 'test_fixture2.py'])

右鍵運(yùn)行如下:

test_fixture2.py .
測(cè)試查詢購(gòu)物車劲弦,無(wú)需登錄

公用的登陸方法
.獲取用戶信息

公用的登陸方法
.查詢訂單信息

公用的登陸方法
.退出登錄
                                                    [100%]

============================== 4 passed in 0.03s ===============================

pytest.fixture參數(shù)

pytest.fixture(scope='function', params=None, autouse=False, ids=None, name=None)
  • scope: 被標(biāo)記方法的作用域耳标, 可以傳入以下四個(gè)值;
    -- "function": 默認(rèn)值,每個(gè)測(cè)試用例都要執(zhí)行一次 fixture 函數(shù)
    -- "class": 作用于整個(gè)類邑跪, 表示每個(gè)類只運(yùn)行一次 fixture 函數(shù)
    -- "module": 作用于整個(gè)模塊次坡, 每個(gè) module 的只執(zhí)行一次 fixture 函數(shù)
    -- "session": 作用于整個(gè) session , 一次 session 只運(yùn)行一次 fixture
  • params: list 類型画畅,默認(rèn) None砸琅, 接收參數(shù)值,對(duì)于 param 里面的每個(gè)值轴踱,fixture 都會(huì)去遍歷執(zhí)行一次症脂。
  • autouse: 是否自動(dòng)運(yùn)行,默認(rèn)為 false淫僻, 為 true 時(shí)此 session 中的所有測(cè)試函數(shù)都會(huì)調(diào)用 fixture

scope參數(shù)

  • function:設(shè)置為function诱篷,表示每個(gè)測(cè)試方法都要執(zhí)行一次
# function:設(shè)置為function,表示每個(gè)測(cè)試方法都要執(zhí)行一次
import pytest

@pytest.fixture(scope='function')
# @pytest.fixture() # 和上面等價(jià)
def foo():
    print('foo')


def test_1(foo):
    print('普通測(cè)試用例111111')

def test_2():
    print('普通測(cè)試用例22222')


class TestClass(object):
    def test_one(self, foo):
        print('類實(shí)例方法測(cè)試用例111111')

    def test_two(self, foo):
        print('類實(shí)例方法測(cè)試用例22222')

運(yùn)行如下:

test_9_scope_function.py foo
普通測(cè)試用例111111
.普通測(cè)試用例22222
.foo
類實(shí)例方法測(cè)試用例111111
.foo
類實(shí)例方法測(cè)試用例22222
.

==================================================================== 4 passed in 0.03s ====================================================================
  • class:設(shè)置為 class 時(shí)代表這個(gè)類中只會(huì)執(zhí)行一次
import pytest

@pytest.fixture(scope='class')
def foo():
    print('foo')


def test_1(foo):
    print('普通測(cè)試用例111111')

def test_2(foo):
    print('普通測(cè)試用例22222')


class TestClass(object):
    def test_one(self, foo):
        print('類實(shí)例方法測(cè)試用例111111')

    def test_two(self, foo):
        print('類實(shí)例方法測(cè)試用例22222')

運(yùn)行如下:

test_10_scope_class.py foo
普通測(cè)試用例111111
.foo
普通測(cè)試用例22222
.foo
類實(shí)例方法測(cè)試用例111111
.類實(shí)例方法測(cè)試用例22222
.

==================================================================== 4 passed in 0.03s ====================================================================
  • module:設(shè)置為 module 時(shí)代表這個(gè)模塊中只會(huì)執(zhí)行一次
  • session:整個(gè) session 都只會(huì)執(zhí)行一次
# module:只會(huì)在最開始的時(shí)候傳入?yún)?shù)執(zhí)行1次
# session:只會(huì)在session開始傳入?yún)?shù)的時(shí)候執(zhí)行1次
import pytest

@pytest.fixture(scope='module')
# @pytest.fixture(scope='session')
def foo():
    print('foo')


def test_1(foo):
    print('普通測(cè)試用例111111')

def test_2(foo):
    print('普通測(cè)試用例22222')


class TestClass(object):
    def test_one(self, foo):
        print('類實(shí)例方法測(cè)試用例111111')

    def test_two(self, foo):
        print('類實(shí)例方法測(cè)試用例22222')

運(yùn)行如下:

test_11_scope_module.py foo
普通測(cè)試用例111111
.普通測(cè)試用例22222
.類實(shí)例方法測(cè)試用例111111
.類實(shí)例方法測(cè)試用例22222
.

==================================================================== 4 passed in 0.03s ====================================================================

params參數(shù)

  • pytest.fixture(params=None) 的params參數(shù)接收l(shuí)ist類型的參數(shù)
  • 對(duì)于param里面的每個(gè)值雳灵,fixture函數(shù)都會(huì)去遍歷執(zhí)行一次
  • 相應(yīng)的每次都會(huì)驅(qū)動(dòng)使用fixture函數(shù)的測(cè)試函數(shù)執(zhí)行一次棕所。
import pytest


def check_password(password):
    """
    檢查密碼是否合法

    :param password: 長(zhǎng)度是 8 到 16
    :return:
    """
    pwd_len = len(password)
    if pwd_len < 8:
        return False
    elif pwd_len > 16:
        return False
    else:
        return True


@pytest.fixture(params=['1234567', '12345678', '123456789', '123456789012345', '1234567890123456', '12345678901234567'])
def password(request):
    return request.param


def test_check_password(password):
    print(password)
    print(check_password(password))

運(yùn)行如下:

test_13_params.py 1234567
False
.12345678
True
.123456789
True
.123456789012345
True
.1234567890123456
True
.12345678901234567
False
.

==================================================================== 6 passed in 0.03s ====================================================================
import pytest


@pytest.fixture(params=['admin', 'zhangsan', 'lisi'])
def username(request):
    return request.param


@pytest.fixture(params=['1234567', '12345678', '123456789', '123456789012345', '1234567890123456', '12345678901234567'])
def password(request):
    return request.param


def test_check_regist(username, password):
    print(username, '=====', password)

if __name__ == '__main__':
    pytest.main(['-s', 'test_14_params2.py'])

運(yùn)行如下:

test_14_params2.py                                     [100%]

============================== 18 passed in 0.06s ==============================

Process finished with exit code 0
.admin ===== 1234567
.admin ===== 12345678
.admin ===== 123456789
.admin ===== 123456789012345
.admin ===== 1234567890123456
.admin ===== 12345678901234567
.zhangsan ===== 1234567
.zhangsan ===== 12345678
.zhangsan ===== 123456789
.zhangsan ===== 123456789012345
.zhangsan ===== 1234567890123456
.zhangsan ===== 12345678901234567
.lisi ===== 1234567
.lisi ===== 12345678
.lisi ===== 123456789
.lisi ===== 123456789012345
.lisi ===== 1234567890123456
.lisi ===== 12345678901234567

autouse參數(shù)

pytest.fixture(autouse=False) 的autouse參數(shù)默認(rèn)為False, 不會(huì)自動(dòng)執(zhí)行;設(shè)置為True時(shí)悯辙,當(dāng)前運(yùn)行的所有測(cè)試函數(shù)在運(yùn)行前都會(huì)執(zhí)行fixture函數(shù)

import pytest


@pytest.fixture(autouse=True)
def before():
    print('\nbefore each test')

class Test2:
    def test_1(self):
        print('test_5')

    def test_2(self):
        print('test_6')

運(yùn)行如下:

test_15_autouse.py 
before each test
test_5
.
before each test
test_6
.

==================================================================== 2 passed in 0.03s ====================================================================

pytest.mark標(biāo)記

pytest.mark下提供了標(biāo)記裝飾器琳省,除了之前我們使用的pytest.mark.usefixtures()裝飾器以外,還有一些常用的標(biāo)記裝飾器

裝飾器 作用
pytest.mark.xfail() 將測(cè)試函數(shù)標(biāo)記為預(yù)期失敗躲撰。
pytest.mark.skip() 無(wú)條件地跳過測(cè)試函數(shù)
pytest.mark.skipif() 有條件地跳過測(cè)試函數(shù)
pytest.mark.parametrize() 參數(shù)化Fixture方法和測(cè)試函數(shù)针贬。
pytest.mark.usefixtures() 使用類、模塊或項(xiàng)目中的Fixture方法拢蛋。

標(biāo)志預(yù)期失效

  • 要測(cè)試的功能或者函數(shù)還沒有實(shí)現(xiàn)桦他,這個(gè)時(shí)候執(zhí)行測(cè)試一定是失敗的。我們通過 xfail 來(lái)標(biāo)記某個(gè)測(cè)試方法一定會(huì)失敗
  • xfail(condition=True, reason=None, raises=None, run=True, strict=False)
    -- condition:標(biāo)記預(yù)期失敗的條件瓤狐,如果條件為 False瞬铸,那么這個(gè)標(biāo)記無(wú)意義
    -- reason:標(biāo)記預(yù)期失敗的原因說明
import pytest

class Test_ABC:
    def setup_class(self):
        print("\nsetup")

    def teardown_class(self):
        print("\nteardown")

    def test_a(self):
        print("\ntest_a")

    @pytest.mark.xfail(condition=False, reason="預(yù)期失敗")
    def test_b(self):
        print("\ntest_b")
        assert 0

    @pytest.mark.xfail(condition=True, reason="預(yù)期失敗")
    def test_c(self):
        print("\ntest_c")
        assert 0

if __name__ == '__main__':
    pytest.main(['-s', 'test_22.py'])

運(yùn)行如下:

test_22.py 
setup
.
test_a
F
test_b

test_22.py:12 (Test_ABC.test_b)
self = <test_22.Test_ABC object at 0x7fc2295bfc18>

    @pytest.mark.xfail(condition=False, reason="預(yù)期失敗")
    def test_b(self):
        print("\ntest_b")
>       assert 0
E       assert 0

test_22.py:16: AssertionError
x
test_c

self = <test_22.Test_ABC object at 0x7fc2295bfef0>

    @pytest.mark.xfail(condition=True, reason="預(yù)期失敗")
    def test_c(self):
        print("\ntest_c")
>       assert 0
E       assert 0

test_22.py:21: AssertionError

teardown

Assertion failed
                                                           [100%]

=================================== FAILURES ===================================
_______________________________ Test_ABC.test_b ________________________________

self = <test_22.Test_ABC object at 0x7fc2295bfc18>

    @pytest.mark.xfail(condition=False, reason="預(yù)期失敗")
    def test_b(self):
        print("\ntest_b")
>       assert 0
E       assert 0

test_22.py:16: AssertionError
----------------------------- Captured stdout call -----------------------------

test_b
=========================== short test summary info ============================
FAILED test_22.py::Test_ABC::test_b - assert 0
==================== 1 failed, 1 passed, 1 xfailed in 0.08s ====================

跳過測(cè)試函數(shù)

無(wú)條件跳過

使用場(chǎng)景: 根據(jù)特定條件批幌、不執(zhí)行標(biāo)識(shí)的測(cè)試函數(shù)

  • skip(reason=None)
    ---reason: 標(biāo)注原因
import pytest
import pytest


class Test_ABC:
    def setup_class(self):
        print("\nsetup")

    def teardown_class(self):
        print("\nteardown")

    def test_a(self):
        print("test_a")

    # 開啟跳過標(biāo)記
    @pytest.mark.skip(reason="無(wú)條件跳過不執(zhí)行,就是任性頑皮")
    def test_b(self):
        print("test_b")


if __name__ == '__main__':
    pytest.main(['-s', 'test_23.py'])

運(yùn)行效果如下:

test_23.py 
setup
.test_a
s
Skipped: 無(wú)條件跳過不執(zhí)行嗓节,就是任性頑皮

teardown
                                                            [100%]

========================= 1 passed, 1 skipped in 0.03s =========================

有條件跳過

使用場(chǎng)景: 根據(jù)特定條件荧缘、不執(zhí)行標(biāo)識(shí)的測(cè)試函數(shù)

  • skipif(condition, reason=None)
    --- condition: 跳過的條件,必傳參數(shù)
    --- reason: 標(biāo)注原因
import pytest

class Test_ABC:
    def setup_class(self):
        print("\nsetup")

    def teardown_class(self):
        print("\nteardown")

    def test_a(self):
        print("test_a")

    # 開啟跳過標(biāo)記
    @pytest.mark.skipif(condition=1, reason="有條件跳過不執(zhí)行拦宣,依舊任性頑皮")
    # @pytest.mark.skipif(condition=0, reason="條件跳不成立截粗,無(wú)法跳過")
    def test_b(self):
        print("test_b")


if __name__ == '__main__':
    pytest.main(['-s', 'test_24.py'])

運(yùn)行效果如下:

test_24.py 
setup
.test_a
s
Skipped: 有條件跳過不執(zhí)行,依舊任性頑皮

teardown
                                                            [100%]

========================= 1 passed, 1 skipped in 0.03s =========================

參數(shù)化

  • 使用場(chǎng)景:需要測(cè)試一組不同的數(shù)據(jù)鸵隧,而測(cè)試過程是一樣的绸罗,這種情況下我們可以寫一個(gè)測(cè)試方法,并且測(cè)試方法通過參數(shù)接受數(shù)據(jù)豆瘫。通過遍歷數(shù)據(jù)并且調(diào)用測(cè)試方法來(lái)完成測(cè)試珊蟀。

  • 作用: 參數(shù)化fixture方法和測(cè)試函數(shù), 方便測(cè)試函數(shù)對(duì)測(cè)試屬性的獲取。

  • parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)

--- argnames:參數(shù)名外驱, 以逗號(hào)分隔的字符串育灸,表示一個(gè)或多個(gè)參數(shù)名稱,或參數(shù)字符串的列表/元組. 參數(shù)名為幾個(gè)昵宇,就會(huì)運(yùn)行幾次磅崭。
--- argvalues:
----參數(shù)對(duì)應(yīng)值,類型必須為 list
----當(dāng)參數(shù)為一個(gè)時(shí)瓦哎,參數(shù)格式:[value1,value2,...]
----當(dāng)參數(shù)個(gè)數(shù)大于一個(gè)時(shí)砸喻,格式為: [(param_value1,param_value2),...]

import pytest


class Test_ABC:
    def setup_class(self):
        print("setup")

    def teardown_class(self):
        print("teardown")

    def test_a(self):
        print("test_a")

    @pytest.mark.parametrize("a", [3, 6])
    def test_b(self, a):
        print(f"test_b data:a={a}")


    @pytest.mark.parametrize(["a","b"],[(1,2),(3,4)])
    def test_c(self, a, b):
        print(f"test_c a: {a}; b: ")

if __name__ == '__main__':
    pytest.main(['-s', 'test_25.py'])

運(yùn)行效果如下

test_25.py                                                          [100%]

============================== 5 passed in 0.04s ===============================

Process finished with exit code 0
setup
.test_a
.test_b data:a=3
.test_b data:a=6
.test_c a: 1; b: 2
.test_c a: 3; b: 4
teardown
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蒋譬,一起剝皮案震驚了整個(gè)濱河市割岛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌羡铲,老刑警劉巖蜂桶,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異也切,居然都是意外死亡扑媚,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門雷恃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)疆股,“玉大人,你說我怎么就攤上這事倒槐⊙裕” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)两残。 經(jīng)常有香客問我永毅,道長(zhǎng),這世上最難降的妖魔是什么人弓? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任沼死,我火速辦了婚禮,結(jié)果婚禮上崔赌,老公的妹妹穿的比我還像新娘意蛀。我一直安慰自己,他們只是感情好健芭,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布县钥。 她就那樣靜靜地躺著,像睡著了一般慈迈。 火紅的嫁衣襯著肌膚如雪若贮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天吩翻,我揣著相機(jī)與錄音兜看,去河邊找鬼。 笑死狭瞎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搏予。 我是一名探鬼主播熊锭,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼雪侥!你這毒婦竟也來(lái)了碗殷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤速缨,失蹤者是張志新(化名)和其女友劉穎锌妻,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旬牲,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仿粹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了原茅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吭历。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖擂橘,靈堂內(nèi)的尸體忽然破棺而出晌区,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布朗若,位于F島的核電站恼五,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏哭懈。R本人自食惡果不足惜唤冈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望银伟。 院中可真熱鬧你虹,春花似錦、人聲如沸彤避。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)琉预。三九已至董饰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間圆米,已是汗流浹背卒暂。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留娄帖,地道東北人也祠。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像近速,于是被迫代替她去往敵國(guó)和親诈嘿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容