iOS UnitTest單元測試

一、單元測試的定義

在計(jì)算機(jī)編程中,單元測試(英語:Unit Testing)又稱為模塊測試, 是針對程序模塊(軟件設(shè)計(jì)的最小單位)來進(jìn)行正確性檢驗(yàn)的測試工作。程序單元是應(yīng)用的最小可測試部件。

在過程化編程中褂傀,一個單元就是單個程序、函數(shù)加勤、過程等仙辟;對于面向?qū)ο缶幊蹋钚卧褪欠椒罚ɑ悾ǔ悾┑⒊橄箢悺⒒蛘吲缮悾ㄗ宇悾┲械姆椒ā?/p>

根據(jù)不同場景戴尸,單元的定義也不一樣粟焊,通常我們將C語言的單個函數(shù)或者面向?qū)ο笳Z言的單個類視作測試的單元。在使用單元測試的過程中孙蒙,我們要知道這一點(diǎn):

單元測試并不是為了證明代碼的正確性吆玖,它只是一種用來幫助我們發(fā)現(xiàn)錯誤的手段

單元測試不是萬能藥,它確實(shí)能幫助我們找到大部分代碼邏輯上的bug马篮,同時,為了提高測試覆蓋率怜奖,這能逼迫我們對代碼不斷進(jìn)行重構(gòu)浑测,提高代碼質(zhì)量等。

二歪玲、iOS單元測試

xcode本身的測試框架集成:在Xcode4.x中集成了測試框架OCUnit迁央,UI Tests是iOS9推出的新特性。目前我們在創(chuàng)建項(xiàng)目的時候會默認(rèn)選中有關(guān)測試的這兩項(xiàng):Include Unit Tests滥崩、Include UI Tests岖圈。在創(chuàng)建項(xiàng)目之后,會自動生成一個appName+Tests的文件夾目錄钙皮,下面存放著單元測試的文件蜂科。

根據(jù)測試的目的大致可以將單元測試分為這三類:
a.性能測試:測試代碼執(zhí)行花費(fèi)的時間
b.邏輯測試:測試代碼執(zhí)行結(jié)果是否符合預(yù)期
c.異步測試:測試多線程操作代碼

UnitTest文件里面方法介紹:

- (void)setUp {//每一個測試用例開始前調(diào)用顽决,用來初始化相關(guān)數(shù)據(jù)
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
}

- (void)tearDown {//測試用例完成后調(diào)用,可以用來釋放變量等結(jié)尾操作
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

\- (void)testExample {//用來執(zhí)行我們需要的測試操作,正常情況下导匣,我們不使用這個方法才菠,而是創(chuàng)建名為test+測試目的的方法來完成我們需要的操作(注意:此時自定義的方法需要以test開頭方能進(jìn)行測試,否則左邊是不顯示菱形的)
    // This is an example of a functional test case.
    // Use XCTAssert and related functions to verify your tests produce the correct results.
}

\- (void)testPerformanceExample {//會將方法中的block代碼耗費(fèi)時長打印出來--默認(rèn)執(zhí)行了10次贡定,打印出了平均耗時赋访,和各次的耗時,最大誤差不超過10%缓待。其中運(yùn)行之后block這行右側(cè)顯示的就是平均耗時蚓耽。
    // This is an example of a performance test case.
    [self measureBlock:^{
        // Put the code you want to measure the time of here.
    }];
}

在每個測試用例方法的左側(cè)有個菱形的標(biāo)記,點(diǎn)擊這個標(biāo)記可以單獨(dú)的運(yùn)行這個測試方法旋炒。如果測試通過沒有發(fā)生任何斷言錯誤步悠,那么這個菱形就會變成綠色勾選狀態(tài)。使用快捷鍵command+U直接依次調(diào)用所有的單元測試国葬。

另外贤徒,可以在左側(cè)的文件欄中選中單元測試欄目,然后直觀的看到所有測試的結(jié)果汇四。同樣的點(diǎn)擊右側(cè)菱形位置的按鈕可以運(yùn)行單個測試方法或者文件:


01.png

為了保證單元測試的正確性接奈,我們應(yīng)當(dāng)保證測試用例中只存在一個類或者只發(fā)生一個類變量的屬性修改。下面是我們測試中常用的宏定義:(XCTest 帶有許多內(nèi)建的斷言)

XCTAssertNotNil(a1, format…) 當(dāng)a1不為nil時成立
XCTAssert(expression, format...) 當(dāng)expression結(jié)果為YES成立
XCTAssertTrue(expression, format...) 當(dāng)expression結(jié)果為YES成立通孽;
XCTAssertEqualObjects(a1, a2, format...) 判斷相等序宦,當(dāng)[a1 isEqualTo: a2]返回YES的時候成立
XCTAssertEqual(a1, a2, format...) 當(dāng)a1==a2返回YES時成立
XCTAssertNotEqual(a1, a2, format...) 當(dāng)a1!=a2返回YES時成立
</br>
&&

XCTFail(format…) 生成一個失敗的測試; 
XCTAssertNil(a1, format...)為空判斷背苦,a1為空時通過互捌,反之不通過;
XCTAssertNotNil(a1, format…)不為空判斷行剂,a1不為空時通過秕噪,反之不通過;
XCTAssert(expression, format...)當(dāng)expression求值為TRUE時通過厚宰;
XCTAssertTrue(expression, format...)當(dāng)expression求值為TRUE時通過腌巾;
XCTAssertFalse(expression, format...)當(dāng)expression求值為False時通過;
XCTAssertEqualObjects(a1, a2, format...)判斷相等铲觉,[a1 isEqual:a2]值為TRUE時通過澈蝙,其中一個不為空時,不通過撵幽;
XCTAssertNotEqualObjects(a1, a2, format...)判斷不等灯荧,[a1 isEqual:a2]值為False時通過;
XCTAssertEqual(a1, a2, format...)判斷相等(當(dāng)a1和a2是 C語言標(biāo)量盐杂、結(jié)構(gòu)體或聯(lián)合體時使用, 判斷的是變量的地址逗载,如果地址相同則返回TRUE哆窿,否則返回NO);
XCTAssertNotEqual(a1, a2, format...)判斷不等(當(dāng)a1和a2是 C語言標(biāo)量撕贞、結(jié)構(gòu)體或聯(lián)合體時使用)更耻;
XCTAssertEqualWithAccuracy(a1, a2, accuracy, format...)判斷相等,(double或float類型)提供一個誤差范圍捏膨,當(dāng)在誤差范圍(+/-accuracy)以內(nèi)相等時通過測試秧均;
XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format...) 判斷不等,(double或float類型)提供一個誤差范圍号涯,當(dāng)在誤差范圍以內(nèi)不等時通過測試目胡;
XCTAssertThrows(expression, format...)異常測試,當(dāng)expression發(fā)生異常時通過链快;反之不通過誉己;(很變態(tài)) XCTAssertThrowsSpecific(expression, specificException, format...) 異常測試,當(dāng)expression發(fā)生specificException異常時通過域蜗;反之發(fā)生其他異尘匏或不發(fā)生異常均不通過;
XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)異常測試霉祸,當(dāng)expression發(fā)生具體異常筑累、具體異常名稱的異常時通過測試,反之不通過丝蹭;
XCTAssertNoThrow(expression, format…)異常測試慢宗,當(dāng)expression沒有發(fā)生異常時通過測試;
XCTAssertNoThrowSpecific(expression, specificException, format...)異常測試奔穿,當(dāng)expression沒有發(fā)生具體異常镜沽、具體異常名稱的異常時通過測試,反之不通過贱田;
XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)異常測試缅茉,當(dāng)expression沒有發(fā)生具體異常、具體異常名稱的異常時通過測試男摧,反之不通過

三宾舅、測試
1、邏輯測試:邏輯測試的目的是為了檢測在代碼執(zhí)行前后發(fā)生的變化是否符合預(yù)期

e.g:

@interface TestModel1 : NSObject

@property (nonatomic, copy) NSString * name;
@property (nonatomic, strong) NSNumber * age;
@property (nonatomic, assign) NSUInteger flags;
+ (instancetype)modelWithName: (NSString *)name age: (NSNumber *)age flags: (NSUInteger)flags;
- (instancetype)initWithDictionary: (NSDictionary *)dict;
- (NSDictionary *)modelToDictionary;

@end

@implementation TestModel1

+ (instancetype)modelWithName:(NSString *)name age:(NSNumber *)age flags:(NSUInteger)flags
{
    TestModel1 *model = [[self alloc] init];
    model.name = name;
    model.age = age;
    model.flags = flags;
    return model;
    
}

- (instancetype)initWithDictionary: (NSDictionary *)dict
{

    self.name = dict[@"name"];
    self.age  = dict[@"age"];
    self.flags = [dict[@"flags"] integerValue];
    
    return self;
}

- (NSDictionary *)modelToDictionary
{
    return @{@"name":self.name,@"age":self.age,@"flags":[NSNumber numberWithInteger:self.flags]};
}

@end

然后在測試文件里面:

\- (void)testModelConvert
{
    NSString * json = @"{\"name\":\"SindriLin\",\"age\":22,\"flags\":987654321}";
    NSMutableDictionary * dict = [[NSJSONSerialization JSONObjectWithData: [json dataUsingEncoding: NSUTF8StringEncoding] options: kNilOptions error: nil] mutableCopy];
    TestModel1 * model = [[TestModel1 alloc] initWithDictionary: dict];
    XCTAssertNotNil(model);
    XCTAssertTrue([model.name isEqualToString: @"SindriLin"]);
    XCTAssertTrue([model.age isEqual: @(22)]);
    XCTAssertEqual(model.flags, 987654321);
    XCTAssertTrue([model isKindOfClass: [TestModel1 class]]);
    model = [TestModel1 modelWithName: @"Tessie" age: dict[@"age"] flags: 562525];
    XCTAssertNotNil(model);
    XCTAssertTrue([model.name isEqualToString: @"Tessie"]);
    XCTAssertTrue([model.age isEqual: dict[@"age"]]);
    XCTAssertEqual(model.flags, 562525);
    NSDictionary * modelJSON = [model modelToDictionary];
    XCTAssertTrue([modelJSON isEqual: dict] == NO);
    dict[@"name"] = @"Tessie";
    dict[@"flags"] = @(562525);
    XCTAssertTrue([modelJSON isEqual: dict]);
}
2彩倚、性能測試:

在平常的工作中,我們還可以通過: instrument(xcode->product->profile)工具很好的查找到項(xiàng)目中的代碼耗時點(diǎn)扶平,(后面介紹)帆离。先介紹單元測試的性能測試:

測試文件:

\- (void)testPerformanceExample {//會將方法中的block代碼耗費(fèi)時長打印出來--默認(rèn)執(zhí)行了10次,打印出了平均耗時结澄,和各次的耗時哥谷,最大誤差不超過10%岸夯。
    // This is an example of a performance test case.
    [self measureBlock:^{
        // Put the code you want to measure the time of here.
        [TestModel1 randomModels];
//        for (int i = 0; i<100; ++i) {
//            NSLog(@"wgj:%d",i);
//        }
    }];
}

自定義的model文件中添加:

\+ (NSArray<TestModel1 *> *)randomModels
{
    NSMutableArray * models = @[].mutableCopy;
    NSArray * names = @[
                        @"xiaoli01", @"xiaoli02", @"xiaoli03", @"xiaoli04", @"xiaoli05"
                        ];
    NSArray * ages = @[
                       @15, @20, @25, @30, @35
                       ];
    NSArray * flags = @[
                        @123, @456, @789, @012, @234
                        ];
    for (NSUInteger idx = 0; idx < 100; idx++) {
        TestModel1 * model = [self modelWithName: names[arc4random() % names.count] age: ages[arc4random() % ages.count] flags: [flags[arc4random() % flags.count] unsignedIntegerValue]];
        [models addObject: model];
        [NSThread sleepForTimeInterval: 0.01];
    }
    return models;
}
02.png

在平常的test方法中,也會打印測試方法的執(zhí)行時間们妥,例如下面,但是沒有上面這種在性能測試方法中測的準(zhǔn)確猜扮。


01.png

打印臺會打印各測試方法的耗時,直接使用單元測試來獲取某段代碼的執(zhí)行時間要比使用instrument快的多(instrument定位更精確)监婶。通過性能測試直觀的獲取執(zhí)行時間后旅赢,我們可以根據(jù)需要來決定是否將這些代碼放到子線程中執(zhí)行來優(yōu)化代碼(很多時候,數(shù)據(jù)轉(zhuǎn)換會占用大量的CPU計(jì)算資源)

3.異步測試

在Xcode 6之前的版本里面并沒有內(nèi)置XCTest惑惶,想使用Xcode測試的只能是在主線程的RunLoop里面使用一個while循環(huán),然后一直等待響應(yīng)或者直到timeout.(Xcode 6中添加了新特性:XCTestExpectation 和性能測試:特性是內(nèi)建的對于異步測試的支持煮盼,測試能夠?yàn)榱舜_定的合適的條件等待一個指定時間長度,而不需要求助于GCD)

e.g.老方法:
\- (void)testAsync
{// 異步測試
    NSDictionary * dict = @{
                            @"name": @"MrLi",
                            @"age": @28,
                            @"flags": @987
                            };
    TestModel1 * model = [[TestModel1 alloc] initWithDictionary: dict];
    XCTAssertNotNil(model);
    [model asyncConvertToData];
    while (model.data == nil) {
        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.01, YES);
        NSLog(@"waiting");
    }
    XCTAssertNotNil(model.data);
    NSLog(@"convert finish %@", model.data);
}

model文件:

\- (void)asyncConvertToData
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSDictionary * modelJSON = nil;
        for (NSInteger idx = 0; idx < 20; idx++) {
            modelJSON = [self modelToDictionary];
            [self setValuesForKeysWithDictionary: modelJSON];
            [NSThread sleepForTimeInterval: 0.001];
        }
        _data = [NSJSONSerialization dataWithJSONObject: modelJSON options: NSJSONWritingPrettyPrinted error: nil];
    });
}
e.g.新方法

在Xcode 6里带污,蘋果以XCTestExpection類的方式向XCTest框架里添加了測試期望(test expection)僵控。當(dāng)我們實(shí)例化一個測試期望(XCTestExpectation)的時候,測試框架就會預(yù)計(jì)它在之后的某一時刻被實(shí)現(xiàn)鱼冀。最終的程序完成代碼塊中的測試代碼會調(diào)用XCTestExpection類中的fulfill方法來實(shí)現(xiàn)期望报破。
我們讓測試框架等待(有時限)測試期望通過XCTestCase的waitForExpectationsWithTimeout:handler:方法實(shí)現(xiàn)。如果完成處理的代碼在指定時限里執(zhí)行并調(diào)用了fulfill方法千绪,那么就說明所有的測試期望在此期間都已經(jīng)被實(shí)現(xiàn)充易。此方法中的handler的參數(shù)其實(shí)是一個block,block中若是寫有代碼翘紊,代碼執(zhí)行的條件(滿足其中之一就可執(zhí)行):a蔽氨、所有期望在指定的時間內(nèi)都以實(shí)現(xiàn); b帆疟、期望在指定的時間內(nèi)沒有實(shí)現(xiàn)(此時會報錯鹉究,但是block里面的方法會執(zhí)行)。
代碼:
<pre>
- (void)testAsyncOutTime{

XCTestExpectation *ex = [self expectationWithDescription:@"wgj001"];

NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

NSURLRequest *request = [NSURLRequest requestWithURL:url];

NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NSLog(@"url請求完成");
    [ex fulfill];//如果完成處理的代碼在指定時限里執(zhí)行并調(diào)用了fulfill方法踪宠,那么就說明所有的測試期望在此期間都已經(jīng)被實(shí)現(xiàn)
    
}];
[task resume];

[self waitForExpectationsWithTimeout:1 handler:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"wati:%@",error);
    }

// [task cancel];
NSLog(@"url請求超時-結(jié)束");
}];

}

</pre>

斷言(詳解):

<pre>
1自赔、XCTFail(...):參數(shù)可有可無,若有則須是字符串柳琢,參數(shù)為錯誤的描述绍妨。無條件的都是測試失敗。在測試驅(qū)動里有這么個情況柬脸,你定義了測試方法他去,但是沒有給出具體的實(shí)現(xiàn)。那么你不會希望這個測試能通過的倒堕。一般被用作一個占位斷言灾测。等你的測試方法完善好了之后再換成最貼近你的測試的斷言。有或者垦巴,在某些情況下else了之后就是不應(yīng)該出現(xiàn)的情況媳搪。那么這個時候可以把XCTFail放在這個else里面铭段。
2、XCTAssertNil(expression, ...)/XCTAssertNotNil(expression, ...):判斷給定的表達(dá)式值是否為nil, XCTAssertNil(表達(dá)式為nil的時候通過)秦爆,XCTAssertNotNil(表達(dá)式不為nil的時候通過),其中...是錯誤描述序愚,為字符串類型,下面的表達(dá)式中的意思都是一樣的等限。
3爸吮、XCTAssert(expression, ...):如果expression(表達(dá)式)執(zhí)行的結(jié)果為true的話,這個測試通過精刷。否則拗胜,測試失敗,并在console中輸出后面的format字符串.
4怒允、后面基于XCTAssert演化出來的斷言埂软,不僅可以滿足測試的需求而且可以更好更明確的表達(dá)出你要測試的是什么。最好是使用這些演化出來的斷言:

a. Bool測試
對于bool型的數(shù)據(jù)纫事,或者只是簡單的bool型的表達(dá)式勘畔,使用XCTestAssertTrue或者XCTestAssertFalse:
XCTAssertTrue(expression, format...)
XCTAssertFalse(expression, format...)

b. 相等測試
測試兩個數(shù)值的值是否相等使用XCTAssert[Not]Equal:
XCTAssertEqual(expression1, expression2, format...)
XCTAssertNotEqual(expression1, expression2, format...);
判斷兩個對象用:XCTAssertEqualObjects(expression1, expression2, ...)和XCTAssertNotEqualObjects(expression1, expression2, ...)

在Double、Float型數(shù)據(jù)的對比中使用XCTAssert[Not]EqualWithAccuracy來處理浮點(diǎn)精度的問題:
XCTAssertEqualWithAccuracy(expression1, expression2, accuracy, format...)
XCTAssertNotEqualWithAccuracy(expression1, expression2, accuracy, format...)
e.g. XCTAssertEqualWithAccuracy(12, 14, 1,@"wgj"),則不通過丽惶,因?yàn)?2和14的差別已經(jīng)超過了設(shè)定的值1炫七。

XCTAssertGreaterThan[OrEqual] & XCTAssertLessThan[OrEqual], 和下面的條件操作符比較的是一個意思 == with >, >=, <, 以及 <=

5、拋異常:
a.
XCTAssertThrows(expression, ...):表達(dá)式拋異常時钾唬,通過万哪;反之,不通過抡秆。e.g. XCTAssertThrows([model onlyTest],@"wgj01");方法在model中只有聲明但沒有實(shí)現(xiàn)奕巍,此表達(dá)式是會異常的,但是這句測試的代碼則是通過的儒士。
b.
XCTAssertThrowsSpecific(expression, exception_class, ...):表達(dá)式 拋出異常的止,并且拋出的異常類屬于NSException,才會執(zhí)行通過着撩;反之诅福。
e.g.
XCTAssertThrowsSpecific([model onlyTest02],NSException,@"wgj001");--onlyTest02方法實(shí)現(xiàn)時:運(yùn)行崩潰;onlyTest02方法未實(shí)現(xiàn)時拖叙,執(zhí)行未實(shí)現(xiàn)的方法氓润,系統(tǒng)會自動生成NSException類型的異常,符合定義的NSException類薯鳍,測試代碼運(yùn)行通過旺芽。
c.
XCTAssertThrowsSpecificNamed(expression, exception_class, exception_name, ...):表達(dá)式拋出異常,并且拋出的異常類屬于NSException,并且異常類的名字符合定義的名字時采章,才會執(zhí)行通過;反之壶辜。
e.g.
XCTAssertThrowsSpecificNamed([model onlyExceptionTest], NSException, @"自定義異常",@"wgj002");
model中的實(shí)現(xiàn)方法:

  • (void)onlyExceptionTest{
    NSException *exx = [NSException exceptionWithName:@"自定義異常" reason:@"崩潰test02" userInfo:@{@"key02":@"value02"}];

      @throw exx;
    

}
此種悯舟,測試代碼是通過的。
若改為:
XCTAssertThrowsSpecificNamed([model onlyExceptionTest], NSException, @"隨便寫的名字",@"wgj002");則測試代碼不通過砸民,因?yàn)楫惓C植黄ヅ洹?br> </pre>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抵怎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子岭参,更是在濱河造成了極大的恐慌反惕,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件演侯,死亡現(xiàn)場離奇詭異姿染,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)秒际,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門悬赏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人娄徊,你說我怎么就攤上這事闽颇。” “怎么了寄锐?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵兵多,是天一觀的道長。 經(jīng)常有香客問我橄仆,道長剩膘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任沿癞,我火速辦了婚禮援雇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘椎扬。我一直安慰自己惫搏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布蚕涤。 她就那樣靜靜地躺著筐赔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪揖铜。 梳的紋絲不亂的頭發(fā)上茴丰,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼贿肩。 笑死峦椰,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的汰规。 我是一名探鬼主播汤功,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼溜哮!你這毒婦竟也來了滔金?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤茂嗓,失蹤者是張志新(化名)和其女友劉穎餐茵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體述吸,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忿族,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了刚梭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肠阱。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖朴读,靈堂內(nèi)的尸體忽然破棺而出屹徘,到底是詐尸還是另有隱情,我是刑警寧澤衅金,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布噪伊,位于F島的核電站,受9級特大地震影響氮唯,放射性物質(zhì)發(fā)生泄漏鉴吹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一惩琉、第九天 我趴在偏房一處隱蔽的房頂上張望豆励。 院中可真熱鬧,春花似錦瞒渠、人聲如沸良蒸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嫩痰。三九已至,卻和暖如春窍箍,著一層夾襖步出監(jiān)牢的瞬間串纺,已是汗流浹背丽旅。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纺棺,地道東北人榄笙。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像祷蝌,于是被迫代替她去往敵國和親办斑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

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