Udostępnij przez


Generowanie testów

W tradycyjnych testach jednostkowych test składa się z kilku elementów:

Poniżej przedstawiono przykładową strukturę testu:

[Test]
void MyTest() {
    // data
    ArrayList a = new ArrayList();

    // method sequence
    a.Add(5);

    // assertions
    Assert.IsTrue(a.Count==1);
    Assert.AreEqual(a[0], 5);
}

Narzędzie IntelliTest może często automatycznie określać odpowiednie wartości argumentów dla bardziej ogólnych sparametryzowanych testów jednostkowych, które zapewniają sekwencję wywołań metod i asercji.

Generatory testów

Narzędzie IntelliTest generuje przypadki testowe, wybierając sekwencję metod implementacji do wykonania, a następnie generując dane wejściowe dla metod podczas sprawdzania asercji na podstawie danych pochodnych.

Sparametryzowany test jednostkowy bezpośrednio określa sekwencję wywołań metod w jej treści.

Gdy narzędzie IntelliTest musi konstruować obiekty, wywołania konstruktorów i metod fabrycznych zostaną automatycznie dodane do sekwencji zgodnie z potrzebami.

Sparametryzowane testowanie jednostkowe

Sparametryzowane testy jednostkowe to testy, które przyjmują parametry. W przeciwieństwie do tradycyjnych testów jednostkowych, które są zwykle zamkniętymi metodami, puts przyjmują dowolny zestaw parametrów. Czy to proste? Tak — z tego miejsca narzędzie IntelliTest spróbuje wygenerować (minimalny) zestaw danych wejściowych , które w pełni obejmują kod osiągalny z testu.

PUT-y są definiowane za pomocą niestandardowego atrybutu PexMethod w podobny sposób jak MSTest (lub NUnit, xUnit). PuTs to metody wystąpień grupowane logicznie w klasach oznaczonych PexClass. W poniższym przykładzie pokazano prostą operację PUT przechowywaną w klasie MyPexTest.

[PexMethod]
void ReplaceFirstChar(string target, char c) {

    string result = StringHelper.ReplaceFirstChar(target, c);

    Assert.AreEqual(result[0], c);
}

gdzie ReplaceFirstChar to metoda, która zastępuje pierwszy znak ciągu:

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

W tym teście narzędzie IntelliTest może automatycznie generować wejścia dla PUT, który pokrywa wiele ścieżek wykonania testowanego kodu. Każde dane wejściowe obejmujące inną ścieżkę wykonywania jest "serializowane" jako test jednostkowy:

[TestMethod, ExpectedException(typeof(ArgumentNullException))]
void ReplaceFirstChar0() {
    this.ReplaceFirstChar(null, 0);
}
...
[TestMethod]
void ReplaceFirstChar10() {
    this.ReplaceFirstChar("a", 'c');
}

Ogólne sparametryzowane testowanie jednostkowe

Sparametryzowane testy jednostkowe mogą być metodami ogólnymi. W takim przypadku użytkownik musi określić typy używane do instancjonowania metody przy użyciu PexGenericArguments.

[PexClass]
public partial class ListTest {
    [PexMethod]
    [PexGenericArguments(typeof(int))]
    [PexGenericArguments(typeof(object))]
    public void AddItem<T>(List<T> list, T value)
    { ... }
}

Zezwalanie na wyjątki

Funkcja IntelliTest udostępnia wiele atrybutów weryfikacji, które ułatwiają klasyfikację wyjątków w oczekiwanych wyjątkach i nieoczekiwanych wyjątkach.

Oczekiwane wyjątki generują negatywne przypadki testowe z odpowiednią adnotacją, taką jak ExpectedException(typeof(xxx))), podczas gdy nieoczekiwane wyjątki generują przypadki testowe zakończone niepowodzeniem.

[PexMethod, PexAllowedException(typeof(ArgumentNullException))]
void SomeTest() {...}

Moduły sprawdzania poprawności to:

Testowanie typów wewnętrznych

Narzędzie IntelliTest może "testować" typy wewnętrzne, o ile może je zobaczyć. Aby narzędzie IntelliTest mogło wyświetlać typy, następujący atrybut jest dodawany do projektu produktu lub testowego przez kreatory IntelliTest programu Visual Studio.

[assembly: InternalsVisibleTo("Microsoft.Pex, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]

Założenia i asercji

Użytkownicy mogą używać założeń i asercji do wyrażania warunków wstępnych (założeń) i pokondycji (asercji) dotyczących ich testów. Gdy narzędzie IntelliTest generuje zestaw wartości parametrów i "eksploruje" kod, może to naruszać założenie testu. W takim przypadku nie wygeneruje testu dla tej ścieżki, ale w trybie dyskretnym go zignoruje.

Asercje to dobrze znana koncepcja w standardowych ramach testów jednostkowych, więc narzędzie IntelliTest już "rozumie" wbudowane klasy Assert udostępniane przez każdą obsługiwaną ramę testową. Jednak większość struktur nie udostępnia klasy Przyjmij . W takim przypadku intelliTest udostępnia klasę PexAssume . Jeśli nie chcesz używać istniejącej platformy testowej, narzędzie IntelliTest ma również klasę PexAssert .

[PexMethod]
public void Test1(object o) {
    // precondition: o should not be null
    PexAssume.IsNotNull(o);

    ...
}

W szczególności założenie o wartości innej niż null może być zakodowane jako atrybut niestandardowy:

[PexMethod]
public void Test2([PexAssumeNotNull] object o)
// precondition: o should not be null
{
   ...
}

Warunek wstępny

Warunek wstępny metody wyraża warunki, w których metoda powiedzie się.

Zazwyczaj warunek wstępny jest wymuszany przez sprawdzenie parametrów i stanu obiektu oraz zgłoszenie wyjątku ArgumentException lub InvalidOperationException , jeśli zostanie naruszone.

W środowisku IntelliTest warunek wstępny sparametryzowanego testu jednostkowego jest wyrażany za pomocą narzędzia PexAssume.

Postwarunek

Postkondycja metody wyraża warunki, które powinny być spełnione podczas i po wykonaniu metody, przy założeniu, że jej warunki wstępne były początkowo prawidłowe.

Zwykle postwarunek jest wymuszany za pomocą wywołań metod Assert.

Dzięki funkcji IntelliTest postwarunek sparametryzowanego testu jednostkowego jest wyrażany za pomocą PexAssert.

Niepowodzenia testów

Kiedy wygenerowany przypadek testowy kończy się niepowodzeniem?

  1. Jeśli nie zakończy się on w ramach skonfigurowanych granic ścieżki, jest uważany za błąd, chyba że ustawiono opcję TestExcludePathBoundsExceeded

  2. Jeśli test zgłosi wyjątek PexAssumeFailedException, powiedzie się. Jednak zwykle jest on filtrowany, chyba że TestEmissionFilter jest ustawiony na All

  3. Jeśli test narusza asercję; na przykład przez zgłoszenie wyjątku naruszenia asercji w frameworku testów jednostkowych, zostaje uznany za nieudany.

Jeśli żadne z powyższych przypadków nie prowadzi do podjęcia decyzji, test zakończy się powodzeniem, jeśli i tylko wtedy, gdy nie zgłosi wyjątku. Naruszenia asercji są traktowane tak samo jak wyjątki.

Konfigurowanie i usuwanie

W ramach integracji z platformami testowymi narzędzie IntelliTest obsługuje wykrywanie i uruchamianie metod instalacji i usuwania.

Przykład

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

Dalsze informacje

Masz opinię?

Opublikuj swoje pomysły i prośby dotyczące funkcji w społeczności deweloperów.