【Laravel5.2翻譯】單元測試


前陣子看了點Laravel源碼尖飞,越看越亂屏富,網(wǎng)上大部分中文文檔都是直譯奉瘤,比較生澀難懂泌射,還是決定看英文文檔順便就我的理解做下翻譯整理記錄下來

思維導圖

簡介

Laravel構(gòu)建的時候就帶上測試。實際上鞠苟,內(nèi)含支持PHPUnit的測試乞榨,開箱即用,同時已經(jīng)為你應用創(chuàng)建了phpunit.xml文件偶妖〗啵框架給你提供了方便的幫助方法,可以讓你形象地測試你應用趾访。

tests文件夾 提供了 ExampleText.php 文件态秧。安裝完Laravel應用,只要在命令行執(zhí)行vendor/bin下的 phpunit就能運行你的測試

測試環(huán)境

當你運行測試扼鞋,Laravel會自動為測試配置環(huán)境申鱼。測試的時候Laravel自動配置session和緩存到你的數(shù)組驅(qū)動,意味著測試的時候不會持久化session和緩存數(shù)據(jù)云头。
需要的話捐友,你可以自由的創(chuàng)建其他測試環(huán)境。測試環(huán)境的參數(shù)可以在phpunit.xml文件里配置溃槐,但要在運行測試前確保你用config:clear Artisan命令清理的配置緩存匣砖。

定義&運行測試

make:testArtisan命令創(chuàng)建一個新的測試案例:

php artisan make:test UserTest

這個命令會在tests文件夾下創(chuàng)建一個新的UserTest。然后你就可以像平時用PHPUnit一樣定義你的測試方法昏滴。只要執(zhí)行phpunit命令就可以運行測試:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class UserTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testExample()
    {
        $this->assertTrue(true);
    }
}

注意:如果在測試類定義你自己的setUp方法猴鲫,確保使用parent:setUp

應用測試

Laravel提供了非常流暢的API,可以讓你向引用發(fā)送Http請求,檢測輸出谣殊,甚至填充表單拂共。
例如,看下ExamleTest.php

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5')
             ->dontSee('Rails');
    }
}

visit方法向應用發(fā)送了一個Get請求姻几。see方法確保在返回的消息中可以看到給定文本宜狐。dontSee方法確保返回消息中沒有給定文本。這是Laravel可用的最基本的應用測試蛇捌。

和應用交互

當然抚恒,比起確保文本出現(xiàn)在給定回復,你可以做更多络拌。讓我們來看些點擊鏈接和填充表單的例子:

點擊鏈接
在這個測試中柑爸,我們將對應用發(fā)起請求,在返回的響應中“點擊”鏈接盒音,然后確保登入指定URL表鳍。例如,我們假設在返回的響應 有一個文本為“About Us”的鏈接:

<a href = "/about-us"> About Us</a>

現(xiàn)在祥诽,讓我們來寫一個測試點擊鏈接確保用戶打開正確的頁面:

public function testBasicExample()
{
    $this->visit('/')
         ->click('About Us')
         ->seePageIs('/about-us');
}

處理表單

Laravel也為測試表單提供了多重方法譬圣。type,select,check,attack,和press方法允許你和所有的表單輸入框做交互。例如雄坪,讓我們想象一下應用的注冊頁面上有這樣一個表單:

<form action="/register" method="POST">
    {{ csrf_field() }}

    <div>
        Name: <input type="text" name="name">
    </div>

    <div>
        <input type="checkbox" value="yes" name="terms"> Accept Terms
    </div>

    <div>
        <input type="submit" value="Register">
    </div>
</form>

我們可以編寫一個測試來填充表單來檢查結(jié)果:

public function testNewUserRegistration()
{
    $this->visit('/register')
         ->type('Taylor', 'name')
         ->check('terms')
         ->press('Register')
         ->seePageIs('/dashboard');
}

當然如果表單包含其他輸入比如單選按鈕和下拉菜單厘熟,你也可以輕松的填充這些字段類型。這里列出每個表單的操作方法:

方法 描述
$this->type($text, $elementName) 輸入文本
$this->select($value, $elementName) 選擇單選按鈕和下拉框
$this->check($elementName) 多選框選擇
$this->uncheck($elementName) 多選框取消選擇
$this->attach($pathToFile, $elementName) 添加附件
$this->press($buttonTextOrElementName) 點擊按鈕

處理附件

如果表單包含file輸入類型维哈,你可以用attach方法關(guān)聯(lián)

public function testPhotoCanBeUploaded()
{
    $this->visit('/upload')
         ->type('File Name', 'name')
         ->attach($absolutePathToFile, 'photo')
         ->press('Upload')
         ->see('Upload Successful!');
}

測試 JSON API

Laravel也為測試JSON API和它們的響應提供了許多幫助绳姨。例如,get,post,put,patchdelete方法用來解決各種HTTP請求阔挠。你也可以輕松用這些方法傳遞數(shù)據(jù)和頭文件飘庄。首先,讓我們寫一個測試购撼,對/user發(fā)送一個POST請求然后確保給定的數(shù)組在返回的Json格式中:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->json('POST', '/user', ['name' => 'Sally'])
             ->seeJson([
                 'created' => true,
             ]);
    }
}

seeJson方法把給定數(shù)組轉(zhuǎn)化成JSON,然后核實這個JSON片段是否在返回的JSON響應中出現(xiàn)跪削。所以,就算返回的JSON里有其他的屬性迂求,只要給定片段存在依然可以通過測試碾盐。

核實JSON精準匹配
如果你像核實給定數(shù)組完全匹配應用返回的JSON,你可以用seeJsonEqual方法:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->json('POST', '/user', ['name' => 'Sally'])
             ->seeJsonEquals([
                 'created' => true,
             ]);
    }
}

驗證JSON結(jié)構(gòu)匹配
你可以驗證返回JSON是否特定結(jié)構(gòu)揩局。為此毫玖,你可以使用seeJsonStructure方法同時傳遞一系列嵌套關(guān)鍵字:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->get('/user/1')
             ->seeJsonStructure([
                 'name',
                 'pet' => [
                     'name', 'age'
                 ]
             ]);
    }
}

上面的例子期望收到一個name和一個包含nameage的嵌套對象pet。只要額外關(guān)鍵字帶響應中存在seeJsonStructure就不會失敗凌盯。比如付枫,就算pet有一個weight屬性測試也會通過。

你可以使用*來確保返回的JSON結(jié)構(gòu)里每一個列表項都至少包含設置的屬性:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        // Assert that each user in the list has at least an id, name and email attribute.
        $this->get('/users')
             ->seeJsonStructure([
                 '*' => [
                     'id', 'name', 'email'
                 ]
             ]);
    }
}

你可以在嵌套中使用*十气,這樣的話励背,你可以確保每個用戶的數(shù)據(jù)里都包含給定的屬性集同是每個pet屬性都包含給定屬性集:

$this->get('/users')
     ->seeJsonStructure([
         '*' => [
             'id', 'name', 'email', 'pets' => [
                 '*' => [
                     'name', 'age'
                 ]
             ]
         ]
     ]);

Session/認證

Laravel為測試期間用session提供了一些幫助。首先砸西,你可以用withSession方法把session的數(shù)據(jù)設置成指定數(shù)組叶眉。這個方法對請求前加載session很有用:

<?php

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $this->withSession(['foo' => 'bar'])
             ->visit('/');
    }
}

當然,seesion常見的應用就是保存用戶狀態(tài)芹枷,比如認證用戶衅疙。actingAs方法提供了一個認證給定用戶為當前用戶的簡便方法。比如鸳慈,我們可以用model factory生成和認證一個用戶:

<?php

class ExampleTest extends TestCase
{
    public function testApplication()
    {
        $user = factory(App\User::class)->create();

        $this->actingAs($user)
             ->withSession(['foo' => 'bar'])
             ->visit('/')
             ->see('Hello, '.$user->name);
    }
}

你也可以指定用哪個guard來認證給定用戶饱溢,通過給actingAs方法的第二個參數(shù)傳遞一個guard名字:

$this->actingAs($user, 'backend')

中間件不可用

在測試你的應用的時候,你會發(fā)現(xiàn)你可以很方便的在某些測試中讓中間件不可用走芋。這將使你可以在隔離中間件的情況下測試你的路由和控制器绩郎。Laravel包含一個WithoutMiddlware trait潘鲫,你可以用他自動讓所有的中間件不可用。

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use WithoutMiddleware;

    //
}

如果你只想對某些測試方法無效化中間件肋杖,你可以在測試方法中調(diào)用withoutMiddleware方法:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->withoutMiddleware();

        $this->visit('/')
             ->see('Laravel 5');
    }
}

自定義HTTP請求

如果你像發(fā)送自定義HTTP請求來獲取完整的Illuminate\Http\Response對象溉仑,你可以使用call方法:

public function testApplication()
{
    $response = $this->call('GET', '/');

    $this->assertEquals(200, $response->status());
}

如果你創(chuàng)建一個POSTPUT或者PATCH請求状植,你可能需要傳送一個輸入數(shù)據(jù)的數(shù)組浊竟。當然,通過Request實例這些數(shù)據(jù)將在你的路由和控制器內(nèi)可用:

$response = $this->call('POST', '/user', ['name' => 'Taylor']);

PHPUnit 斷言

Laravel 為PHPUnit提供了多個額外的斷言方法:

方法 描述
->assertResponseOk(); 確認客戶端響應一個OK狀態(tài)
->assertResponseStatus($code); 確認客戶端響應一個指定代碼
->assertViewHas($key, $value = null); 確認客戶端響應視圖里有給定綁定數(shù)據(jù)片段
->assertViewHasAll(array $bindings); 確認客戶端響應視圖有給定綁定數(shù)據(jù)隊列
->assertViewMissing($key); 確認客戶端響應視圖缺失一對綁定數(shù)據(jù)
->assertRedirectedTo($uri, $with = []); 確認客戶端是否重定向到指定URL
->assertRedirectedToRoute($name, $parameters = [], $with = []); 確認客戶端是否重定向到指定路由
->assertRedirectedToAction($name, $parameters = [], $with = []); 確認客戶端是否重定向到指定動作
->assertSessionHas($key, $value = null); 確認Session里有給定值
->assertSessionHasAll(array $bindings); 確認Session中有給定值集合
->assertSessionHasErrors($bindings = [], $format = null); 確認Session有錯誤綁定
->assertHasOldInput(); 確認Session中有舊的輸入
->assertSessionMissing($key); 確認Session中缺失指定關(guān)鍵字

數(shù)據(jù)庫操作

Laravel提供了各種各樣有用的工具來簡化測試我們的數(shù)據(jù)庫驅(qū)動應用津畸。首先振定,你可以用seeInDatabase來確認數(shù)據(jù)庫里是存在符合你條件的數(shù)據(jù)。例如肉拓,如果你像驗證在user表中有條數(shù)據(jù)它email值為sally@example.com后频,你可以這樣寫:

 public function testDatabase()
{
    // Make call to application...

    $this->seeInDatabase('users', ['email' => 'sally@example.com']);
}

當然,seeInDatabase方法和其他類似的幫助方法都是為了方便帝簇。你可以自由使用任何PHPUnit的內(nèi)建斷言方法來支持你的測試徘郭。

測試后重置數(shù)據(jù)庫

在測試后重置數(shù)據(jù)庫是很有用的,這讓后續(xù)測試不會受到前面測試的數(shù)據(jù)影響丧肴。

使用Migration

一個選擇就是每次測試完都回滾數(shù)據(jù)庫然后在下次測試前移植過去残揉。Laravel提供了DatabaseMigrationstrait來自動進行這些操作:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseMigrations;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5');
    }
}

使用會話
另一個選擇就是把每個測試案列包括在一個數(shù)據(jù)庫會話中。同樣的芋浮,Laravel提供了一個方便的DatabaseTransactionstrait來自動操作這些:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseTransactions;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5');
    }
}

注意:這個trait只是把默認的數(shù)據(jù)庫連接包裹在會話中

模塊工廠

在指定測試前抱环,一般都需要插入一些記錄到數(shù)據(jù)庫中。Laravel允許使用"工廠"為你所有的Eloquent models定義一個屬性集合纸巷,你就不用在你創(chuàng)建測試數(shù)據(jù)的時候手動指定每一列的值了镇草。首先,讓我們看一下database/factories/ModelFactory.php瘤旨,開箱即用梯啤,這個文件包含一個工程定義:

$factory->define(App\User::class, function (Faker\Generator $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => bcrypt(str_random(10)),
        'remember_token' => str_random(10),
    ];
});

在factory定義的閉包中,你可以返回模塊上的所有屬性的測試值存哲。這個閉包會接受一個Faker PHP Library實例因宇,它允許你很方便的生成各種隨機的數(shù)據(jù)來測試。

當然祟偷,你可以自由地在ModelFactory.php中添加自己的額外工廠察滑。你也可以為每個model添加另外的工廠文件來更好的組織。比如修肠,你可以在你的database/factories目錄下創(chuàng)建UserFactory.phpCommentFactory.php文件贺辰。

多樣工廠類型

有時候你像為同一個Eloquent model類創(chuàng)建多個工程溉浙。比如除了普通用戶你還想為管理員用戶添加工程筷屡。你可以用defineAs方法定義這些工程:

$factory->defineAs(App\User::class, 'admin', function ($faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => str_random(10),
        'remember_token' => str_random(10),
        'admin' => true,
    ];
});

如果不想從基礎用戶工廠中復制所有屬性挣磨,你可以用raw方法來獲取基類的所有屬性金蜀。然后你只要任何你要加的值添加進去就可以了:

$factory->defineAs(App\User::class, 'admin', function ($faker) use ($factory) {
    $user = $factory->raw(App\User::class);

    return array_merge($user, ['admin' => true]);
});

在測試中用工廠
當你定義好工廠,你可以用factory方法在你的測試或數(shù)據(jù)庫seed文件中使用它們來生成model實例吃靠。讓我們看一些創(chuàng)建model的例子蒋川。首先,我們用make方法撩笆,它會創(chuàng)建model但不會存入數(shù)據(jù)庫:

public function testDatabase()
{
    $user = factory(App\User::class)->make();

    // Use model in tests...
}

如果你想重寫一些你model中的默認值,你可以給make方法傳遞一個數(shù)組缸浦。只有指定的值會被替換夕冲,其他的值都會保留你在工廠中定義的默認值:

$user = factory(App\User::class)->make([
    'name' => 'Abigail',
   ]);

你也可以創(chuàng)建一個model集合或者創(chuàng)建一個給定類型的model:

// Create three App\User instances...
$users = factory(App\User::class, 3)->make();

// Create an App\User "admin" instance...
$user = factory(App\User::class, 'admin')->make();

// Create three App\User "admin" instances...
$users = factory(App\User::class, 'admin', 3)->make();

持久化工廠model
create方法不但創(chuàng)建model實例,還會用Eloquent的save方法把它們存入數(shù)據(jù)庫:

public function testDatabase()
{
    $user = factory(App\User::class)->create();

    // Use model in tests...
}

同樣的裂逐,你可以通過給create方法傳數(shù)組來重寫model屬性:

$user = factory(App\User::class)->create([
    'name' => 'Abigail',
   ]);

為Model添加關(guān)聯(lián)
你或許想保存多個model到數(shù)據(jù)庫歹鱼。在這個例子中,你可以對一個已建model附加關(guān)聯(lián)卜高。當你用create方法創(chuàng)建多個models弥姻,會返回一個Eloquent collection實例,它讓你可以用它提供的任何快捷函數(shù)掺涛,比如each

$users = factory(App\User::class, 3)
           ->create()
           ->each(function ($u) {
                $u->posts()->save(factory(App\Post::class)->make());
            });

關(guān)聯(lián)和屬性閉包
你可以在工廠定義中用屬性閉包添加關(guān)聯(lián)庭敦。比如,如果你想在創(chuàng)建Post的時候創(chuàng)建一個User,你可以這樣做:

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        }
    ];
});

這些閉包還能接收工廠的屬性數(shù)組:

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        },
        'user_type' => function (array $post) {
            return App\User::find($post['user_id'])->type;
        }
    ];
});

模仿

模仿事件

如果你在大量使用Laravel的事件系統(tǒng)薪缆,你可能希望在測試中有一個讓事件安靜下來或者模擬它秧廉。比如,如果你在測試用戶注冊拣帽,你可能不希望所有的UserRegistered事件操作被執(zhí)行疼电,因為它們會發(fā)送一個welcome電子郵件等等。
Laravel提供了一個expectsEvents方法來驗證預計的時間被執(zhí)行减拭,同時阻止任何這些時間的操作被執(zhí)行:

<?php

class ExampleTest extends TestCase
{
    public function testUserRegistration()
    {
        $this->expectsEvents(App\Events\UserRegistered::class);

        // Test user registration...
    }
}

你可以用doesntExpectEvents方法來驗證給定事件沒有被觸發(fā):

<?php

class ExampleTest extends TestCase
{
    public function testPodcastPurchase()
    {
        $this->expectsEvents(App\Events\PodcastWasPurchased::class);

        $this->doesntExpectEvents(App\Events\PaymentWasDeclined::class);

        // Test purchasing podcast...
    }
}

如果你像阻止所有的事件操作蔽豺,你可以用withoutEvents方法:

<?php

class ExampleTest extends TestCase
{
    public function testUserRegistration()
    {
        $this->withoutEvents();

        // Test user registration code...
    }
}

模擬工作

有時候,當你發(fā)送請求給應用的時候你想測試特定工作是否被控制器分派下來拧粪。這允許你隔離工作邏輯來測試路由或者控制器修陡。當然,你可以在獨立的測試類里測試工作既们。

Laravel提供了expectsJobs方法來驗證預期的工作有沒有分派下來濒析,但不會執(zhí)行工作:

<?php

class ExampleTest extends TestCase
{
    public function testPurchasePodcast()
    {
        $this->expectsJobs(App\Jobs\PurchasePodcast::class);

        // Test purchase podcast code...
    }
}

注意:這個方法只會檢索通過DispatchesJobs trait或者dispatch幫助函數(shù)分派下來的方法。它不會檢索由Queue::push直接發(fā)送下來的工作啥纸。

模擬門面

在測試中号杏,你可能經(jīng)常希望模擬調(diào)用一個Laravel門面,例如,看一下下面的控制器動作:

<?php

namespace App\Http\Controllers;

use Cache;

class UserController extends Controller
{
    /**
     * Show a list of all users of the application.
     *
     * @return Response
     */
    public function index()
    {
        $value = Cache::get('key');

        //
    }
}

你可以使用shouldReceive方法模擬調(diào)用Cache門面盾致,它會返回一個Mockery實例主经。由于門面實際上由Laravel的服務容器處理和管理的,它們會比典型的靜態(tài)類更容易測試庭惜。例如罩驻,讓我們模擬條用Cache門面:

<?php

class FooTest extends TestCase
{
    public function testGetIndex()
    {
        Cache::shouldReceive('get')
                    ->once()
                    ->with('key')
                    ->andReturn('value');

        $this->visit('/users')->see('value');
    }
}

注意:在你運行測試的時候,不要去模擬Request門面护赊,你應該把你想要的輸入傳入HTTP幫助方法比如callpost

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惠遏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子骏啰,更是在濱河造成了極大的恐慌节吮,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件判耕,死亡現(xiàn)場離奇詭異透绩,居然都是意外死亡,警方通過查閱死者的電腦和手機壁熄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門帚豪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人草丧,你說我怎么就攤上這事狸臣。” “怎么了方仿?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵固棚,是天一觀的道長。 經(jīng)常有香客問我仙蚜,道長此洲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任委粉,我火速辦了婚禮呜师,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贾节。我一直安慰自己汁汗,他們只是感情好,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布栗涂。 她就那樣靜靜地躺著知牌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪斤程。 梳的紋絲不亂的頭發(fā)上角寸,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機與錄音,去河邊找鬼扁藕。 笑死沮峡,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的亿柑。 我是一名探鬼主播邢疙,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼望薄!你這毒婦竟也來了疟游?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤痕支,失蹤者是張志新(化名)和其女友劉穎乡摹,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體采转,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年瞬痘,在試婚紗的時候發(fā)現(xiàn)自己被綠了故慈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡框全,死狀恐怖察绷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情津辩,我是刑警寧澤拆撼,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站喘沿,受9級特大地震影響闸度,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蚜印,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一莺禁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窄赋,春花似錦哟冬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至错敢,卻和暖如春翰灾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工预侯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留致开,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓萎馅,卻偏偏與公主長得像双戳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子飒货,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

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