2013-08-15 16 views
5

Próbuję dokładniej śledzić praktykę "jednego stwierdzenia na jednostkę testu". Nie zawsze jest to możliwe, ale uważam, że jest to przydatne do wskazywania błędów.Czy istnieje atrybut pozwalający uniknąć kaskadowych testów jednostkowych w MSTest?

Na przykład może mam coś takiego:

var toTest; 

[TestInitialize] 
Init() { 
    toTest = // Create toTest 
} 

[TestMethod] 
TestIsCreated() { 
    Assert.IsNotNull(toTest); 
} 

[TestMethod] 
TestIsProperty1Setup() { 
    Assert.IsNotNull(toTest.Property1); 
    // Maybe some more tests on Property1 
} 

// More tests for other properties... 

Problemem jest to, czy tworzenie toTest były na niepowodzenie, a następnie wszystkich innych testów jednostkowych fail też. Tak więc możemy dodać trochę czeku w ten sposób:

... 

[TestMethod] 
TestIsProperty1Setup() { 
    if (toTest == null) Assert.Inconclusive() 
    Assert.IsNotNull(toTest.Property1); 
    // Maybe some more tests on Property1 
} 

... 

Spowoduje to zatrzymanie awarii kaskady i wskaże dokładny problem. Jeśli linia // Create toTest zwróci wartość zerową, to otrzymam dokładnie jeden test jednostkowy, a także kilka nierozstrzygających testów. Kiedy naprawię jeden test, to wszystko inne przechodzi.

Są dwa miejsca, w których to spada. Jednym z nich jest fakt, że teraz powtarzam kod na początku prawie wszystkich testów jednostkowych.

Drugim problemem jest to, kiedy chcesz ustawić i sprawdzić bardziej złożony obiekt (w tym manekina przykład toTest ma również tablicę):

[TestMethod] 
TestArrayIsNotNull() { 
    if (toTest == null) Assert.Inconclusive(); 
    Assert.IsNotNull(toTest.Array); 
} 

[TestMethod] 
TestArrayIsInitilizedWithOneElement() { 
    if (toTest == null) Assert.Inconclusive(); 
    if (toTest.Array == null) Assert.Inconclusive(); 
    Assert.AreEqual(1, toTest.Array.Count()) 
} 

[TestMethod] 
TestArrayIsInitilizedWithCorrectElement() { 
    if (toTest == null) Assert.Inconclusive(); 
    if (toTest.Array == null) Assert.Inconclusive(); 
    if (toTest.Array.Count() != 1) Assert.Inconclusive(); 
    // Assert something about toTest.Array[0] 
} 

Teraz jest więcej duplikat kodu dla każdego testu, oraz ważniejsze jest, że Assery muszą być zsynchronizowane między różnymi testami, co oznacza, że ​​jedna mała zmiana może przebiegać w wielu testach jednostkowych.

Idealnie chciałbym mieć atrybut, który znajduje się na górze każdego testu i uruchamia test tylko wtedy, gdy zdadzą "wstępne" testy. Może to wyglądać mniej więcej tak:

[TestMethod] 
[OnlyRunIfOtherTestPasses(TestIsCreated())] 
TestArrayIsNotNull() { 
    Assert.IsNotNull(toTest.Array); 
} 

[TestMethod] 
[OnlyRunIfOtherTestPasses(TestArrayIsNotNull())] 
TestArrayIsInitilizedWithOneElement() { 
    Assert.AreEqual(1, toTest.Array.Count()) 
} 

[TestMethod] 
[OnlyRunIfOtherTestPasses(TestArrayIsInitilizedWithOneElement())] 
TestArrayIsInitilizedWithCorrectElement() { 
    // Assert something about toTest.Array[0] 
} 

Testy jednostkowe są teraz bardzo proste - nie ma powielanie i prowadzenie testów zsynchronizowane z ich „warunków” jest teraz automatyczne.

Czy jest coś takiego? Czy istnieje zupełnie inna funkcja, której mogę użyć, aby uzyskać ten sam efekt?

Jestem świadomy, że prawie na pewno występują problemy z odwołaniem się do metody testowej w atrybucie do innej metody testowej - prawdopodobnie musiałbyś użyć łańcucha, który jest zakodowany na sztywno do nazwy metody (więc co się stanie, jeśli metoda zmiana nazwy lub metoda nie istnieje). Jestem pewien, że istnieją potencjalne problemy z odwołaniami cyklicznymi. Ale mimo wszystkich tych problemów ktoś musiał rozwiązać ten problem. Czy ktoś może mi to wskazać?

+1

IMHO masz zbyt dużo logiki w swoich testach jednostkowych. Powinny być zwięzłe i nie zawierać dużej logiki. Nie powinny także polegać na innych testach. Myślę, że musisz ponownie przemyśleć swoje podejście. – Belogix

+0

Kiedy mówisz "przemyśleć swoje podejście", masz na myśli ponowne przemyślenie sposobu, w jaki napisane są testy jednostkowe (nie powinienem sprawdzać, czy test jest zawsze pusty) lub ponownie przemyśleć zależności badanej klasy (test nie powinien mieć tablica, którą należy skonfigurować)? – Jonny

+0

Duplikat: http://stackoverflow.com/questions/15871933/how-to-stop-mstest-tests-execution-on-first-failure – BartoszKP

Odpowiedz

0

Zależność między testami jest odradzana. Możliwe rozwiązanie twojego problemu: jeśli rzucisz wyjątek, jeśli tworzenie "toTestu" nie powiedzie się (lub użyjesz zwykłego Assert) w metodzie inicjalizacji testu, to sądzę, że testy z grupy nie będą w ogóle działać. Można również użyć inicjalizacji klasy statycznej (http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.classinitializeattribute.aspx). Jednak wszystkie testy będą nadal oznaczone jako nieudane.

+0

Jeśli wyrzucę wyjątek w metodzie TestInitialize, wszystkie testy jednostkowe zakończą się niepowodzeniem.Dążę do tego, by dokładnie jeden test jednostkowy zakończył się niepowodzeniem, jeśli tworzenie nie zadziała, aby bardzo łatwo było zlokalizować problem. – Jonny

Powiązane problemy