TDD(測(cè)試驅(qū)動(dòng)開發(fā))項(xiàng)目實(shí)踐——開發(fā)實(shí)戰(zhàn)(一)

TDD-PRACTICE

背景 ?

本文接《TDD(測(cè)試驅(qū)動(dòng)開發(fā))項(xiàng)目實(shí)踐》開始指孤,前文偏重設(shè)計(jì)甥雕,對(duì)測(cè)試晶乔,尤其是單元測(cè)試

涉及不多几迄,本文是對(duì)前文的補(bǔ)充,相同的項(xiàng)目案例青柄,側(cè)重的是單元測(cè)試伐债。

有關(guān)需求及項(xiàng)目描述,可以直接參看前文:

http://www.reibang.com/p/ae34612e1eeb

環(huán)境(操作系統(tǒng)&&工具&&框架&&第三方庫(kù))


① 操作系統(tǒng):Win8.1

② IDE:VS2015 Pro

③ 單元測(cè)試框架:Nunit致开,版本號(hào):3.0.5813.39033

④ 單元測(cè)試輔助插件:NUnit3 Test Adapter(這個(gè)適用于VS2013/VS2015峰锁,Nunit Test Adpater 不支持VS2013/VS2015,這個(gè)Pi君親測(cè))用這個(gè)插件可以將Nunit單元測(cè)試的結(jié)果放到VS自帶的測(cè)試資源管理器中顯示双戳,比較方便虹蒋。

⑤ 還有第二個(gè)更好的選擇,VS2015的CodeRush插件飒货,這簡(jiǎn)直就是個(gè)測(cè)試神器魄衅,強(qiáng)烈推薦,沒有之一塘辅,后續(xù)出文單說此神器晃虫。

CodeRush-TestRunner

⑥ Moq框架,在需要Mock時(shí)使用扣墩,VS2015的配置可以通過NuGet程序包管理器配置哲银,細(xì)節(jié)不贅述,可留言分享沮榜;

⑦ Ninject框架盘榨,依賴注入框架喻粹;

⑧ Fluent NHibernate ORM框架;

⑨ .net4.0

項(xiàng)目組織結(jié)構(gòu)


個(gè)人習(xí)慣蟆融,在開始一個(gè)新的項(xiàng)目前,先規(guī)劃好項(xiàng)目代碼及相關(guān)文件的路徑守呜,因?yàn)檫@個(gè)項(xiàng)目是Pi君github上的項(xiàng)目(非公司代碼)型酥,所以在github文件夾下,新建一個(gè)子文件夾查乒,并以該項(xiàng)目命名FBGame弥喉,繼續(xù)在該文件夾下新建兩個(gè)子文件夾libs和src,其中l(wèi)ibs存放第三方庫(kù)或框架玛迄,src存放項(xiàng)目代碼由境。

把需要依賴的框架或類庫(kù)復(fù)制到libs中,并在src文件夾下新建一個(gè)空的解決方案,命名為FBGame虏杰,然后新建一些項(xiàng)目:

→ 建一個(gè)類庫(kù)項(xiàng)目讥蟆,命名為FBGame.Core;

→ 建一個(gè)類庫(kù)項(xiàng)目纺阔,作為該解決方案的單元測(cè)試項(xiàng)目瘸彤,命名為FBGame.UnitTests;

→ 建一個(gè)類庫(kù)項(xiàng)目笛钝,作為該解決方案的集成測(cè)試項(xiàng)目质况,命名為FBGame.IntegrationTests

→ 建一個(gè)WinForm項(xiàng)目,作為該解決方案的客戶端玻靡,命名為FBGame.WinClient结榄。

OK,這個(gè)項(xiàng)目的基本組織結(jié)構(gòu)基本成型囤捻。

FBGame項(xiàng)目結(jié)構(gòu)

在后續(xù)的開發(fā)過程中潭陪,這個(gè)結(jié)構(gòu)可能會(huì)修改,但是從一開始就保持結(jié)構(gòu)的簡(jiǎn)單和清晰是個(gè)好習(xí)慣最蕾,倘若在開發(fā)和迭代過程中依溯,想添加一個(gè)新的項(xiàng)目,那首先要反問自己“即將要添加的部分必須屬于一個(gè)獨(dú)立的項(xiàng)目嗎瘟则?”黎炉,如果不一定,那就暫時(shí)不要新建醋拧,倘若必須新建慷嗜,也要考慮和現(xiàn)有項(xiàng)目之間的關(guān)系,最好在新項(xiàng)目命名的時(shí)候就充分體現(xiàn)這種關(guān)系丹壕。

需求回顧


首先庆械,回顧一下前文中這個(gè)項(xiàng)目的需求描述:

① 一個(gè)足球比賽類小游戲,用戶可以通過鍵盤操控控球球員前進(jìn)/后退/左轉(zhuǎn)/右轉(zhuǎn)/加速/傳球/射門菌赖;如果用戶控制的球隊(duì)沒有球權(quán)缭乘,則用戶可以切換控制球員進(jìn)行鏟球/防守;用戶可以控制游戲開始琉用,設(shè)置游戲時(shí)間堕绩,一般有兩支球隊(duì)進(jìn)行比賽;

② 每個(gè)球隊(duì)有一個(gè)教練邑时,有十一個(gè)球員奴紧,有自己的球隊(duì)隊(duì)形,用戶可以自己調(diào)整針對(duì)特定隊(duì)形的球員站位晶丘,有自己的隊(duì)服/隊(duì)徽黍氮;

③ 有一個(gè)管理員賬號(hào),管理員可以管理球隊(duì)相關(guān)數(shù)據(jù),包括球員數(shù)據(jù)/教練數(shù)據(jù)/隊(duì)形數(shù)據(jù)/隊(duì)服數(shù)據(jù)/隊(duì)徽數(shù)據(jù)沫浆。

OK觉壶,一般到此可以根據(jù)需求進(jìn)行需求分析,確定需求優(yōu)先級(jí)......這是一般的開發(fā)過程件缸,如果考慮TDD铜靶,也就是先添加針對(duì)功能的測(cè)試用例而已~但是,TDD真的就是這樣的他炊?争剿!PI君不曉得,一起探索下吧~

0次迭代


本次迭代的用戶場(chǎng)景


既然痊末,我們是要做一個(gè)游戲蚕苇,游戲前端界面在前文中已有描述,可以簡(jiǎn)單的理解為C/S結(jié)構(gòu)凿叠,真正需要考慮的是給前端提供功能涩笤,這樣,核心的功能(陰影部分描述)可以通過一些場(chǎng)景來描述:

① 當(dāng)比賽時(shí)間完成時(shí)盒件,比賽結(jié)束蹬碧;

② 當(dāng)足球進(jìn)入A隊(duì)球門時(shí),B隊(duì)得分炒刁,球權(quán)交給B隊(duì)恩沽,在球場(chǎng)中心位置發(fā)球繼續(xù)開始比賽;

③ 當(dāng)足球被A隊(duì)隊(duì)員踢出界時(shí)翔始,球權(quán)交給B隊(duì)罗心,B隊(duì)隊(duì)員在出界位置發(fā)球繼續(xù)比賽;

④ 球員根據(jù)唯一動(dòng)作標(biāo)識(shí)進(jìn)行位置更新(前進(jìn)/后退/左轉(zhuǎn)/右轉(zhuǎn)/加速)城瞎,球員有指定的速度(前進(jìn)速度/后退速度/轉(zhuǎn)向速度)和當(dāng)前方向渤闷,前進(jìn)/后退/加速時(shí),更新球員的位置脖镀,左轉(zhuǎn)/右轉(zhuǎn)更新球員的前進(jìn)方向飒箭;

⑤ 足球根據(jù)受控狀態(tài),加速度认然,速度补憾,位置漫萄,方向卷员,時(shí)刻更新足球位置;

⑥ 球權(quán)更新腾务,根據(jù)足球的空間位置和所有球員的運(yùn)動(dòng)狀態(tài)<空間位置>毕骡,計(jì)算所有球員(設(shè)置占有球權(quán)的邏輯)占有足球的概率,并返回概率最大者為控球球員。

當(dāng)然未巫,這些并不包含全部的需求(甚至不到完整需求的20%)窿撬,但是,這是一個(gè)Core叙凡,在實(shí)現(xiàn)這些功能以后劈伴,足球游戲是可玩的,好不好玩先不用管~核心需求關(guān)系這個(gè)項(xiàng)目的核心價(jià)值握爷,只有保證Core實(shí)現(xiàn)了跛璧,這個(gè)項(xiàng)目才有延續(xù)推進(jìn)的可能,對(duì)于用戶而言新啼,也存在一個(gè)迭代需求的依據(jù)追城,否則,用戶總是看不到項(xiàng)目進(jìn)展燥撞,總是不能上手使用座柱,開發(fā)和憋大招一樣,大家都互相憋著物舒,憋著憋著就沒了耐性色洞,項(xiàng)目也多半會(huì)流產(chǎn)~

網(wǎng)上一些大牛們?cè)诿枋鲇脩魣?chǎng)景上有一些很好的建議,Pi君引用過來冠胯,一起學(xué)習(xí):

將較大的用戶情景分解為較小的功能锋玲,這些功能應(yīng)當(dāng)短小,簡(jiǎn)單涵叮,獨(dú)立惭蹂,可測(cè)。”——James Bender&&Jeff McWherter

用戶場(chǎng)景的功能列表


1 當(dāng)比賽時(shí)間完成時(shí)割粮,比賽結(jié)束盾碗;

1.1 一個(gè)獨(dú)立線程計(jì)時(shí)器類,可以設(shè)置時(shí)間舀瓢,開始計(jì)時(shí)廷雅,當(dāng)計(jì)時(shí)結(jié)束時(shí)返回結(jié)束狀態(tài);

2 當(dāng)足球進(jìn)入A隊(duì)球門時(shí)京髓,B隊(duì)得分航缀,球權(quán)交給B隊(duì),在球場(chǎng)中心位置發(fā)球繼續(xù)開始比賽堰怨;

2.1 一個(gè)球門類芥玉,用來描述球門,傳入足球的三維坐標(biāo)可以判斷是否進(jìn)球备图;

2.2 一個(gè)游戲信息服務(wù)類灿巧,這是一個(gè)獨(dú)立線程赶袄,監(jiān)控進(jìn)球發(fā)生事件,更新計(jì)算比分抠藕,更新球權(quán)狀態(tài)饿肺,更新足球位置;

2.3 一個(gè)全局變量盾似,球場(chǎng)中心位置敬辣;

3 當(dāng)足球被A隊(duì)隊(duì)員踢出界時(shí),球權(quán)交給B隊(duì)零院,B隊(duì)隊(duì)員在出界位置發(fā)球繼續(xù)比賽购岗;

3.1 一個(gè)球場(chǎng)邊界類,根據(jù)足球的位置判斷界內(nèi)界外门粪,當(dāng)足球出界時(shí)喊积,返回當(dāng)前足球位置;

3.2 參看2.2

4 球員根據(jù)唯一動(dòng)作標(biāo)識(shí)進(jìn)行位置更新(前進(jìn)/后退/左轉(zhuǎn)/右轉(zhuǎn)/加速)玄妈,球員有指定的速度(前進(jìn)速度/后退速度/轉(zhuǎn)向速度)和當(dāng)前方向乾吻,前進(jìn)/后退/加速時(shí),更新球員的位置拟蜻,左轉(zhuǎn)/右轉(zhuǎn)更新球員的前進(jìn)方向绎签;

4.1 一個(gè)球員類,根據(jù)動(dòng)作指示符酝锅,進(jìn)行位置及方向的更新诡必;

5 足球根據(jù)受控狀態(tài),加速度搔扁,速度爸舒,位置,方向稿蹲,時(shí)刻更新足球位置扭勉;

5.1 一個(gè)足球類,包含足球的運(yùn)動(dòng)屬性苛聘,方向和三維位置信息涂炎,這是一個(gè)單例類;

5.2 一個(gè)足球服務(wù)類设哗,這是一個(gè)獨(dú)立線程唱捣,在比賽時(shí)間內(nèi),每間隔單位時(shí)間根據(jù)當(dāng)前時(shí)刻下的足球?qū)ο笮畔⒏伦闱虻娜S位置信息网梢;

6 球權(quán)更新震缭,根據(jù)足球的空間位置和所有球員的運(yùn)動(dòng)狀態(tài)<空間位置>,計(jì)算所有球員(設(shè)置占有球權(quán)的邏輯)占有足球的概率澎粟,并返回概率最大者為控球球員蛀序。

6.1 游戲信息服務(wù)類欢瞪,每間隔單位時(shí)間活烙,計(jì)算所有球員(設(shè)置占有球權(quán)的邏輯)占有足球的概率徐裸,并更新概率最大者為控球球員;

實(shí)現(xiàn)場(chǎng)景1——>當(dāng)比賽時(shí)間完成時(shí)啸盏,比賽結(jié)束


1.1 一個(gè)獨(dú)立線程計(jì)時(shí)器類重贺,可以設(shè)置時(shí)間,開始計(jì)時(shí)后每隔單位時(shí)間返回計(jì)時(shí)結(jié)果(字符串)回懦,當(dāng)計(jì)時(shí)結(jié)束時(shí)返回結(jié)束狀態(tài)气笙;

定義一個(gè)計(jì)時(shí)器類,給計(jì)時(shí)器設(shè)置時(shí)間t怯晕,當(dāng)計(jì)時(shí)器開始計(jì)時(shí)時(shí)潜圃,根據(jù)不同的時(shí)刻(不到t,超過t舟茶,等于t)谭期,獲取計(jì)時(shí)字符串和狀態(tài),即:

TestCase-1:不到t吧凉,返回時(shí)刻字符串和Running狀態(tài)隧出;

TestCase-2:超過或到達(dá)t,返回時(shí)刻字符串和Over狀態(tài)狀態(tài)阀捅。

其中Running用整數(shù)1標(biāo)識(shí)胀瞪,Over用0標(biāo)識(shí)。

在單元測(cè)試的構(gòu)建中饲鄙,采用BDD(行為驅(qū)動(dòng)開發(fā))風(fēng)格的命名規(guī)則是個(gè)好的建議凄诞,在單元測(cè)試的類名及方法名的定義中將用戶場(chǎng)景進(jìn)行描述,很直觀忍级,易于和業(yè)務(wù)人員溝通幔摸。簡(jiǎn)單說來就是三個(gè)步驟:

1. when->一般是某類場(chǎng)景單元測(cè)試的基類,保存但元測(cè)試的運(yùn)行環(huán)境颤练,用在此處可以這寫:

public class when_working_with_the_TimeCounter_start{}既忆;

2. and->一般是具體某種情形下的場(chǎng)景的單元測(cè)試類,繼承when定義的基類嗦玖,共享測(cè)試環(huán)境,例如:

public class and_by_the_time_point : when_working_with_the_TimeCounter_start{}宇挫;

3. which...then->一般是測(cè)試用例器瘪,即測(cè)試方法的定義翠储,例如:

public void which_in_the_time_then_TimeCounter_status_should_be_running()绘雁;

在使用BDD的命名規(guī)則時(shí)庐舟,可以直接引用BDD的命名庫(kù),但是Pi君暫時(shí)還沒有感受到使用nBehave類似的BDD語法糖帶來的優(yōu)勢(shì)住拭,所以先借用一下命名規(guī)則而已挪略,(對(duì)于BDD而言杠娱,這連皮毛都不算~)測(cè)試框架谱煤,直接使用NUnit刘离。

TestCase-1:


OK,構(gòu)建單元測(cè)試如下:

when
and_by_time_point

Pi君省去了一步一步的添加過程,當(dāng)前這個(gè)狀態(tài)可以編譯通過疲憋,但是運(yùn)行時(shí)會(huì)報(bào)錯(cuò)~

因?yàn)開timeCounter沒有實(shí)例缚柳,只有一個(gè)接口的定義而已:

ITimeCounter

接下來需要添加一個(gè)實(shí)現(xiàn)ITimeCounter的實(shí)體類:

TimeCounter

然后在when_working_with_the_TimeCounter_start添加對(duì)_timeCounter的定義:

_timeCounter

運(yùn)行測(cè)試彩掐,失敗了堵幽,原因是:

測(cè)試結(jié)果

計(jì)算當(dāng)前時(shí)刻字符串的方法不能通過測(cè)試弹澎,調(diào)整該方法的代碼:

在TDD過程中,小步前進(jìn)總是好的殴胧,和獲取計(jì)時(shí)器的狀態(tài)一樣团滥,也可以直接在獲取當(dāng)前時(shí)刻字符串的方法上返回測(cè)試用例中需要的時(shí)刻,但是timePoint=_radom.Next(0,10)拱燃,這是個(gè)固定范圍內(nèi)的隨機(jī)數(shù)扼雏,次奧夯膀,寫測(cè)試案例的小朋友真是機(jī)靈......這意味著如果想通過測(cè)試诱建,不得不“前進(jìn)”一大步了俺猿。

為了讓計(jì)時(shí)器可以返回計(jì)時(shí)時(shí)間段內(nèi)的不同時(shí)刻格仲,給計(jì)時(shí)器添加幾個(gè)成員:

currentPoint&&currentPointStr

分別記錄時(shí)刻及其對(duì)應(yīng)的字符串谊惭,二者有個(gè)一一對(duì)應(yīng)的轉(zhuǎn)換關(guān)系侮东,用一個(gè)功能函數(shù)來實(shí)現(xiàn)這種轉(zhuǎn)換:

ToFormateString

哎呀媽呀悄雅,步子太大宽闲,容易扯著蛋......

謹(jǐn)慎起見容诬,再跑一次原來的測(cè)試,次奧姚建,又失敗了掸冤,看來步子還是太小啊~~繼續(xù)扯:

因?yàn)闇y(cè)試用例已經(jīng)說明計(jì)時(shí)器是個(gè)獨(dú)立線程,所以給start函數(shù)添加這段代碼:

start
Run

再跑一次測(cè)試,次奧包斑,又是紅叉叉~這次問題出在哪里涕俗?多線程~

_currentPoint和_currentPointStr其實(shí)是共享資源再姑,使用時(shí)元镀,要加鎖的~這個(gè)不能忘~添加幾行代碼:

LCOK
Run

再跑一次測(cè)試栖疑,還是失敗遇革,依然是多線程的問題澳淑,這一次是多線程同步的問題,分析如下:

線程同步問題描述

主線程的計(jì)時(shí)時(shí)刻和計(jì)時(shí)器線程的計(jì)時(shí)時(shí)刻不同步,導(dǎo)致測(cè)試失敗氢拥,注意嫩海,這不是共享資源的同步問題叁怪,是時(shí)刻同步問題,So涣觉,使用同步事件和等待句柄(AutoResetEvent或ManualResetEvent)官册,不熟悉的看官直接MSDN搜查下:計(jì)時(shí)器是一個(gè)獨(dú)立線程膝宁,所以使用AutoResetEvent比較簡(jiǎn)單,修改代碼如下:

在TimeCounter中添加成員合蔽,并初始化:

AutoResetEvent

然后在Run()方法中的while循環(huán)下辈末,添加WaitOne句柄:

WaitOne

然后再ITimeCounter接口中增加對(duì)AutoResetEvent事件的控制方法及實(shí)現(xiàn):

SetAutoEvent
方法的實(shí)現(xiàn)

OK轰枝,這樣鞍陨,客戶端線程(其實(shí)就是這里的測(cè)試線程)就可以控制計(jì)時(shí)器的計(jì)時(shí)過程啦,讓你三更掛掉缭裆,絕對(duì)不會(huì)等到四更~接下來修改測(cè)試代碼:

which_in_the_time_then_TimeCounter_status_should_be_running

在主線程“計(jì)時(shí)過程”中控制計(jì)時(shí)器的計(jì)時(shí)過程澈驼,以此來保證同步(其實(shí)只是相對(duì)同步缝其,基于線程的概念内边,如果沒有硬件的外在支持待锈,在時(shí)間上的絕對(duì)同步是不現(xiàn)實(shí)的),運(yùn)行測(cè)試阳惹,OK眶俩,通過~

:https://msdn.microsoft.com/zh-cn/library/ms173179(VS.80).aspx——線程同步MSDN鏈接

總是編寫最小的代碼量來讓測(cè)試通過和小步前進(jìn)不沖突颠印,后者更偏向于說明運(yùn)行單元測(cè)試的時(shí)機(jī)线罕。

TestCase-2:


構(gòu)建單元測(cè)試用例:超過或到達(dá)t钞楼,返回時(shí)刻字符串和Over狀態(tài);

which_after_the_time_then_TimeCounter_status_should_be_over

阿西吧,這個(gè)測(cè)試沒通過~Why宛琅?問題出在最后一個(gè)斷言嘿辟,計(jì)時(shí)器的最大時(shí)刻就是t红伦,對(duì)于超出t的時(shí)刻昙读,計(jì)時(shí)器是無法獲取的,修改下某残,斷言計(jì)時(shí)器當(dāng)前時(shí)刻是其最大時(shí)刻:

修改最后一個(gè)斷言

運(yùn)行測(cè)試玻墅,OK澳厢,通過~ ?

針對(duì)第一個(gè)場(chǎng)景是不是就結(jié)束了剩拢,是嗎徐伐?對(duì)于TDD而言,這只是一個(gè)開始啊親~~

重構(gòu)——每次單元測(cè)試運(yùn)行通過以后角雷,都應(yīng)該考慮重構(gòu)


重構(gòu)勺三,是一個(gè)過程工具吗坚,每次測(cè)試通過之后呆万,都要重構(gòu)桑嘶,不僅是業(yè)務(wù)邏輯代碼逃顶,也包括測(cè)試代碼充甚。

先檢查業(yè)務(wù)邏輯代碼:TimeCounter伴找,還好技矮,沒有重復(fù)衰倦,命名基本達(dá)意,先過我磁,再看看單元測(cè)試代碼:

測(cè)試代碼中的重復(fù)

藍(lán)色框選中的代碼模擬的是主線程的計(jì)時(shí)芋哭,同時(shí)關(guān)聯(lián)控制計(jì)時(shí)器的計(jì)時(shí)郁副,兩個(gè)測(cè)試用例都需要這個(gè)功能存谎,所以可以提取方法:

MockTimeCount

兩個(gè)測(cè)試案例代碼修改為:

重構(gòu)后的測(cè)試案例代碼

因?yàn)镸ockTimeCount方法草雕,只和when_working_with_the_TimeCounter_start類有關(guān)系固以,所以把該方法上提至基類憨琳,更改訪問權(quán)限為protected篙螟。

切記切記遍略,你的每一次修改,都要運(yùn)行所有的但元測(cè)試下愈,至少對(duì)于目前的狀態(tài)是這樣的(不然势似,為啥要寫測(cè)試嘞~~~)履因。

OK栅迄,重構(gòu)暫時(shí)先到這里霞篡。

對(duì)于用戶場(chǎng)景1:

1 當(dāng)比賽時(shí)間完成時(shí),比賽結(jié)束污淋;

1.1 一個(gè)獨(dú)立線程計(jì)時(shí)器類寸爆,可以設(shè)置時(shí)間赁豆,開始計(jì)時(shí)魔种,當(dāng)計(jì)時(shí)結(jié)束時(shí)返回結(jié)束狀態(tài)节预;

TDD開發(fā)過程告一段落属韧,稍后宵喂,Pi君以另一篇文字記述用戶場(chǎng)景2的TDD過程锅棕。

有關(guān)FBGame項(xiàng)目源碼的github地址:

https://github.com/fei090620/FBGame.git

源碼會(huì)隨著文字的更新而更新哲戚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市王浴,隨后出現(xiàn)的幾起案子氓辣,更是在濱河造成了極大的恐慌钞啸,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異忱屑,居然都是意外死亡暇昂,警方通過查閱死者的電腦和手機(jī)急波,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門名段,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赏寇,“玉大人嗅定,你說我怎么就攤上這事渠退∷槟耍” “怎么了梅誓?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵梗掰,是天一觀的道長(zhǎng)及穗。 經(jīng)常有香客問我埂陆,道長(zhǎng),這世上最難降的妖魔是什么懂版? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任定续,我火速辦了婚禮,結(jié)果婚禮上禾锤,老公的妹妹穿的比我還像新娘私股。我一直安慰自己,他們只是感情好恩掷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布倡鲸。 她就那樣靜靜地躺著,像睡著了一般黄娘。 火紅的嫁衣襯著肌膚如雪峭状。 梳的紋絲不亂的頭發(fā)上逼争,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天优床,我揣著相機(jī)與錄音,去河邊找鬼誓焦。 笑死胆敞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的杂伟。 我是一名探鬼主播移层,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼赫粥!你這毒婦竟也來了观话?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤越平,失蹤者是張志新(化名)和其女友劉穎频蛔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秦叛,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帽驯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了书闸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡利凑,死狀恐怖浆劲,靈堂內(nèi)的尸體忽然破棺而出嫌术,到底是詐尸還是另有隱情,我是刑警寧澤牌借,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布度气,位于F島的核電站,受9級(jí)特大地震影響膨报,放射性物質(zhì)發(fā)生泄漏磷籍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一现柠、第九天 我趴在偏房一處隱蔽的房頂上張望院领。 院中可真熱鬧,春花似錦够吩、人聲如沸比然。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽强法。三九已至,卻和暖如春湾笛,著一層夾襖步出監(jiān)牢的瞬間饮怯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工嚎研, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蓖墅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓嘉赎,卻偏偏與公主長(zhǎng)得像置媳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子公条,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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