2010-02-16 6 views
6

Sono nuovo ai test unitari, quindi questa è forse una domanda un po 'stupida. Immagina, abbiamo un semplice metodo di modello.Codeigniter Modelli di test unitari

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; 
} 

La domanda è come dovrebbe essere scritto un buon test? UPD: Suppongo che la migliore libreria di test unitari per CI sia Toast, quindi l'esempio che sto cercando è preferibile che sia scritto usando questo. Grazie.

risposta

10

Anche io sto usando il toast e per lo più lo uso per testare i metodi del modello. Per farlo, prima troncare tutti i valori della tabella, inserire un valore predefinito, quindi ottenerlo. Questo è l'esempio di prova ho usato nella mia domanda:

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)); 

    } 
} 

Sto utilizzando ADODB nella mia domanda, ma non farti confondere con quello. È possibile eseguire $this->db all'interno del controller di test, dopo aver caricato la libreria del database. Puoi metterlo in autoload in modo che venga caricato automaticamente.

Vedere che nel mio codice, prima dell'esecuzione del test, la tabella viene troncata. Dopo l'esecuzione, riceverò qualsiasi errore che potrebbe verificarsi. Asserisco per un inserto e un aggiornamento predefiniti. L'uso di Toast per testare il modello ti farà essere sicuro che il metodo del modello svolga esattamente il compito che vuoi che faccia. Fai il test che ti serve e assicurati di coprire tutte le possibilità dei valori di input e output.

+0

Fresco, ma mi chiedo perché si inseriscono tutti quei test all'interno di una singola funzione di test? Perché non inserirli in singole funzioni? Suppongo che renderebbe più semplice la traccia dei bug in caso di fallimento di una dichiarazione di asserzione? –

+0

Nel mio test di cui sopra, riflette il caso reale nella mia applicazione. Ecco perché ci sono 2 "azioni" in un test. Anche se lo fai, se uno fallisce, allora verrà visualizzato, che fallisce, la prima o la seconda azione. Puoi farlo come vuoi per adattarlo alle tue esigenze. –