Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Dans les tests unitaires traditionnels, un test se compose de plusieurs éléments :
- Séquence d’appels de méthode
- Arguments avec lesquels les méthodes sont appelées ; les arguments sont les entrées de test
- Validation du comportement prévu de l’application testée en indiquant un ensemble d’assertions
Voici un exemple de structure de test :
[Test]
void MyTest() {
// data
ArrayList a = new ArrayList();
// method sequence
a.Add(5);
// assertions
Assert.IsTrue(a.Count==1);
Assert.AreEqual(a[0], 5);
}
IntelliTest peut souvent déterminer automatiquement les valeurs d’argument pertinentes pour des tests unitaires paramétrables plus généraux, qui fournissent la séquence d’appels de méthode et d’assertions.
Générateurs de test
IntelliTest génère des cas de test en sélectionnant une séquence de méthodes de l’implémentation sous test à exécuter, puis en générant des entrées pour les méthodes lors de la vérification des assertions sur les données dérivées.
Un test unitaire paramétrable indique directement une séquence d’appels de méthode dans son corps.
Lorsque IntelliTest doit construire des objets, les appels aux constructeurs et aux méthodes de fabrique sont ajoutés automatiquement à la séquence en fonction des besoins.
Tests unitaires paramétrables
Les tests unitaires paramétrables (PUT) sont des tests qui prennent des paramètres. Contrairement aux tests unitaires traditionnels, qui sont généralement des méthodes fermées, les PUT prennent n’importe quel ensemble de paramètres. C’est simple ? Oui : à partir de là, IntelliTest tente de générer l’ensemble (minimal) d’entrées qui couvrent entièrement le code accessible à partir du test.
Les PUT sont définis à l’aide de l’attribut personnalisé PexMethod de la même manière que MSTest (ou NUnit, xUnit). Les PUT sont des méthodes d’instance regroupées logiquement dans des classes marquées avec PexClass. L’exemple suivant montre un PUT simple stocké dans la classe MyPexTest :
[PexMethod]
void ReplaceFirstChar(string target, char c) {
string result = StringHelper.ReplaceFirstChar(target, c);
Assert.AreEqual(result[0], c);
}
où ReplaceFirstChar est une méthode qui remplace le premier caractère d’une chaîne :
class StringHelper {
static string ReplaceFirstChar(string target, char c) {
if (target == null) throw new ArgumentNullException();
if (target.Length == 0) throw new ArgumentOutOfRangeException();
return c + target.Substring(1);
}
}
À partir de ce test, IntelliTest peut générer automatiquement des entrées pour un PUT qui couvre de nombreux chemins d’exécution du code testé. Chaque entrée qui couvre un chemin d’exécution différent est sérialisée en test unitaire.
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
void ReplaceFirstChar0() {
this.ReplaceFirstChar(null, 0);
}
...
[TestMethod]
void ReplaceFirstChar10() {
this.ReplaceFirstChar("a", 'c');
}
Tests unitaires paramétrables génériques
Les tests unitaires paramétrables peuvent être des méthodes génériques. Dans ce cas, l’utilisateur doit spécifier les types utilisés pour instancier la méthode à l’aide de PexGenericArguments.
[PexClass]
public partial class ListTest {
[PexMethod]
[PexGenericArguments(typeof(int))]
[PexGenericArguments(typeof(object))]
public void AddItem<T>(List<T> list, T value)
{ ... }
}
Autorisation d’exceptions
IntelliTest fournit de nombreux attributs de validation pour aider à trier les exceptions en exceptions attendues et les exceptions inattendues.
Les exceptions attendues génèrent des cas de test négatifs avec l’annotation appropriée telle que ExpectedException(typeof(xxx)), tandis que les exceptions inattendues génèrent des cas de test défaillants.
[PexMethod, PexAllowedException(typeof(ArgumentNullException))]
void SomeTest() {...}
Les validateurs sont les suivants :
- PexAllowedException : autorise un type d’exception particulier n’importe où
- PexAllowedExceptionFromAssembly : autorise un type d’exception particulier d’un assembly spécifié
- PexAllowedExceptionFromType : autorise un type d’exception particulier à partir d’un type spécifié
- PexAllowedExceptionFromTypeUnderTest : autorise un type d’exception particulier du type sous test
Test des types internes
IntelliTest peut « tester » les types internes, tant qu’il peut les voir. Pour qu’IntelliTest affiche les types, l’attribut suivant est ajouté à votre projet de produit ou de test par les Assistants Visual Studio IntelliTest :
[assembly: InternalsVisibleTo("Microsoft.Pex, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
Hypothèses et assertions
Les utilisateurs peuvent utiliser des hypothèses et des assertions pour exprimer des conditions préalables (hypothèses) et postconditions (assertions) sur leurs tests. Lorsque IntelliTest génère un ensemble de valeurs de paramètre et « explore » le code, il peut violer une hypothèse du test. Lorsque cela se produit, il ne génère pas de test pour ce chemin d’accès, mais l’ignore silencieusement.
Les assertions sont un concept bien connu dans les frameworks de test unitaire standard. IntelliTest « comprend » déjà les classes Assert intégrées fournies par chaque infrastructure de test prise en charge. Toutefois, la plupart des frameworks ne fournissent pas de classe Assume . Dans ce cas, IntelliTest fournit la classe PexAssume . Si vous ne souhaitez pas utiliser une infrastructure de test existante, IntelliTest possède également la classe PexAssert .
[PexMethod]
public void Test1(object o) {
// precondition: o should not be null
PexAssume.IsNotNull(o);
...
}
En particulier, l’hypothèse de non-nullness peut être encodée en tant qu’attribut personnalisé :
[PexMethod]
public void Test2([PexAssumeNotNull] object o)
// precondition: o should not be null
{
...
}
Condition préalable
Une condition préalable d’une méthode exprime les conditions dans lesquelles la méthode réussira.
En règle générale, la condition préalable est appliquée en vérifiant les paramètres et l’état de l’objet, et lève une exception ArgumentException ou InvalidOperationException si elle est violée.
Dans IntelliTest, une condition préalable d’un test unitaire paramétrable est exprimée avec PexAssume.
Postcondition
Une postcondition d’une méthode exprime les conditions qui doivent être conservées pendant et après l’exécution de la méthode, en supposant que ses conditions préalables étaient initialement valides.
En règle générale, la postcondition est appliquée par les appels aux méthodes Assert .
Avec IntelliTest, une postcondition d’un test unitaire paramétrable est exprimée avec PexAssert.
Échecs des tests
Quand un cas de test généré échoue-t-il ?
S’il ne se termine pas dans les limites de chemin configurées, il est considéré comme un échec, sauf si l’option TestExcludePathBoundsExceededed est définie
Si le test lève une exception PexAssumeFailedException, il réussit. Toutefois, il est généralement filtré sauf si TestEmissionFilter a la valeur All
Si le test enfreint une assertion ; par exemple, en lançant une exception de violation d’assertion dans un cadre de test unitaire, il échoue
Si aucune des versions ci-dessus ne produit une décision, un test réussit si et seulement s’il ne lève pas d’exception. Les violations d’assertion sont traitées de la même façon que les exceptions.
Configuration et démontage
Dans le cadre de l’intégration à des frameworks de test, IntelliTest prend en charge la détection et l’exécution des méthodes d’installation et de destruction.
Exemple
using Microsoft.Pex.Framework;
using NUnit.Framework;
namespace MyTests
{
[PexClass]
[TestFixture]
public partial class MyTestClass
{
[SetUp]
public void Init()
{
// monitored
}
[PexMethod]
public void MyTest(int i)
{
}
[TearDown]
public void Dispose()
{
// monitored
}
}
}
Lectures complémentaires
Vous avez des commentaires ?
Publiez vos idées et demandes de fonctionnalités sur la Communauté des développeurs.