自動(dòng)化測(cè)試(3) | Selenium Python WebDriver 進(jìn)階

WebDriver 進(jìn)階

歡迎閱讀WebDriver進(jìn)階講義继控。本篇講義將會(huì)重點(diǎn)介紹Selenium WebDriver API的重點(diǎn)使用方法械馆,以及使用模塊化和參數(shù)化進(jìn)行自動(dòng)化測(cè)試的設(shè)計(jì)胖眷。

WebDriver API 進(jìn)階使用

元素定位

從之前的講義和學(xué)習(xí)中武通,我們知道,WebDriver API的調(diào)用以及自動(dòng)化測(cè)試珊搀,務(wù)必從頁(yè)面元素的定位開始冶忱,那么回顧之前的內(nèi)容,WebDriver提供了一系列的定位符以便使用元素定位方法境析。常見(jiàn)的定位符有以下幾種:

  • id
  • name
  • class name
  • tag
  • link text
  • partial link text
  • xpath
  • css selector

那么我們以下的操作將會(huì)基于上述的定位符進(jìn)行定位操作囚枪。

對(duì)于元素的定位派诬,WebDriver API可以通過(guò)定位簡(jiǎn)單的元素和一組元素來(lái)操作。在這里链沼,我們需要告訴Selenium如何去找元素默赂,以至于他可以充分的模擬用戶行為,或者通過(guò)查看元素的屬性和狀態(tài)括勺,以便我們執(zhí)行一系列的檢查缆八。

在Selenium2中,WebDriver提供了多種多樣的find_element_by方法在一個(gè)網(wǎng)頁(yè)里面查找元素疾捍。這些方法通過(guò)提供過(guò)濾標(biāo)準(zhǔn)來(lái)定位元素奈辰。當(dāng)然WebDriver也提供了同樣多種多樣的find_elements_by的方式去定位多個(gè)元素。

Selenium2提供的8個(gè)find_element_by方法去定位元素乱豆。在這里我們來(lái)具體查看每個(gè)方法的詳細(xì)使用方式奖恰。下面的表格將會(huì)列出這些具體的方法:

方法Method 描述Description 參數(shù)Argument 示例Example
id 該方法通過(guò)ID的屬性值去定位查找單個(gè)元素 id: 需要被查找的元素的ID find_element_by_id('search')
name 該方法通過(guò)name的屬性值去定位查找單個(gè)元素 name: 需要被查找的元素的名稱 find_element_by_name('q')
class name 該方法通過(guò)class的名稱值去定位查找單個(gè)元素 class_name: 需要被查找的元素的類名 find_element_by_class_name('input-text')
tag_name 該方法通過(guò)tag的名稱值去定位查找單個(gè)元素 tag: 需要被查找的元素的標(biāo)簽名稱 find_element_by_tag_name('input')
link_text 該方法通過(guò)鏈接文字去定位查找單個(gè)元素 link_text: 需要被查找的元素的鏈接文字 find_element_by_link_text('Log In')
partial_link_text 該方法通過(guò)部分鏈接文字去定位查找單個(gè)元素 link_text: 需要被查找的元素的部分鏈接文字 find_element_by_partial_link_text('Long')
xpath 該方法通過(guò)XPath的值去定位查找單個(gè)元素 xpath: 需要被查找的元素的xpath find_element_by_xpath('//*[@id="xx"]/a')
css_selector 該方法通過(guò)CSS選擇器去定位查找單個(gè)元素 css_selector: 需要被查找的元素的ID find_element_by_css_selector('#search')

接下來(lái)的列表將會(huì)詳細(xì)展示find_elements_by的方法集合。這些方法依據(jù)匹配的具體標(biāo)準(zhǔn)返回一系列的元素宛裕。

方法Method 描述Description 參數(shù)Argument 示例Example
id 該方法通過(guò)ID的屬性值去定位查找多個(gè)元素 id: 需要被查找的元素的ID find_elements_by_id('search')
name 該方法通過(guò)name的屬性值去定位查找多個(gè)元素 name: 需要被查找的元素的名稱 find_elements_by_name('q')
class_name 該方法通過(guò)class的名稱值去定位查找多個(gè)元素 class_name: 需要被查找的元素的類名 find_elements_by_class_name('input-text')
tag_name 該方法通過(guò)tag的名稱值去定位查找多個(gè)元素 tag: 需要被查找的元素的標(biāo)簽名稱 find_elements_by_tag_name('input')
link_text 該方法通過(guò)鏈接文字去定位查找多個(gè)元素 link_text: 需要被查找的元素的鏈接文字 find_elements_by_link_text('Log In')
partial_link_text 該方法通過(guò)部分鏈接文字去定位查找多個(gè)元素 link_text: 需要被查找的元素的部分鏈接文字 find_elements_by_partial_link_text('Long')
xpath 該方法通過(guò)XPath的值去定位查找多個(gè)元素 xpath: 需要被查找的元素的xpath find_elements_by_xpath("http://div[contains(@class,'list')]")
css_selector 該方法通過(guò)CSS選擇器去定位查找多個(gè)元素 css_selector: 需要被查找的元素的ID find_element_by_css_selector('.input_class')

依據(jù)ID查找

請(qǐng)查看如下HTML的代碼瑟啃,以便實(shí)現(xiàn)通過(guò)ID的屬性值去定義一個(gè)查找文本框的查找:

<input id="search" type="text" name="q" value=""
       class="input-text" maxlength="128" autocomplete="off"/>

根據(jù)上述代碼,這里我們使用find_element_by_id()的方法去查找搜索框并且檢查它的最大長(zhǎng)度maxlength屬性续滋。我們通過(guò)傳遞ID的屬性值作為參數(shù)去查找翰守,參考如下的代碼示例:

def test_search_text_field_max_length(self):
    # get the search textbox
    search_field = self.driver.find_element_by_id("search")
    # check maxlength attribute is set to 128
    self.assertEqual("128", search_field.get_attribute("maxlength"))

如果使用find_elements_by_id()方法,將會(huì)返回所有的具有相同ID屬性值的一系列元素疲酌。

依據(jù)名稱name查找

這里還是根據(jù)上述ID查找的HTML代碼蜡峰,使用find_element_by_name的方法進(jìn)行查找。參考如下的代碼示例:

# get the search textbox
self.search_field = self.driver.find_element_by_name("q")

同樣朗恳,如果使用find_elements_by_name()方法湿颅,將會(huì)返回所有的具有相同name屬性值的一系列元素。

依據(jù)class name查找

除了上述的ID和name的方式查找粥诫,我們還可以使用class name的方式進(jìn)行查找和定位油航。

事實(shí)上,通過(guò)ID怀浆,name或者類名class name查找元素是最提倡推薦的和最快的方式谊囚。當(dāng)然Selenium2 WebDriver也提供了一些其他的方式,在上述三類方式條件不足执赡,查找無(wú)效的時(shí)候镰踏,可以通過(guò)這些其他方式來(lái)查找。這些方式將會(huì)在后續(xù)的內(nèi)容中講述沙合。

請(qǐng)查看如下的HTML代碼奠伪,通過(guò)改代碼進(jìn)行練習(xí)和理解.

<button type="submit" title="Search" class="button">
  <span><span>Search</span></span>
</button>

根據(jù)上述代碼,使用find_element_by_class_name()方法去定位元素。

def test_search_button_enabled(self):
    # get Search button
    search_button = self.driver.find_element_by_class_name("button")
    # check Search button is enabled
    self.assertTrue(search_button.is_enabled())

同樣的如果使用find_elements_by_class_name()方法去定位元素绊率,將會(huì)返回所有的具有相同name屬性值的一系列元素谨敛。

依據(jù)標(biāo)簽名tag name查找

利用標(biāo)簽的方法類似于利用類名等方法進(jìn)行查找。我們可以輕松的查找出一系列的具有相同標(biāo)簽名的元素滤否。例如我們可以通過(guò)查找表中的<tr>來(lái)獲取行數(shù)脸狸。

下面有一個(gè)HTML的示例,這里在無(wú)序列表中使用了<img>標(biāo)簽藐俺。

<ul class="promos">
    <li>
        <a >
            <img src="/media/wysiwyg/homepage-three-column-promo-
        01B.png" alt="Physical & Virtual Gift Cards">
        </a>
    </li>
    <li>
        <a >
            <img src="/media/wysiwyg/homepage-three-column-promo-
        02.png" alt="Shop Private Sales - Members Only">
        </a>
    </li>
    <li>
        <a href="http://demo.magentocommerce.com/accessories/
        bags-luggage.html">
            <img src="/media/wysiwyg/homepage-three-columnpromo-
        03.png" alt="Travel Gear for Every Occasion">
        </a>
    </li>
</ul>

這里面我們使用find_elements_by_tag_name()的方式去獲取全部的圖片肥惭,在此之前,我們將會(huì)使用find_element_by_class_name()去獲取到指定的<ul>紊搪。

具體代碼如下:

def test_count_of_promo_banners_images(self):
    # get promo banner list
    banner_list = self.driver.find_element_by_class_name("promos")
    # get images from the banner_list
    banners = banner_list.find_elements_by_tag_name("img")
    # check there are 20 tags displayed on the page
    self.assertEqual(20, len(banners))

依據(jù)鏈接文字link查找

鏈接文字查找通常比較簡(jiǎn)單蜜葱。使用find_element_by_link_text請(qǐng)查看以下示例

<a href="#header-account" class="skip-link skip-account">
    <span class="icon"></span>
    <span class="label">Account</span>
</a>

測(cè)試代碼如下:

def test_my_account_link_is_displayed(self):
    # get the Account link
    account_link =
    self.driver.find_element_by_link_text("ACCOUNT")
    # check My Account link is displayed/visible in
    # the Home page footer
    self.assertTrue(account_link.is_displayed())

依據(jù)部分鏈接文字partial text查找

這里依舊使用上述的列子進(jìn)行代碼編寫:

def test_account_links(self):
    # get the all the links with Account text in it
    account_links = self.driver.\\
    find_elements_by_partial_link_text("ACCOUNT")
    # check Account and My Account link is
    displayed/visible in the Home page footer
    self.assertTrue(2, len(account_links)) 

依據(jù)XPath進(jìn)行查找

XPath是一種在XML文檔中搜索和定位節(jié)點(diǎn)node的一種查詢語(yǔ)言。所有的主流Web瀏覽器都支持XPath耀石。Selenium2可以用強(qiáng)大的XPath在頁(yè)面中查找元素牵囤。

常用的XPath的方法有starts-with()contains()ends-with()

若想要了解更多關(guān)于XPath的內(nèi)容,請(qǐng)查看http://www.w3schools.com/XPath/

如下有一段HTML代碼,其中里面的<img>沒(méi)有使用ID落君,name或者類屬性,所以我們無(wú)法使用之前的方法野崇。亞這里我們可以通過(guò)<img>alt屬性,定位到指定的tag亩钟。

<ul class="promos">
    <li>
        <a >
            <img src="/media/wysiwyg/homepage-three-column-promo-
        01B.png" alt="Physical & Virtual Gift Cards">
        </a>
    </li>
    <li>
        <a >
            <img src="/media/wysiwyg/homepage-three-column-promo-
        02.png" alt="Shop Private Sales - Members Only">
        </a>
    </li>
    <li>
        <a href="http://demo.magentocommerce.com/accessories/
        bags-luggage.html">
            <img src="/media/wysiwyg/homepage-three-columnpromo-
        03.png" alt="Travel Gear for Every Occasion">
        </a>
    </li>
</ul>

具體代碼如下:

def test_vip_promo(self):
    # get vip promo image
    vip_promo = self.driver.\\
    find_element_by_xpath("http://img[@alt='Shop Private Sales - Members Only']")
    # check vip promo logo is displayed on home page
    self.assertTrue(vip_promo.is_displayed())
    # click on vip promo images to open the page
    vip_promo.click()
    # check page title
    self.assertEqual("VIP", self.driver.title)

當(dāng)然乓梨,如果使用find_elements_by_xpath()的方法,將會(huì)返回所有匹配了XPath查詢的元素清酥。

依據(jù)CSS選擇器進(jìn)行查找

CSS是一種設(shè)計(jì)師用來(lái)描繪HTML文檔的視覺(jué)的層疊樣式表扶镀。一般來(lái)說(shuō)CSS用來(lái)定位多種多樣的風(fēng)格,同時(shí)可以用來(lái)是同樣的標(biāo)簽使用同樣的風(fēng)格等焰轻。類似于XPath臭觉,Selenium2也可以使用CSS選擇器來(lái)定位元素。

請(qǐng)查看如下的HTML文檔辱志。

<div class="minicart-wrapper">
    <p class="block-subtitle">Recently added item(s)
        <a class="close skip-link-close" href="#" title="Close">×</a>
    </p>
    <p class="empty">You have no items in your shopping cart.
    </p>
</div>

我們來(lái)創(chuàng)建一個(gè)測(cè)試蝠筑,驗(yàn)證這些消息是否正確。

def test_shopping_cart_status(self):
    # check content of My Shopping Cart block on Home page
    # get the Shopping cart icon and click to open the
    # Shopping Cart section
    shopping_cart_icon = self.driver.\\
    find_element_by_css_selector("div.header-minicart
                                 span.icon")
    shopping_cart_icon.click()
    # get the shopping cart status
    shopping_cart_status = self.driver.\\
    find_element_by_css_selector("p.empty").text
    self.assertEqual("You have no items in your shopping cart.",
    shopping_cart_status)
    # close the shopping cart section
    close_button = self.driver.\\
    find_element_by_css_selector("div.minicart-wrapper
                                 a.close")
    close_button.click()

鼠標(biāo)事件

Web測(cè)試中揩懒,有關(guān)鼠標(biāo)的操作什乙,不只是單擊,有時(shí)候還要做右擊旭从、雙擊稳强、拖動(dòng)等操作。這些操作包含在ActionChains類中和悦。

常用的鼠標(biāo)方法:

  • context_click() ##右擊
  • douch_click() ##雙擊
  • drag_and_drop() ##拖拽
  • move_to_element() ##鼠標(biāo)停在一個(gè)元素上
  • click_and_hold() # 按下鼠標(biāo)左鍵在一個(gè)元素上

例子:

#圖3.4
#如圖3.x4退疫,假如一個(gè)web 應(yīng)用的列表文件提供了右擊彈出快捷菜單的的操作「胨兀可以通過(guò)context_click()
#方法模擬鼠標(biāo)右鍵褒繁,參考代碼如下:
#引入ActionChains 類
from selenium.webdriver.common.action_chains import ActionChains
...
#定位到要右擊的元素
right =driver.find_element_by_xpath("xx")
#對(duì)定位到的元素執(zhí)行鼠標(biāo)右鍵操作
ActionChains(driver).context_click(right).perform()
#引入ActionChains 類
from selenium.webdriver.common.action_chains import ActionChains
...
#定位到要雙擊的元素
double =driver.find_element_by_xpath("xxx")
#對(duì)定位到的元素執(zhí)行鼠標(biāo)雙擊操作
ActionChains(driver).double_click(double).perform()

鍵盤事件

鍵盤操作經(jīng)常處理的如下:

代碼 描述
send_keys(Keys.BACK_SPACE) 刪除鍵(BackSpace)
send_keys(Keys.SPACE) 空格鍵(Space)
send_keys(Keys.TAB) 制表鍵(Tab)
send_keys(Keys.ESCAPE) 回退鍵(Esc)
send_keys(Keys.ENTER) 回車鍵(Enter)
send_keys(Keys.CONTROL,'a') 全選(Ctrl+A)
send_keys(Keys.CONTROL,'c') 復(fù)制(Ctrl+C)

代碼如下

#coding=utf-8
from selenium import webdriver
#引入Keys 類包
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
#輸入框輸入內(nèi)容
driver.find_element_by_id("kw").send_keys("selenium")
time.sleep(3)
#刪除多輸入的一個(gè)m
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)
time.sleep(3)
#輸入空格鍵+“教程”
driver.find_element_by_id("kw").send_keys(Keys.SPACE)
driver.find_element_by_id("kw").send_keys(u"教程")
time.sleep(3)
#ctrl+a 全選輸入框內(nèi)容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')

模塊化與類庫(kù)

線性測(cè)試

至此之前,我們介紹的測(cè)試腳本馍忽,盡管使用了unittest測(cè)試框架棒坏,但是測(cè)試是按照指定的線路進(jìn)行的,是線性的測(cè)試遭笋,完全遵循了腳本的執(zhí)行順序坝冕。

測(cè)試腳本1

from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://wwww.xxx.com")
driver.find_element_by_id("tbUserName").send_keys("username")
driver.find_element_by_id("tbPassword").send_keys("123456")
driver.find_element_by_id("btnLogin").click()
#執(zhí)行具體用例操作
......
driver.quit ()

如上圖,其實(shí)登錄的模塊可以共用瓦呼。

模塊化

模塊話是自動(dòng)化測(cè)試的第一個(gè)延伸和基礎(chǔ)喂窟。需要對(duì)自動(dòng)化重復(fù)編寫的腳本進(jìn)行重構(gòu)(refactor),將重復(fù)的腳本抽取出來(lái)央串,放到指定的代碼文件中磨澡,作為共用的功能模塊。

測(cè)試腳本1:Login.py

#登錄模塊
def login():
driver.find_element_by_id("tbUserName").send_keys("username")
driver.find_element_by_id("tbPassword").send_keys("456123")
driver.find_element_by_id("btnLogin").click()

另一份文件 quit.py

#退出模塊
def quit():
..............

自動(dòng)化的測(cè)試:代碼如下

#coding=utf-8
from selenium import webdriver
import login,quit_ #調(diào)用登錄质和、退出模塊
driver = webdriver.Firefox()
driver.get("http://wwww.xxx.com")
#調(diào)用登錄模塊
login.login()
#其它個(gè)性化操作
......
#調(diào)用退出模塊
quit.quit()

參數(shù)化驅(qū)動(dòng)

數(shù)據(jù)驅(qū)動(dòng)

如果說(shuō)模塊化是自動(dòng)化測(cè)試的第一步稳摄,那么數(shù)據(jù)驅(qū)動(dòng)是自動(dòng)化的第二步,從本意上來(lái)講饲宿。數(shù)據(jù)改變更新驅(qū)動(dòng)自動(dòng)化的執(zhí)行厦酬。從而引起測(cè)試結(jié)果的改變。其實(shí)類似于參數(shù)化瘫想。

示例代碼

#coding=utf-8
from selenium import webdriver
import time
values=['selenium','webdriver',u'軟件自動(dòng)化測(cè)試']
# 執(zhí)行循環(huán)
for serch in values:
    driver = webdriver.Firefox()
    driver.get("https://www.baidu.com")
    driver.find_element_by_id("kw").send_keys(serch)
    time.sleep(3)
    .....

關(guān)于參數(shù)化驅(qū)動(dòng)弃锐,我們可以將數(shù)據(jù)放到csv中,然后通過(guò)讀取csv的數(shù)據(jù)進(jìn)行自動(dòng)化測(cè)試殿托。

關(guān)鍵字驅(qū)動(dòng)

這里的數(shù)據(jù)換成了特別的數(shù)據(jù)霹菊,就是關(guān)鍵字。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末支竹,一起剝皮案震驚了整個(gè)濱河市旋廷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌礼搁,老刑警劉巖饶碘,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異馒吴,居然都是意外死亡扎运,警方通過(guò)查閱死者的電腦和手機(jī)瑟曲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)豪治,“玉大人洞拨,你說(shuō)我怎么就攤上這事「耗猓” “怎么了烦衣?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)掩浙。 經(jīng)常有香客問(wèn)我花吟,道長(zhǎng),這世上最難降的妖魔是什么厨姚? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任衅澈,我火速辦了婚禮,結(jié)果婚禮上谬墙,老公的妹妹穿的比我還像新娘矾麻。我一直安慰自己,他們只是感情好芭梯,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布险耀。 她就那樣靜靜地躺著,像睡著了一般玖喘。 火紅的嫁衣襯著肌膚如雪甩牺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天累奈,我揣著相機(jī)與錄音贬派,去河邊找鬼。 笑死澎媒,一個(gè)胖子當(dāng)著我的面吹牛搞乏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播戒努,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼请敦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了储玫?” 一聲冷哼從身側(cè)響起侍筛,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎撒穷,沒(méi)想到半個(gè)月后匣椰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡端礼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年禽笑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了入录。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評(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,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望腕侄。 院中可真熱鬧小泉,春花似錦、人聲如沸冕杠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)分预。三九已至兢交,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間笼痹,已是汗流浹背配喳。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凳干,地道東北人晴裹。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像救赐,于是被迫代替她去往敵國(guó)和親涧团。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

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