2010-02-16 191 views
6

我是單元測試新手,所以這可能有點愚蠢的問題。想象一下,我們有一個簡單的模型方法。Codeigniter單元測試模型

public function get_all_users($uid = false, $params = array()){ 
    $users = array(); 
    if(empty($uid) && empty($params)){return $users;} 
    $this->db->from('users u'); 
    if($uid){ 
     $this->db->where('u.id',(int)$id); 
    } 
    if(!empty($params)){ 
     if(isset($params['is_active']){ 
      $this->db->where('u.status ', 'active'); 
     } 
     if(isset($params['something_else']){ // some more filter actions} 
    } 
    $q = $this->db->get(); 
    if($q->num_rows()){ 
     foreach($q->result_array() as $user){ 
      $users[$user['id']] = $user; 
     } 
    } 
    $q->free_result(); 
    return $users; 
} 

問題是如何爲它編寫_good測試? UPD:我想,CI的最佳單元測試庫是Toast,所以我正在尋找的例子,最好是使用它來編寫。 謝謝。

回答

10

我也用烤麪包,而且大多數情況下我用它來測試模型方法。要做到這一點,首先截斷所有表值,插入一個預定義的值,然後得到它。這是我在應用程序中使用測試的例子:我在我的應用程序中使用ADODB

class Jobads_tests extends Toast 
{ 
    function Jobads_tests() 
    { 
    parent::Toast(__FILE__); 
    // Load any models, libraries etc. you need here 
    $this->load->model('jobads_draft_model'); 
    $this->load->model('jobads_model'); 
    } 

    /** 
    * OPTIONAL; Anything in this function will be run before each test 
    * Good for doing cleanup: resetting sessions, renewing objects, etc. 
    */ 
    function _pre() 
    { 
    $this->adodb->Execute("TRUNCATE TABLE `jobads_draft`"); 
    } 

    /** 
    * OPTIONAL; Anything in this function will be run after each test 
    * I use it for setting $this->message = $this->My_model->getError(); 
    */ 
    function _post() 
    { 
    $this->message = $this->jobads_draft_model->display_errors(' ', '<br/>'); 
    $this->message .= $this->jobads_model->display_errors(' ', '<br/>'); 
    } 

    /* TESTS BELOW */ 
    function test_insert_to_draft() 
    { 
    //default data 
    $user_id = 1; 

    //test insert 
    $data = array(
     'user_id' => $user_id, 
     'country' => 'ID', 
     'contract_start_date' => strtotime("+1 day"), 
     'contract_end_date' => strtotime("+1 week"), 
     'last_update' => time() 
    ); 
    $jobads_draft_id = $this->jobads_draft_model->insert_data($data); 
    $this->_assert_equals($jobads_draft_id, 1); 

    //test update 
    $data = array(
     'jobs_detail' => 'jobs_detail', 
     'last_update' => time() 
    ); 
    $update_result = $this->jobads_draft_model->update_data($jobads_draft_id, $data); 
    $this->_assert_true($update_result); 

    //test insert_from_draft 
    $payment_data = array(
     'activation_date' => date('Y-m-d', strtotime("+1 day")), 
     'duration_amount' => '3', 
     'duration_unit' => 'weeks', 
     'payment_status' => 'paid', 
     'total_charge' => 123.45 
    ); 
    $insert_result = $this->jobads_model->insert_from_draft($jobads_draft_id, $payment_data); 
    $this->_assert_true($insert_result); 

    //draft now must be empty 
    $this->_assert_false($this->jobads_draft_model->get_current_jobads_draft($user_id)); 

    } 
} 

,但注意不要與混淆。加載數據庫庫後,您可以在測試控制器內部執行$this->db。你可以把它放在自動加載,所以它會自動加載。

在我的代碼中看到,在測試運行之前,表格被截斷。運行後,我會收到可能發生的任何錯誤。我確定了一個預定義的插入和更新。使用Toast測試模型將確保模型的方法完成您想要完成的任務。進行所需的測試,並確保涵蓋輸入和輸出值的所有可能性。

+0

酷,但我想知道爲什麼你把所有這些測試在一個單一的測試功能?爲什麼不把它們放在單獨的函數中 - 我認爲如果assert語句失敗會更容易發生bug軌跡。 –

+0

在我上面的測試中,它反映了我的應用程序中的真實案例。這就是爲什麼在一次測試中有2個「行動」。即使你這樣做,如果一個失敗,那麼它會顯示,這是失敗的第一個或第二個動作。 你可以根據自己的需要製作任何你想要的東西。 –