Pytanie Jak organizować testy jednostkowe i nie czynić refaktoryzacji koszmarem?


Mój obecny sposób organizowania testów jednostkowych sprowadza się do:

  • Każdy projekt ma swój własny projekt z testami jednostkowymi. Dla projektu BusinessLayer, tam jest BusinessLayer.UnitTests projekt testowy.
  • Dla każdej klasy, którą chcę przetestować, istnieje osobna klasa testowa w projekcie testowym umieszczona w dokładnie tej samej strukturze folderów i dokładnie w tej samej przestrzeni nazw co testowana klasa. Dla klasy CustomerRepository z przestrzeni nazw BusinessLayer.Repositories, jest klasa testowa CustomerRepositoryTests w przestrzeni nazw BusinessLayerUnitTests.Repositories.

Metody w każdej klasie testowej są zgodne z prostą konwencją nazewnictwa MethodName_Condition_ExpectedOutcome. A więc klasa CustomerRepositoryTests zawiera testy dla klasy CustomerRepository z a Get zdefiniowana metoda wygląda następująco:

[TestFixture]
public class CustomerRepositoryTests
{
    [Test]
    public void Get_WhenX_ThenRecordIsReturned()
    {
        // ...
    }

    [Test]
    public void Get_WhenY_ThenExceptionIsThrown()
    {
        // ...
    }
}

To podejście dobrze mi służyło, ponieważ sprawia, że ​​testowanie lokalizacji dla jakiegoś fragmentu kodu jest naprawdę proste. Na przeciwległej stronie sprawia, że ​​refaktoryzacja kodu jest naprawdę trudniejsza niż powinna być:

  • Kiedy decyduję się podzielić jeden projekt na wiele mniejszych, muszę również podzielić mój projekt testowy.
  • Kiedy chcę zmienić przestrzeń nazw klasy, muszę pamiętać o zmianie przestrzeni nazw (i struktury folderów) również w klasie testowej.
  • Kiedy zmieniam nazwę metody, muszę przejść przez wszystkie testy i zmienić tam również nazwę. Oczywiście, mogę użyć funkcji Search & Replace, ale nie jest to zbyt niezawodne. Na koniec wciąż muszę sprawdzić zmiany ręcznie.

Czy istnieje jakiś sprytny sposób organizowania testów jednostkowych, które pozwolą mi szybko zlokalizować testy dla określonego kodu i jednocześnie nadają się bardziej do refaktoryzacji?

Czy jest jakieś rozszerzenie Visual Studio, które pozwoliłoby mi w jakiś sposób powiedzieć, że "hej, te testy są dla że metoda, więc kiedy zmieni się nazwa metody, proszę bądź tak miła i zmień również testy "? Szczerze mówiąc, poważnie rozważam napisanie czegoś takiego samemu :)


12
2017-07-20 18:41


pochodzenie


Jak nazywasz swoje metody testowe? Czy zawierają one nazwę metody, którą testujesz? - Ufuk Hacıoğulları
@ UfukHacıoğulları Tak, robią. W pytaniu podaję dokładną konwencję, której te nazwy dotyczą. - Nikola Anusev


Odpowiedzi:


Po wielu próbach, zdałem sobie sprawę, że (przynajmniej dla mnie) posiadanie tych wszystkich ograniczeń przynosi wiele problemów na dłuższą metę, a nie na dobre. Dlatego zamiast używać "Nazw" i konwencji, aby to ustalić, zaczęliśmy używać kodu. Każdy projekt i każda klasa może mieć dowolną liczbę projektów testowych i klas testowych. Cały kod testowy jest zorganizowany w oparciu o to, co jest testowane z perspektywy funkcjonalności (lub które wymagania implementuje, lub który błąd został odtworzony, itp.). Następnie, aby znaleźć testy dla kodu, robimy to:

[TestFixture]
public class MyFunctionalityTests
{
    public IEnumerable<Type> TestedClasses()
    {
        // We can find the tests for a class, because the test cases references in some special method.
        return new []{typeof(SomeTestedType), typeof(OtherTestedType)};
    }

    [Test]
    public void TestRequirement23423432()
    {
        // ... test code.
        this.TestingMethod(someObject.methodBeingTested); //We do something similar for methods if we want to track which methods are being tested (we usually don't)
        // ... 
    }
}

Możemy użyć takich narzędzi, jak "resursy" resharpera, aby znaleźć przypadki testowe, itd ... A kiedy to nie wystarcza, robimy magię przez odbicie i LINQ przez ładowanie wszystkich klas testowych i uruchamianie czegoś takiego allTestClasses.where(testClass => testClass.TestedClasses().FindSomeTestClasses()); Możesz również użyć TearDown, aby zebrać informacje o metodach testowanych przez każdą metodę / klasę i zrobić to samo.


4
2017-07-21 01:59



Dziękuję za przedstawienie ciekawych pomysłów dotyczących śledzenia metod. Nie jestem pewien, czy chcę porzucić wszystkie konwencje - prawdopodobnie spróbuję opracować narzędzie, które automatycznie synchronizuje projekty testowe z ich "prawdziwymi" odpowiednikami. - Nikola Anusev
To jak testowa baza danych! Lubię to! - Spencer Ruport


Jednym ze sposobów synchronizacji lokalizacji zajęć i testów podczas przenoszenia kodu:

  • Przenieś kod do jednoznacznie nazwanego tymczasowego obszaru nazw
  • Wyszukaj odniesienia do tej przestrzeni nazw w testach, aby zidentyfikować testy, które należy przenieść
  • Przenieś testy do właściwej nowej lokalizacji
  • Gdy wszystkie odniesienia do tymczasowej przestrzeni nazw z testów są we właściwym miejscu, przenieś oryginalny kod do zamierzonego celu

Jedną z siły testów end-to-end lub behawioralnych są testy pogrupowane według wymagań, a nie kodu, dzięki czemu unikasz problemu z synchronizacją lokalizacji testów z odpowiednim kodem.


1
2017-07-20 19:05





Jeśli chodzi o rozszerzenia VS, które wiążą kod z testami, przyjrzyj się wpływowi testu programu Visual Studio. Przeprowadza testy pod profilerem i tworzy kompaktową bazę danych, która mapuje punkty sekwencji IL na testy jednostkowe. Innymi słowy, po zmianie kodu Visual Studio wie, które testy należy uruchomić.


1
2017-07-22 02:16



Dzięki za to, na pewno się tym przyjrzę. - Nikola Anusev


Jeden testowy projekt jednostkowy na projekt jest drogą do zrobienia. Próbowaliśmy z projektem testowym mega-jednostki, ale to zwiększyło czas kompilacji.

Aby pomóc Ci refaktoryzować, użyj produktu podobnego do Resharper lub pośpiech kodu.


0
2017-07-20 18:53



Tak, używam już Resharpera, ale pomaga to tylko częściowo przy zmianie nazwy metod. Próbuje znaleźć miejsce w rozwiązaniu, w którym myśli, że metoda jest używana, ale wciąż jest wiele fałszywych trafień, szczególnie w przypadku popularnych nazw metod. Szukam czegoś bardziej automatycznego i mniej czasochłonnego. - Nikola Anusev
Resharper i VS mogą pomóc w zmianie nazw obszarów nazw, zobacz: stackoverflow.com/questions/3360320/... - Shiraz Bhaiji
Zgadza się. Ale w moim przypadku zmieniłaby tylko nazwę obszaru np. CustomerRepository i nie CustomerRepositoryTests, po co dokładnie jestem. - Nikola Anusev
Możesz utworzyć X nowe projekty testowe z poprawnymi nowymi nazwami, a następnie przenieść testy do odpowiedniego nowego projektu testowego. - Shiraz Bhaiji


Czy istnieje jakiś sprytny sposób organizowania testów jednostkowych, które wciąż będą   Pozwól mi szybko zlokalizować testy dla określonego kodu

Resharper ma kilka dobrych skrótów, które umożliwiają wyszukiwanie pliku lub kodu

Jak powiedziałeś dla klasy CustomerRepository, jest to test Testów CustomerRepository

R # skrót pokazuje pole inpput dla tego, co znajdziesz w tobie, możesz po prostu wpisać CRT i pokaże Ci wszystkie pliki zaczynające się od imienia najpierw jako C, potem R, a potem T

Umożliwia również wyszukiwanie za pomocą kart wieloznacznych, takich jak CR *, pokaże listę plików CustomerRepository i CustomerRepositoryTests


0
2017-07-20 18:57



Dzieki za sugestie. Jednak tak naprawdę nie widzę, jak mogłoby mi to pomóc w moich problemach; cytowane zdanie będzie kontynuowane a jednocześnie nadają się bardziej do refaktoryzacji? - i to jest rzecz, którą muszę rozwiązać :) - Nikola Anusev