pytest詳細教程

????本文參考了官方文檔和一些樂于分享的大佬的博客,結合自己的理解完成。學習pytest框架的小白,需要按照教程自己敲一遍,配置一遍,摸索一下整個框架的運行邏輯,數據流的走向,文字雖多,請細細看完,有問題歡迎在群里提出,相互學習,互相指正。希望大家有所收獲,學有所得。(群:自動化測試-夜行者:816489363)

--成都-阿木木

框架說明

官方文檔:https://docs.pytest.org/en/latest/contents.html

感謝慕城南風的博客:https://blog.csdn.net/lovedingd/article/details/98952868

Pytest支持的插件庫:https://plugincompat.herokuapp.com/

第三方插件庫:https://docs.pytest.org/en/latest/plugins.html

pytest兼容unittest

pytest兼容以前的unittest,只需要少量的更改代碼即可,下面就大家熟悉的setup、teardown以及html報告進行說明

setup和teardown

setup和teardown主要分為:類級、函數級。

運行于測試方法前后:

#!/user/bin/env?python

#?-*-?coding:?utf-8?-*-

"""??

------------------------------------??

@Project?:?pyqt5_study??

@Time????:?2020/8/4?9:33??

@Auth????:?chineseluo??

@Email???:?848257135@qq.com??

@File????:?test_setup_teardown.py??

@IDE?????:?PyCharm??

------------------------------------??

"""??

import?pytest??

class?TestSetupTeardown():??

????def?setup(self):??

????????print("運行于測試方法之前")??

????def?teardown(self):??

????????print("運行于方法之后")??

????def?test_01(self):??

????????print("這是第一個方法")??

????def?test_02(self):??

????????print("這是第二個方法")??

if?__name__?==?'__main__':??

????pytest.main("-s?test_setup_teardown.py")??

運行結果:

test_setup_teardown.py::TestSetupTeardown::test_01???

運行于測試方法之前??

PASSED????????????????[?50%]這是第一個方法??

運行于方法之后??

test_setup_teardown.py::TestSetupTeardown::test_02???

運行于測試方法之前??

PASSED????????????????[100%]這是第二個方法??

運行于方法之后??

運行于測試類的始末:

#!/user/bin/env?python

#?-*-?coding:?utf-8?-*-

"""?

------------------------------------??

@Project?:?pyqt5_study??

@Time????:?2020/8/4?9:33??

@Auth????:?chineseluo??

@Email???:?848257135@qq.com??

@File????:?test_setup_teardown.py??

@IDE?????:?PyCharm??

------------------------------------??

"""??

import?pytest??

class?TestSetupTeardown():??

????@classmethod??

????def?setup_class(self):??

????????print("運行于測試類之前")??

????@classmethod??

????def?teardown_class(self):??

????????print("運行于測試類之后")??

????def?test_01(self):??

????????print("這是第一個方法")??

????def?test_02(self):??

????????print("這是第二個方法")??

if?__name__?==?'__main__':??

????pytest.main(["-s","test_setup_teardown.py"])??

html測試報告

使用pytest的測試報告插件可以替換unittest本身的HTMLTestRunner報告

安裝:pip install pytest-html

使用方式:命令行格式:pytest --html=用戶路徑/report.html

pytest框架使用約束

所有的單測文件名都需要滿足test_*.py格式或*_test.py格式。

在單測文件中,測試類以Test開頭,并且不能帶有?init?方法(注意:定義class時,需要以T開頭,不然pytest是不會去運行該class的)

在單測類中,可以包含一個或多個test_開頭的函數。

此時,在執行pytest命令時,會自動從當前目錄及子目錄中尋找符合上述約束的測試函數來執行。可以在pytest.ini中修改測試目錄、測試模塊、測試類、測試方法掃描進行默認修改。

Pytest Exit Code含義清單

程序運行成功結束控制臺輸出:Process?finished?with?exit?code?0??

Exit code 0 所有用例執行完畢,全部通過

Exit code 1 所有用例執行完畢,存在Failed的測試用例

Exit code 2 用戶中斷了測試的執行

Exit code 3 測試執行過程發生了內部錯誤

Exit code 4 pytest 命令行使用錯誤

Exit code 5 未采集到可用測試用例文件

pytest之fixture

Fixture作用

fixture修飾器來標記固定的工廠函數,在其他函數,模塊,類或整個工程調用它時會被激活并優先執行,通常會被用于完成預置處理和重復操作。

fixture是在測試函數前后運行,由pytest執行的外殼函數;代碼可以定制,滿足多變的測試需求,包括定義傳入測試中的數據集,配置測試前系統的初始工作,為批量測試提供數據源等等,fixture是pytest用于將測試前后進行預備,清理工作的代碼分離出核心測試邏輯的一種機制

說明

@pytest.fixture()裝飾器用于申明函數是一個fixture,如果測試函數的參數列表中包含fixture,那么pytest會檢測到,檢測順序是,優先搜索該測試所在的模塊,然后搜索conftest.py,并在測試函數運行之前執行該fixture,fixture可以完成測試任務,也可以返回測試數據給測試函數

scope:被標記方法的作用域

function" (default):作用于每個測試方法,每個test都運行一次

"class":作用于整個類,每個class的所有test只運行一次

"module":作用于整個模塊,每個module的所有test只運行一次

"session:作用于整個session(慎用),每個session只運行一次

params:(list類型)提供參數數據,供調用標記方法的函數使用

autouse:是否自動運行,默認為False不運行,設置為True自動運行

pytest --setup-show test_example1.py(可以看到執行過程順序)

3、測試數據返回(參數化)

A.返回測試數據

#?coding:utf-8

import?pytest??

#?@pytest.fixture()不傳參,默認是function級別的,也就是只在test開頭函數前后執行

@pytest.fixture()??

def?fixture_test():??

????print("方法執行前執行")??

????yield??

????print("方法執行后執行")??

def?test_data(fixture_test):??

????assert?2?==?2??

返回測試數據

#?coding:utf-8

import?pytest??

#?@pytest.fixture()不傳參,默認是function級別的,也就是只在test開頭函數前后執行;也可以使用fixture返回數據

@pytest.fixture()??

def?fixture_test():??

return?[1,?2,?3,?4]??

def?test_data(fixture_test):??

????print(fixture_test[1])??

????assert?2?==?fixture_test[1]??

4、Fixture函數存放位置

單個測試模塊文件內,只有該模塊文件的類和方法可以訪問到該fixture函數

如果希望多個測試文件共享fixtrue,可以在某個公共目錄下新建一個fixture,將fixture放在里面

Fixture作用范圍

function級別作用域

function每個函數或方法都會調用(有兩種寫法,不傳遞參數,默認就是function,也可以指定scope="function",來進行作用域的指定

@pytest.fixture()??

def?fixture_function():??

????print("fixturetest測試1")??

? ??return?1??

@pytest.fixture(scope="function"):??

def?fixture_function():??

????print("fixture測試2")??

? ??return?2??

def?test_fixture(fixture_function1):??

????assert?1?==?fixture_function1??

Class級別作用域

#?coding:utf-8

import?pytest??

#?@pytest.fixture(scope="class")只在類的前后執行一次

@pytest.fixture(scope="class")??

def?fixture_class():??

????print("類前執行一次")??

????yield??

????print("類后執行一次")??

class?TestCase:??

????def?test_1(self,?fixture_class):??

????????print("類方法")??

Module級別作用域

#?coding:utf-8

import?pytest??

@pytest.fixture(scope="module")??

def?fixture_module():??

????print("模塊執行前執行")??

????yield??

????print("模塊執行后執行")??

def?test_1(fixture_module):??

????print("\n測試方法")??

class?TestCase:?

????def?test_2(self,?fixture_module):??

????????print("\n類方法")??

Session級別作用域

session是多個文件調用一次,可以跨越.py文件調用,每個.py文件都是module

當我們有多個.py文件的用例時,如果多個用例只需要調用一次fixture,可以設置scope="session",并且寫入到conftest。py文件里面

import?pytest??

@pytest.fixture(scope="session")??

def?fixture_session():??

????print("全局前執行一次")??

????yield??

????print("全局后執行一次")??

#?coding:utf-8

import?pytest??

def?test_1(fixture_session):??

????print("方法")??

class?TestCase:??

????def?test_2(self,?fixture_session):??

????????print("類方法")??

pytest之配置文件

pytest非測試文件介紹

1、pytest.ini:pytest的主配置文件,可以改變pytest的默認行為,其中有很多可以配置的選項,包含日志,命令行的一些參數,控制臺輸出的信息等等

2、conftest.py:是本地的插件庫,其中的hook函數和fixture將作用于該文件所在目錄以及所有子目錄

如何查看pytest.ini選項

使用pytest --help查看pytest.ini所有設置選項

如何更改默認命令行選項

pytest -v --verbose 可以輸出詳細信息

[pytest]

addops = -v --alluredir ./allure-result(addopts增加默認執行的操作步驟,簡化命令行參數)(allure測試報告默認在json文件目錄下生成,可以使用allure generate jsonpathdir -o allurepathdir更改)

ps:

如何使用allure生成測試報告

1、brew install allure

2、安裝allure-pytest

3、運行case時增加命令行選項pytest -v --allure ./allure-results test.py

4、生成測試報告allure generate allure-results -o allure

有哪些常用的命令行選項呢?

-v:輸出詳細信息,顯示具體執行了那些測試用例

--collect-only 展示在給定的配置下那些測試用例會被執行,僅用于展示,不執行

-k 允許使用表達式指定希望運行的測試用例

exp:pytest -v -k 'baidu' test.py(在pytest中查找含有baidu關鍵字的case執行)

-m marker用于標記測試并分組

--strict 遇到mark拼寫錯誤會檢查,與mark配合使用

注冊標記防范拼寫錯誤

自定義標記可以簡化測試工作,但是標記容易拼寫錯誤,默認情況下不會引起錯誤,pytest以為這是另外一個標記,為了避免拼寫錯誤,可以在pytest.ini文件里進行注冊

markers = data_file:a test_data get_and_format marker

通過命令查看:pytest --help(或者pytest --marks)沒有注冊的標記不會出現在markers列表里面,如果使用--strict選項,遇到拼寫錯誤的標記或者未注冊的標記會報錯

如果自己增加一個測試函數的標記呢?

@pytest.mark.smoke

pytest -m 'smoke' test.py

執行pytest的最低版本號設置

minversion = 6.0

minversion選項可以指定運行測試用例的pytest的最低版本

指定pytest忽略某些目錄

norecursedirs = .*data config utils

可以使用norecursedirs縮小pytest的搜索范圍

指定訪問目錄

testpath = testsdir

配置日志

通過將log_cli配置選項設置為true,pytest將在直接將日志記錄發送到控制臺時輸出日志記錄。

您可以指定傳遞的級別,以將等于或更高級別的日志記錄打印到控制臺的日志記錄級別--log-cli-level。此設置接受python文檔中顯示的日志記錄級別名稱,或者接受整數作為日志記錄級別num。

此外,您還可以指定--log-cli-format和?--log-cli-date-format哪個鏡和默認--log-format和?--log-date-format如果沒有提供,但只被應用到控制臺日志處理程序。

還可以在配置INI文件中設置所有CLI日志選項。選項名稱為:

log_cli_level

log_cli_format

log_cli_date_format

如果您需要將整個測試套件的日志記錄記錄到一個文件中,則可以傳遞?--log-file=/path/to/log/file。該日志文件以寫模式打開,這意味著它將在每個運行測試會話中被覆蓋。

您還可以通過傳遞日志文件的日志記錄級別?--log-file-level。此設置接受python文檔中所見的日志記錄級別名稱(即大寫的名稱),或者接受整數作為日志記錄級別num。

此外,您還可以指定--log-file-format和?--log-file-date-format,它們等于--log-format和?--log-date-format但應用于日志文件日志處理程序。

還可以在配置INI文件中設置所有日志文件選項。選項名稱為:

log_file

log_file_level

log_file_format

log_file_date_format

您可以調用set_log_path()以動態自定義log_file路徑。此功能被認為是實驗性的。

[pytest]??

testpaths?=?TestCases??

log_format?=?%(asctime)s?%(levelname)s?%(message)s??

log_level?=?INFO??

log_file_level?=?debug??

log_file_date_format?=?%Y-%m-%d?%H:%M:%S??

log_file_format?=?%(asctime)s?%(levelname)s?%(message)s??

;log_file?=?../../Logs/log.log??

log_cli?=?True??

log_cli_level?=?INFO??

log_cli_format?=?%(asctime)s?[%(levelname)1s]?%(message)s?(%(filename)s:%(lineno)s)??

log_cli_date_format=%Y-%m-%d?%H:%M:%S??

8、配置例子

#配置pytest命令行運行參數

[pytest]

addopts = -s ... # 空格分隔,可添加多個命令行參數 -所有參數均為插件包的參數配置測試搜索的路徑

testpaths = ./scripts # 當前目錄下的scripts文件夾 -可自定義

#配置測試搜索的文件名稱

python_files = test*.py

#當前目錄下的scripts文件夾下,以test開頭,以.py結尾的所有文件 -可自定義

配置測試搜索的測試類名

python_classes = Test_*

#當前目錄下的scripts文件夾下,以test開頭,以.py結尾的所有文件中,以Test開頭的類 -可自定義

配置測試搜索的測試函數名

python_functions = test_*

#當前目錄下的scripts文件夾下,以test開頭,以.py結尾的所有文件中,以Test開頭的類內,以test_開頭的方法 -可自定義

pytest之數據驅動

Fixture

import?pytest??

@pytest.fixture(params=[1,?2,?3])??

def?need_data(request):?#?傳入參數request?系統封裝參數??

return?request.param?#?取列表中單個值,默認的取值方式??

class?Test_ABC:??

????def?test_a(self,need_data):??

????????print("------->test_a")??

????????assert?need_data?!=?3?#?斷言need_data不等于3??

if?__name__?==?'__main__':??

????pytest.main("-s??test_abc.py")??

parametrize裝飾器

@pytest.mark.parametrize(argnames,argvalues)裝飾器可以達到批量傳送參數的目的,argvalues里面傳遞的是元組或者列表里面嵌套元組的方式

pytest插件與hook函數

簡介

pytest可以通過添加插件可以擴展功能,pytest的代碼結構適合定制和擴展插件,可以借助hook函數來實現。把fixture函數或者hook函數添加到conftest文件里,這種方式,就已經創建了一個本地的conftest插件!!!

pytest plugin加載的幾種方式

1、內置plugins:從代碼內部的_pytest目錄加載;

2、外部插件(第三方插件):通過setuptools entry points機制發現的第三方插件模塊;

推薦使用的第三方的pytest插件:https://docs.pytest.org/en/latest/plugins.html

3、conftest.py形式的本地插件:測試目錄下的自動模塊發現機制

通過pytest --trace-config命令可以查看當前pytest中所有的plugin

在pytest中,所謂的plugin其實就是能被pytest發現的一些帶有pytest hook方法的文件或者對象

什么是hook方法(鉤子函數)

使用的框架提供公用的規則,其他開發者使用這個規則編寫的文件或者代碼可以被框架識別,框架進行初始化時,會收集滿足這個規則的所有代碼(文件),然后將這些代碼加入到框架中來,在執行時,一并進行初始化。所有這一規則下可以被框架收集到的方法就是hook方法。

編寫自己的插件

插件可以改變pytest行為,可用的hook函數很多,詳細的定義:

http://doc.pytest.org/en/latest/_modules/_pytest/hookspec.html

1、pytest_addoption,基本每個pytest plugin都會有這個hook方法,它的作用是為pytest命令添加自定義的參數

parser:用戶命令行參數與ini文件值的解析器

def pytest_addoption(parser):

parser.addoption("--env",##注冊一個命令行選項

default="test",#默認值為test

dest="env",

help="set test run env")#說明

pytest_addoption:Hook function,這里創建了一個argparser的group,通過addoption方法添加option,使得顯示help信息時相關option顯示在一個group下面,更加友好,使用pytest --help可以查看

def?pytest_addoption(parser):??

????group?=?parser.getgroup("chinese?auto?test")??

????group.addoption("--env",?default="ggg",?dest="env",?help="test?env")??

????group.addoption("--env2",?default="ggg",?dest="env",?help="test?env")??


@pytest.fixture(scope="session")??

def?cmdopt(request):??

????print("獲取不同環境變量的配置")??

return?request.config.getoption("--env")??

2、pytest_collection_modifyitems,是一個完成所有測試項的收集后,pytest調用的鉤子

def pytest_collection_modifyitems(items):

pass

測試用例收集完成后,將收集到的item的name和nodeid的中文顯示在控制臺上,所有的測試用例收集完畢后調用,可以再次過濾或者對它們重新排序

items(收集的測試項目列表)

def?pytest_collection_modifyitems(items):??

????print("test?hook?函數")??

for?item?in?items:??

????????item.name?=?item.name.encode("utf-8").decode("unicode_escape")??

????????item._nodeid?=?item._nodeid.encode("utf-8").decode("unicode_escape")??

Pytest高級用法

1、跳過測試函數

根據特定的條件,不執行標識的測試函數.

方法:

skipif(condition, reason=None)

參數:

condition:跳過的條件,必傳參數

reason:標注原因,必傳參數

使用方法:

@pytest.mark.skipif(condition, reason="xxx")

import?pytest??

class?Test_ABC:??

????def?setup_class(self):??

????????print("------->setup_class")??

????def?teardown_class(self):??

????????print("------->teardown_class")??

????def?test_a(self):??

????????print("------->test_a")??

????????assert?1??

????@pytest.mark.skipif(condition=2>1,reason?=?"跳過該函數")?#?跳過測試函數test_b??

????def?test_b(self):??

????????print("------->test_b")??

????????????assert?0??

2、標記為預期失敗的函數

標記測試函數為失敗函數

方法:

xfail(condition=None, reason=None, raises=None, run=True, strict=False)

常用參數:

condition:預期失敗的條件,必傳參數

reason:失敗的原因,必傳參數

使用方法:

@pytest.mark.xfail(condition, reason="xx")

import?pytest??

class?Test_ABC:??

????def?setup_class(self):??

????????print("------->setup_class")??

????def?teardown_class(self):??

????????print("------->teardown_class")??

????def?test_a(self):??

????????print("------->test_a")??

????????assert?1??

????@pytest.mark.xfail(2?>?1,?reason="標注為預期失敗")?#?標記為預期失敗函數test_b??

???????def?test_b(self):??

???????????print("------->test_b")??

??????????assert?0??

函數參數化

方便測試函數對測試屬于的獲取。

方法:

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

常用參數:

argnames:參數名

argvalues:參數對應值,類型必須為list

當參數為一個時格式:[value]

當參數個數大于一個時,格式為:[(param_value1,param_value2.....),(param_value1,param_value2.....)]

使用方法:

@pytest.mark.parametrize(argnames,argvalues)

? 參數值為N個,測試方法就會運行N次

在函數參數化中還可以傳遞函數,進行參數化

import?pytest??

def?return_test_data():??

return?[(1,2),(0,3)]??

class?Test_ABC:??

????def?setup_class(self):??

????????print("------->setup_class")??

????def?teardown_class(self):??

????????????print("------->teardown_class")??

@pytest.mark.parametrize("a,b",return_test_data())?#?使用函數返回值的形式傳入參數值??

def?test_a(self,a,b):??

????print("test?data:a=%d,b=%d"%(a,b))??

????assert?a+b?==?3??

4、修改python traceback輸出

pytest --showlocals # show local variables in tracebacks

pytest -l # show local variables (shortcut)

pytest --tb=auto # (default) 'long' tracebacks for the first and last

# entry, but 'short' style for the other entries

pytest --tb=long # exhaustive, informative traceback formatting

pytest --tb=short # shorter traceback format

pytest --tb=line # only one line per failure

pytest --tb=native # Python standard library formatting

pytest --tb=no # no traceback at all

python --full-trace?參數會打印更多的錯誤輸出信息,比參數 --tb=long 還多,即使是 Ctrl+C 觸發的錯誤,也會打印出來

5、獲取用例執行的性能數據

獲取最慢的10個用例的執行耗時

pytest --durations=10

Pytest-xdist進程級并發插件講解

參考夜行者自動化測試群(群號:816489363)文件:pytest-xdist進程級并發參數化說明--成都-阿木木

Pytest常用插件介紹

pytest-assume

多重校驗插件,可以執行完所有的斷言,常規assert斷言執行失敗后下面的斷言便會停止,不在執行,assume插件可以執行完所有斷言

安裝命令:pip install pytest-assume

使用方式:

def?test_add_case(self):??

????pytest.assume(add(1,2)==3)??

????pytest.assume(add(1,4)==3)??

????pytest.assume(add(2,2)==4)??

pytest-ording

Pytest用例默認執行順序是和collect的順序一致,用例收集是按照測試目錄開始,由上到下,在測試模塊中,測試用例收集也是從上到下,需要調整測試函數的執行順序可以通過pytest_collection_modifyitems這個hook函數(鉤子)進行插件編寫。在pytest的第三方插件中,已經有人實現了這個功能,下面介紹pytest-ordering這個插件。

安裝命令:pip install pytest-ordering

@pytest.mark.run(order=2)??

def?test_order1():??

????print?("first?test")??

????assert?True??

@pytest.mark.run(order=1)??

def?test_order2():??

????print?("second?test")??

????assert?True??

pytest-rerunfailures

失敗重跑插件,使用比較簡單,在腳本運行過程中,可能某些原因導致用例執行失敗,可能是網絡加載等,可以使用該插件,對于失敗的用例進行重跑,提高報告的準確性。

安裝命令:pip install pytest-rerunfailures

命令行指定:

Pytest -s test_xxx.py --reruns 5 #表示失敗用例運行五次

Pytest -s test_xxx.py --reruns-delay 2 #表示失敗用例等待2S后在執行

在裝飾器中指定:

@pytest.mark.flaky(reruns=6,?reruns_delay=2)??

????def?test_example(self):??

????????print(3)??

????????assert?random.choice([True,?False])??

pytest-sugar

顯示進度條,控制臺顯示比較好看

顯示效果如下:

?

安裝命令:pip install pytest-sugar

(群:自動化測試-夜行者:816489363)

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376