2009-12-15 3 views
0

La fonction qui doit être testé est:C++ comment tester la fonction pour lui faire jeter une erreur?

int hire(Payroll * p) throw(out_of_range, logic_error) 
{ 

     // error if no holes left 

     if (staffcount == MAX_EMPLOYEES) 
        throw (out_of_range("Hire: Too many employees")); 

     // spin down holes looking for a hole. 
     for (int i = 0; i < MAX_EMPLOYEES; ++i) { 
      Payroll *current = staff[i].get(); // get the pointer 

      if (current == 0) { // it is empty 
       appay newpay(p); // convert *Payrollto auto_ptr 
       staff[i] =newpay; 
       staffcount++; // one more staff 
       return i;  // return index 
      } else { 
       // do nothing. Hole is filled 
      } 
     } 
     // should never get here 
     throw (logic_error("no holes, but count ok")); } 

Je suis en mesure de le tester en lançant une erreur out_of_range, mais je ne peux pas penser à tout logic_error.

Voici mon test dans le principal out_of_range:

try { 
    for (int i = 0; i<11; i++){ 
     hr.hire(new Payroll("Prog M. Er", 55757575)); 
     hr.showAllStaff(" after hires"); 
    } 
} catch (out_of_range e) { 
    cout << "Out of range error: " << e.what() << endl; 
    cout << "DEBUG: carry on processing - line 177 was tested\n"; 
} 

Toute aide sur la façon d'écrire un test logic_error pour cette fonction serait grandement apprécié! Merci.

A

+3

Les spécifications d'exception en C++ sont quelque peu brisées: http://www.gotw.ca/publications/mill22.htm –

+0

On dirait que vous définissez MAX_EMPLOYEES sur 2 et que vous essayez d'embaucher un 3e employé.Je ne pense pas que cela devrait être une erreur de logique, mais plutôt un débordement. –

+0

C'est vrai Thomas. Et je trouve difficile de trouver une erreur de logique pour cela. J'ai besoin de créer un test pour cette fonction où je lance des erreurs (des deux types). Dites-moi si vous pouvez penser à autre chose. Je vous remercie. Adri – Adri

Répondre

1

Vous n'avez pas vraiment besoin de l'optimisation au début. Si vous omettez cela alors vous n'avez qu'une seule exception à lancer, vous ne pouvez pas faire d'erreur de logique et vous n'avez aucun problème à la tester. Plus lent, oui, mais si vous lancez une exception de toute façon, je doute que cela fasse une différence. Cela donne aussi une fonction plus simple. Voici le code:

int hire(Payroll * p) throw (out_of_range) 
{ 
    // spin down holes looking for a hole. 
    for (int i = 0; i < MAX_EMPLOYEES; ++i) 
    { 
     Payroll *current = staff[i].get(); // get the pointer 

     if (current == 0) { // it is empty 
      appay newpay(p); // convert *Payrollto auto_ptr 
      staff[i] =newpay; 
      staffcount++; // one more staff 
      return i;  // return index 
     } else { 
      // do nothing. Hole is filled 
     } 
    } 

    // error if no holes left 
    throw (out_of_range("Hire: Too many employees")); 
} 
0

Il y a deux façons de penser à cette exception. L'un serait de muter MAX_EMPLOYEES après la comparaison à staff_count, mais avant que vous ayez fini d'exécuter la boucle for. Vous devriez avoir un autre thread à faire, et espérer qu'il fonctionne au bon moment.

Deux serait modifier le tableau hr.staff sans utiliser la méthode de location. Si vous remplissez le tableau de matrices avec les objets de paie MAX_EMPLOYEES et que vous appelez ensuite la méthode d'embauche, vous rencontrez cette exception. Vous voudrez probablement faire faire cela par une classe d'amis, car je suppose que le tableau du personnel est privé.

1

Il s'agit probablement d'un domaine dans lequel les pratiques de programmation diffèrent, mais je soulèverais une assertion plutôt que de lancer une exception ici.

Les assertions sont utilisées pour indiquer "ce qui ne devrait jamais arriver"; une erreur de programmation, pouvant entraîner une corruption interne des données, ou une violation grave des hypothèses sous lesquelles le code a été écrit.

Des exceptions sont généralement utilisées pour indiquer des erreurs d'exécution inattendues ou inhabituelles (manque d'espace disque, erreurs réseau inattendues, etc.). Si staffcount et staff ne sont pas synchronisés, cela indique une erreur de programmation et une corruption probable des données, et l'abandon du programme (avec une bonne trace d'erreur) peut être préférable à la poursuite de données corrompues.

C a intégré assert function, mais des alternatives sont disponibles, comme le léger Boost.Assert (que j'utilise) et le très complet de ce Alexandrescu et Torjo SMART_ASSERT library.

+0

Je dirais que ça dépend: pour les tests internes, une assertion est bien, parce que vous obtenez toute la pile pour comprendre le problème. Lorsque vous mettez un client devant votre application, vous voulez certainement quelque chose de mieux qu'un vidage de base! –

+0

+1 pour le lien de la bibliothèque SMART_ASSERT, ne le savaient pas et l'article est vraiment instructif (même un peu de supercherie!) –

+0

Voilà une raison pour utiliser quelque chose comme Boost.Assert ou SMART_ASSERT au lieu de l'intégré affirmer la fonction; vous pouvez conserver la logique du style assert, mais utiliser quelque chose de plus convivial qu'un core dump pour les versions de versions. –

0

La question ici est ce que vous devez vraiment tester. Je dirais que ce que vous devez tester est de savoir si le reste de votre système se comportera de manière acceptable une fois l'exception levée. Cela étant dit, vous pouvez temporairement remplacer cette fonction par une fonction qui lève simplement l'exception, assurez-vous qu'elle est gérée correctement par tout ce qui est supposé l'attraper, puis restaurez la fonction correcte.

Questions connexes