[JAVA] L'idée de tests corrects, dédiés aux projets où les tests ne fonctionnent pas

Qui est la cible de cet article

introduction

J'avais beaucoup de connaissances sur les méthodes de conception et la mise en œuvre des tests, mais ce que je ne savais pas, c'était l'idée de tester.

Kobito.Rq2LN5.png

Je pense que beaucoup de gens savent que les tests semblent être importants. Cependant, je pense que certaines personnes n'ont pas réellement réalisé les avantages. En fait, il y a ceux qui disent que *** les tests sont importants *** et ceux qui savent que *** les tests semblent être importants ***. Cette dernière personne peut passer un test pour le moment. Cependant, je pense que malgré le temps passé sur les tests, je compte souvent sur la recherche de bogues dans les tests manuels à la fin.

Écrire un test est monnaie courante dans le monde et le test est important! Pourquoi ne pouvons-nous pas réaliser que les tests sont importants? ?? Comment faire un projet qui utilise efficacement les tests?

Dans cet article, comment pensez-vous de tels problèmes dans la pratique plutôt que de manière délicate? Je voudrais expliquer le circuit de la pensée.

Par exemple, considérons le cas suivant.

Étude de cas

class SampleController
  def index
    # do something
  end
end

Dans cette action, 10 méthodes A, B, C, D, E, F, G, H, I, J sont appelées, chacune retournant (0, 1), et il y a 1024 comportements différents. Faire.

Ici, il y a un rapport selon lequel il ne se comporte pas normalement dans les situations suivantes.

Rapport 1

A -> 0 
B -> 1 
C -> null
D -> 1 
E -> 1 
F -> 1 
G -> 0 
H -> 0 
I -> 0 
J -> - 2

Rapport 2

A -> 0 
B -> 1 
C -> 0 
D -> 1 
E -> 1 
F -> 1 
G -> 0 
H -> 0 
I -> 0 
J -> 1

Quels tests aurais-je dû faire pour éviter que le bogue ne se reproduise? ??

Ici, dans un projet où seuls les tests unitaires sont écrits, il peut être possible d'éviter le bogue dans le rapport 1, mais il peut être difficile d'éviter le bogue dans le rapport 2. Quel type de cas de test dois-je écrire en fonction de ce cas? Je voudrais expliquer cela.

supposition

Quel est le but du test en premier lieu, plutôt que d'entrer soudainement dans la méthodologie? Quel est le test idéal? Quels sont les problèmes avec le test idéal? Je voudrais unifier l'interprétation à cet égard.

Objectif du test

Le but du test est

  1. Recherche d'un bug
  2. Garantie de la qualité
  3. Amélioration de la qualité

Il est dit que. L'objectif le plus important est *** 1. Trouver des bogues ***. Donc, pour mettre les choses à l'extrême, une application sans bogue est idéale, et les tests sont l'un des meilleurs moyens de se rapprocher de cet idéal.

Que dois-je faire pour éviter les bogues?

Je pense qu'il peut être divisé en trois domaines: les spécifications, la conception du programme et les tests. Si les spécifications et la conception du programme sont mauvaises, le test sera difficile. Refactorisez donc votre code spaghetti avant de tester. Mais cette fois, il s'agit de tests.

Kobito.V11The.png

Quel est le test idéal?

Alors, quel est le test idéal? C'est un test qui prouve que *** tous les cas d'utilisation fonctionnent correctement ***.

En d'autres termes, si vous avez 100 utilisations différentes, vous pouvez parfaitement trouver le bogue en testant si les 100 réponses sont correctes. Je vais expliquer en utilisant le cas précédent.

Étude de cas

class SampleController
  def index
    # do something
  end
end

Dans cette action, 10 méthodes A, B, C, D, E, F, G, H, I, J sont appelées et il y a 1024 cas d'utilisation. Supposons également que chaque méthode renvoie (0, 1).

Ici, j'ai reçu un rapport indiquant qu'un bogue s'est produit dans les situations suivantes.

A -> 0 
B -> 1 
C -> 0 
D -> 1 
E -> 1 
F -> 1 
G -> 0 
H -> 0 
I -> 0 
J -> 1

Réponse (position idéale)

Tout d'abord, je ne sais pas si la combinaison est à l'origine du bogue ou si la méthode unique est à l'origine du bogue. Cependant, cette fois, je vais ignorer une telle situation et considérer le cas de test à partir d'une position idéale.

Dans une position idéale, vérifiez que toutes les combinaisons sont normales. En d'autres termes, 2 ^ 10 = 1024 tests vous aideront à trouver parfaitement le bogue.

Problèmes dans une position idéale

Une fonction avec 1024 cas d'utilisation est un monstre, mais en réalité, il est impossible de tester des centaines de fonctions pour une action (fonction) d'une application normale. De plus, lorsque plusieurs actions (fonctions) sont combinées, un nombre infini de cas de test sera nécessaire. Le problème ici est que tester tous les cas d'utilisation demande beaucoup de travail. (Bien sûr)

Méthode de conception d'essai pratique

Plus vous visez le test idéal, plus vous ferez de travail de manière exponentielle. Donc dans le monde des tests logiciels *** Comment pouvez-vous rédiger un test rentable? *** *** Cela devient une proposition.

Alors, comment rédigez-vous un test rentable? C'est *** écrire des tests solides pour le code bogué ***. Pour le dire autrement, *** éliminez les conditions moins importantes du test idéal ***. Maintenant, je vais expliquer trois façons de passer du cas de test idéal à un niveau réaliste.

--Méthode 1: éclaircir les éléments indépendants --Méthode 2: ne pas tester les motifs moins importants --Méthode 3: affiner les combinaisons basées sur des informations statistiques --Résumé

Méthode 1: éclaircir les éléments indépendants

Cette technique est l'idée la plus élémentaire qui rend les tests réalistes.

Étude de cas

class SampleController
  def index
    # do something
  end
end

Dans cette action, 10 méthodes A, B, C, D, E, F, G, H, I, J sont appelées et il y a 1024 cas d'utilisation. Supposons également que chaque méthode renvoie (0, 1).

Proposition 1:Si "1024 cas d'utilisation sont tous normaux", alors "10 méthodes sont toutes normales"
Proposition 2:Si "10 méthodes sont toutes normales", alors "1024 cas d'utilisation sont tous normaux"

La proposition 1 et la proposition 2 sont-elles respectivement vraies ou fausses?

Répondre

La proposition 1 est "vraie" et la proposition 2 est "fausse". (Il semble que vous puissiez écrire un programme qui est vrai même dans ce dernier en utilisant un langage fonctionnel)

Le premier nécessite 2 ^ 10 = 1024 tests, Ce dernier nécessite 2 * 10 = 20 tests.

Ces propositions prouvent que *** les tests unitaires seuls ne suffisent pas pour trouver un bogue ***. Cependant, en réalité, un éclaircissage peut être suffisant.

Par exemple, si les méthodes D et H sont complètement indépendantes (n'affecte pas les autres méthodes) sur les 10 méthodes, il peut même être prouvé que D et H renvoient 0 ou 1. Il n'y a aucun problème si vous le faites. De plus, E et F ont également des portées d'influence étroites, et on peut estimer qu'ils ne sont pas nécessaires pour les tests de combinaison.

Autrement dit, l'indice de cas d'utilisation est réduit de 10 à 6 et le test unitaire est augmenté de 4. 2 ^ 6 + 2 * 4 = 70 voies

De cette manière, nous éclaircirons les combinaisons indépendantes.

point

Pour les méthodes indépendantes, un test unitaire est suffisant et est soustrait de l'exposant de la combinaison.

Méthode 2: ne pas tester les motifs moins importants

Cela ne peut pas être déterminé théoriquement. Au cas par cas, le simple fait de connaître l'idée maintiendra l'erreur dans une plage acceptable.

Étude de cas

class SampleController
  def index
    # do something
  end
end

Dans cette action, 10 méthodes A, B, C, D, E, F, G, H, I, J sont appelées et il y a 1024 cas d'utilisation.

De plus, la méthode A est la fonction d'authentification fournie par la bibliothèque. 1 pour l'authentification Renvoie 0 pour la non-authentification. La méthode F renvoie les valeurs «rouge», «vert» et change la couleur du bouton. La méthode H renvoie l'objet Plan A et l'objet Plan B à partir des informations saisies par l'utilisateur.

Il devrait y avoir une hiérarchie de cas à tester et de cas autorisés sans test. Alors, comment devez-vous prioriser vos tests? ??

Répondre

Le jugement est basé sur la matrice de (importance) x (risque de contamination par des insectes).

L'importance a des facteurs tels que l'importance pour l'utilisateur et un large éventail d'influence. De par sa conception, le risque de bogues est plus élevé dans les endroits où le code source est plus complexe. (Lieux avec un haut degré de liaison) Le risque de contamination par des bogues peut être déterminé quantitativement dans une certaine mesure en effectuant une analyse métrique. (Je parlerai de l'analyse métrique plus tard)

Donc, dans ce cas, A est fourni par une bibliothèque de confiance et le risque de bogues est faible. F La plage d'influence est étroite et n'est pas si importante pour les utilisateurs. H est la valeur de l'application elle-même et la logique est compliquée. En d'autres termes

Kobito.DXuYmk.png

Avec une telle matrice, il peut être déterminé que A n'a pas besoin d'être testé unitaire et que F n'a pas besoin d'être dans le modèle de combinaison.

point

Compte tenu de (importance) × (risque de contamination par des bugs), diluez les parties qui n'ont pas besoin d'être incluses dans le code et le modèle de combinaison qui ne nécessitent pas de test unitaire.

Méthode 3: restreindre les combinaisons en fonction des informations statistiques

Quels types de cas de test devraient être éclaircis jusqu'à présent? J'ai appris l'idée de base. Cependant, avec la puissance humaine, même des dizaines de cas de test sont stricts pour une fonction. Alors, quand les ingénieurs de test peuvent-ils avoir des bogues? J'en ai fait des informations statistiques. Ensuite, les problèmes qui surviennent entre les paramètres *** 2 représentent 70 à 90%. Le résultat statistique de *** est apparu. Une méthode de conception de test basée sur ces données est appelée la *** méthode par paires ***.

Étude de cas

class SampleController
  def index
    # do something
  end
end

Dans cette action, trois méthodes A, B, C et D sont appelées et il existe huit cas d'utilisation.

La méthode par paires est la suivante.

L'une des techniques de test de combinaison, la méthode toutes paires (par paires), crée une mire de test qui couvre au moins la combinaison de valeurs entre deux paramètres pour tous les paramètres.

Méthode toutes paires (par paire)

Est écrit.

En d'autres termes, ce n'est pas grave si toutes les combinaisons des deux méthodes sont couvertes. Par exemple, si vous considérez un cas de test utilisant la méthode par paires pour les méthodes A, B, C et D, ce sera comme suit.

A       B       C       D
1       0       0       0
1       1       1       1
0       1       0       1
0       0       1       1
0       1       1       0

Il semble qu'il existe un outil pour créer des paires, vous pouvez donc essayer de l'utiliser.

Outil de génération de cas de test combiné "PictMaster" et thème des tests de logiciels

Résumé

Méthode 1, trouvez un modèle indépendant. Méthode 2, pensez à la matrice si vous devriez vraiment tester. Méthode 3, réduire judicieusement le nombre de combinaisons basées sur des informations statistiques.

Je pense que ce serait une combinaison réaliste.

Bonnes connaissances à connaître lors de la rédaction de tests en pratique

Avec ce qui précède, j'ai acquis l'idée de base. Cependant, les cas jusqu'à présent sont des études de cas basées sur un modèle qui a été idéalisé dans une certaine mesure. Dans les cas précédents, la combinaison était très claire. Cependant, dans le code de champ, le nombre de combinaisons varie d'une personne à l'autre. De plus, quel type de code se cache chez certaines personnes? Il y aura des variations dans l'interprétation.

Cependant, lors du développement dans un projet, nous voulons avoir une compréhension commune autant que possible. Par conséquent, je voudrais expliquer les connaissances sur les éléments suivants. (Ignorez les éléments que vous connaissez.)

Le taux de couverture est une méthode de comptage des combinaisons d'itinéraire. Le fractionnement égal et l'analyse des valeurs limites sont des méthodes d'extraction de modèles de valeurs. L'analyse des métriques est une méthode de mesure quantitative du type de code présentant un bogue.

En les connaissant, il y aura une certaine variation dans la sélection des combinaisons et la priorité entre les projets.

Quel est le taux de couverture?

Un index qui montre combien les branches du programme sont couvertes. Il existe des niveaux de couverture C0, C1 et C2.

Prenons un exemple de ce code.

def my_method
  if type1 == "A"
    print("Processus 1")
  else
    print("Processus 2")
  end

  if type == "B"
    print("Processus 3")
  end
end

C0: Couverture de l'instruction

Au niveau C0, il est déterminé si les instructions sont couvertes. En d'autres termes, il n'y a pas de problème si vous passez le processus 1 au processus 3 une fois.

def my_method
  if type1 == "A"
    print("Processus 1")
  else
    print("Processus 2")
  end

  if type == "B"
    print("Processus 3")
  end
end

On peut dire que le cas de test a un taux de couverture de niveau C0 de 100% dans les deux cas suivants.

type == "A" TRUE,  type == "B" TRUE
type == "A" FALSE, type == "B" TRUE

C1: Couverture des succursales

Au niveau C1, déterminez si la branche est exhaustive. En d'autres termes, vous pouvez parcourir toutes les branches une fois.

def my_method
  if type1 == "A"
    print("Processus 1")
  else
    print("Processus 2")
  end

  if type == "B"
    print("Processus 3")
  end
end

On peut dire que les quatre cas de test suivants ont un taux de couverture de niveau C1 de 100%. 2 + 2 = 4 voies

type == "A" TRUE,  type == "B" TRUE
type == "A" FALSE, type == "B" TRUE
type == "A" TRUE,  type == "B" FALSE
type == "A" FALSE, type == "B" FALSE

C2: Couverture des conditions

Au niveau C2, déterminez si toutes les combinaisons de succursales sont couvertes. C'est difficile car c'est assez proche du test idéal.

def my_method
  if type1 == "A"
    print("Processus 1")
  else
    print("Processus 2")
  end

  if type == "B"
    print("Processus 3")
  end
end

Il y a quatre cas de test ci-dessous, mais en réalité, le nombre de cas de test continue d'augmenter de façon exponentielle à mesure que les conditions augmentent. 2 * 2 = 4 voies

type == "A" TRUE  && type == "B" TRUE
type == "A" FALSE && type == "B" TRUE
type == "A" TRUE  && type == "B" FALSE
type == "A" FALSE && type == "B" FALSE

Analyse de la division égale et de la valeur limite

D'ailleurs, on sait que les combinaisons sont comptées en fonction du nombre de branches conditionnelles. Cependant, il existe encore une autre combinaison de variables. C'est la plage de valeurs qui peut être prise. (Plage de valeurs)

Étude de cas

Considérez la stratégie de test de code suivante.


#Les valeurs possibles pour var sont String, Int,Un de rien
def my_method(var)
  var.your_method
end

Pour la couverture, une seule fois suffit. Cependant, il ne suffit pas de considérer uniquement le taux de couverture. Dans ce cas, vous voudrez au moins tester les cas String, Int et nill.

*** Si la couverture est une couverture d'itinéraire, cette fois, c'est une couverture de valeur. *** *** Cependant, la couverture des valeurs est infinie. (Nombres naturels seuls) Alors, comment le couvrez-vous? ??

Partage égal

Comme d'habitude, je laisserai l'explication à d'autres articles faciles à comprendre.

Qu'est-ce que l'égalité partagée?

Analyse de la valeur limite

Comme son nom l'indique, il s'agit de tester les valeurs limites.

Qu'est-ce que l'analyse métrique?

Il analyse statiquement le logiciel et évalue quantitativement la qualité sous différents angles. En connaissant cette idée, *** Quel type de code source a de nombreux bogues? Vous pouvez voir que *** dans une certaine mesure. Je mettrai un lien de référence ci-dessous pour une explication détaillée, mais je n'expliquerai que l'index appelé complexité circulaire.

Qu'est-ce que la complexité circulaire?

Une façon de montrer la complexité en comptant le nombre de chemins dans le code source. Cependant, cet article est extrêmement facile à comprendre, alors jetez un œil.

\ C'est un bug! / Quel est le confort et la complexité cyclomatique du point de vue de M. Bug, qui nidifie dans le système? \ C'est un bug! /

Lien de référence

Qu'est-ce que l'analyse métrique? Ruby on Rails | Analyse métrique avec metric_fu À quoi sert l'outil d'analyse de code statique MetricFu

Outil d'analyse métrique pour chaque langue First Software Metrics (Part 1): Quantify and Confirm Software Quality

À lire lorsque vous souhaitez choisir une méthode de sélection de cas de test.

[Lire «Tests logiciels tirés de zéro connaissance» [Des tests de la boîte blanche aux tests exploratoires]](http://qiita.com/shinofumijp@github/items/6121105c608fc0cf11d4#%E5%90%8C%E5%80 % A4% E5% 88% 86% E5% 89% B2% E6% B3% 95% E3% 81% A8% E5% A2% 83% E7% 95% 8C% E5% 88% 86% E6% 9E% 90 % E6% B3% 95)

Q&A

J'ai beaucoup écrit. Cependant, il est difficile pour tous les membres du projet de maintenir la qualité du test. Par conséquent, j'aimerais écrire les problèmes qui ont été soulevés jusqu'à présent dans un format de questions et réponses.

Question 1: Comment utiliser correctement le test unitaire et le test E2E?

L'idéal est de tester unitaire le comportement de toutes les fonctions et méthodes. Toutes leurs combinaisons doivent être testées avec le test E2E. Mais en réalité, c'est difficile. Par conséquent, les fonctions et méthodes de faible complexité ne sont pas testées unitaire. Les combinaisons indépendantes sont éclaircies à partir du cas de test. Conception de test basée sur l'idée.

Mis à jour de temps en temps

Recommended Posts

L'idée de tests corrects, dédiés aux projets où les tests ne fonctionnent pas
Comment utiliser l'apprentissage automatique pour le travail? 01_ Comprendre l'objectif de l'apprentissage automatique
J'ai essayé de résumer la manière logique de penser l'orientation objet.
J'ai essayé d'automatiser le travail de masquage du visage de l'image de coordination pour l'usure
Le moyen le plus rapide pour les débutants de maîtriser Python
Excel X Python La technique de travail la plus rapide
Un moyen simple de vérifier la source des modules Python
Au point où le céleri de Python et RabbitMQ (Docker) fonctionnent