W trzecim już poście dotyczącym zakamarków Visual Studio, czyli mało znanych funkcji tego środowiska programistycznego, chciałbym napisać o oknie
Object Test Bench. Okno to pozwala na szybkie testowanie wywołań metod statycznych i instancyjnych bez potrzeby pisania małych programików testowych. Jeśli po uruchomieniu środowiska nie jest widoczne możemy je wyświetlić wybierając
View->Other Widnows->Object Test Bench. Aby wygodnie pracować z tym oknem przyda się również okno
Class View (
View->Class View), które służy do przeglądania typów zdefiniowanych w naszych projektach oraz w innych pakietach/podzespołach (ang.
assembly), do których się odwołujemy. Ważna uwaga! Widok
Object Test Bench może zostać użyty tylko i wyłącznie do testowania klas w projekcie oznaczonym jako
StartUp oraz w pakietach, do których ten projekt się odwołuje. Co prawda zgodnie z dokumentacją powinniśmy móc testować wszystkie klasy w bieżącym rozwiązaniu (ang.
solution) ale niestety nie jest to możliwe.
Dalej będę posługiwał się prościutką, a wręcz naiwną klasą zdefiniowaną poniżej, w celu omówienia zastosowania okna
Object Test Bench.
public class Person
{
private static int count = 0;
private string name;
private DateTime dateOfBirth;
public string Name
{
get { return name; }
set { name = value; }
}
public DateTime DateOfBirth
{
get { return dateOfBirth; }
set { dateOfBirth = value; }
}
public Person()
{
Person.count++;
}
public Person(string name, DateTime dateOfBirth)
: this()
{
this.name = name;
this.dateOfBirth = dateOfBirth;
}
public int GetAge(bool inDays)
{
if(!inDays)
return DateTime.Now.Year - dateOfBirth.Year;
else
return (DateTime.Now - dateOfBirth).Days ;
}
public static int GetCount()
{
return Person.count;
}
}
Aby rozpocząć testowanie jakiejś klasy musimy zlokalizować ją w oknie
Class View i wywołać dla niej menu kontekstowe.
W menu kontekstowym powinny być widoczne dwie komendy:
- Create Instance - Pozwala wywołać dowolny konstruktor dla danego typu i przypisać mu identyfikator. Stworzony obiekt pojawi się w oknie Object Test Bench. Dla stworzonych obiektów możemy następnie wywoływać metody instancyjne. W ten sposób nie powołamy do życia instancji klasy abstrakcyjnej czy też delegata.
- Invoke Static Mehtod - Pozwala wywołać wybraną metodę statyczną danej klasy (również klasy abstrakcyjnej).
Polecenia te będą widoczne tylko dla klas z projektu głównego. Oczywiście przed wywołaniem metody statycznej, instancyjnej czy też konstruktora powinniśmy w interesujących nas miejscach w kodzie ustawić
breakpointy.
Zacznijmy od wywołania metody statycznej. Po najechaniu w menu kontekstowym na polecenie
Invoke Static Mehtod wyświetlone zostaną wszystkie metody statyczne dostępne w tej klasie. Należy wybrać jedną z nich. W przypadku naszej klasy testowej
Person możemy wybierać pomiędzy
GetCount() oraz dwie metodami odziedziczonymi po klasie
Object:
Equals(object, object) oraz
ReferenceEquals(object, object). Po wybraniu
GetCount() pojawi się okno potwierdzające chęć wywołania tej metody. Natomiast w przypadku metod, które posiadają parametry pojawi się okno pozwalające na wyspecyfikowanie wartości tych parametrów. Kiedy klikniemy
Ok metoda zostanie wywołana. Na zakończenie pojawi się okno z wynikiem, które powinno wyglądać jak poniżej:
Istnieje również możliwość zapisania wyniku wywołania metody. W tym celu powinniśmy zaznaczyć opcję
Save return value (w oknie pokazanym powyżej) i nadać identyfikator dla zwracanego obiektu/struktury. Jeśli zdecydujemy się na zapisanie wyniku pojawi się on w oknie
Object Test Bench:
Stworzone obiekty reprezentowane są w oknie
Object Test Bench przez prostokąty. Dla każdego obiektu możemy wywołać menu kontekstowe, które pozwoli nam wybrać metodę instancyjną do wywołania. Spróbujmy wykonać metodę posiadającą parametry np.:
CompareTo(int). Po jej wybraniu powinniśmy zobaczyć okno jak poniżej:
Warto zauważyć, że jeżeli metoda opatrzona była komentarze to zostanie on przytoczony. Po podaniu wartości parametru aktualnego i wybraniu przycisku
Ok, metoda zostanie wywołana, a wynik zostanie przedstawiony w takim samym oknie jak przy wywoływaniu metody statycznej (jego też możemy zapisać).
Przyjrzyjmy się teraz poleceniu
Create Instance i stwórzmy instancję klasy
Person korzystając z konstruktora dwuargumentowego. Po wybraniu konstruktora powinno pojawić się okno przedstawionej dalej:
Po pierwsze powinniśmy podać nazwę dla tworzonego obiektu. W tym miejscu trzeba uważać bo jeśli podanym nazwę, której już użyliśmy zostaniemy o tym poinformowani dopiero po naciśnięciu przycisku
Ok, a nie ma możliwości cofnięcia się i naprawienia błędu.
Po drugie, podobnie jak przy wywoływaniu metod, należy podać wartości poszczególnych argumentów. Napiszę o tym troszeczkę więcej. Jeśli chodzi o typy proste nie ma co się rozpisywać. Po prostu wpisujemy liczbę lub ciąg znaków (zamknięty w cudzysłowy) i koniec. Troszeczkę trudniej jest z typami złożonymi. Na rysunku widać, że dla parametru
dateOfBirth wstawiłem dziwną wartość
dateTime1. Niestety ale w przypadku typów złożonych musimy najpierw stworzyć instancję danego typu, a dopiero potem powołując się na przypisaną danej instancji nazwę, użyć jej jako argumentu wywołania. Nazwa stworzonej instancji pojawi się na rozwijanej liście dla argumentów o odpowiednim typie.
W tym przypadku stworzyłem uprzednio strukturę typu
DateTime i nadałem jej nazwę
dateTime1. Zacząłem od zlokalizowania typu struktury w drzewie (najwygodniej posłużyć się przyciskiem
Search u góry okna
Class View). Następnie wybrałem polecenie
Create Instance, dalej zdecydowałem się na konstruktor trójargumentowy, jako argumenty wywołania podając rok, miesiąc i dzień mojego urodzenia (wszystkie wartości to typy proste). Na koniec powróciłem do klasy
Person i ponownie wybrałem interesujący mnie konstruktor. Jak widać tworzenie obiektów wymagających skomplikowanej inicjalizacji jest trudne i kłopotliwe ale te okno nie do tego służy.
Po stworzeniu instancji klasy
Person możemy przystąpić do testowania jej metod, a właściwie jednej metody. Odbywa się to dokładnie w ten sam sposób jak opisałem na przykładzie metody
CompareTo(int). Polecam spróbować wywołać metodę
GetAge(bool) z parametrem
true oraz
false oraz sprawdzić jaki wynik zwraca metoda statyczna
GetCount() po utworzeniu instancji klasy
Person.
Jeszcze dwie uwagi na koniec. Jeśli wprowadzimy jakieś zmiany do kodu to okno
Object Test Bench wymusi na nas ponowną kompilację źródeł. Równoznaczne jest to z utratą wszystkich obiektów, struktur, które umieściliśmy wcześniej w tym oknie.
W drugiej części tej serii postów pisałem o oknie
Immediate. W ciekawy sposób współpracuje ono z oknem
Object Test Bench. Dla przypomnienia w oknie
Immediate również możemy wywoływać metody i tworzyć obiekty. Istotne jest to, że obiekty, które stworzymy w tym oknie pojawią się również w oknie
Object Test Bench. Tutaj też obowiązuje warunek, żeby użyty typ pochodził z projektu oznaczonego jako
StartUp lub z pakietu/podzespołu, do którego tej projekt się odwołuje. Kolejny warunek jaki musimy spełnić (wygląda to na błąd w Visual Studio) jest taki, że okno
Object Test Bench nie może być puste w momencie tworzenia obiektu w oknie
Immediate. Jeśli będzie tworzone obiekty nie zostaną do niego dodane. Co ciekawe jeśli w pewnym momencie dodamy jakiś obiekt do okna
Object Test Bench (z poziomu okna
Class View) to nagle pojawią się w nim również obiekty utworzone wcześniej w oknie
Immediate.
Warto jeszcze dodać, że obiekty z okna
Immediate w oknie
Object Test Bench będą miały takie same identyfikatory jak zmienne użyta w oknie
Immediate. Czyli wpisanie takiej komendy:
Person person = new Person();
spowoduje dodanie do okna
Object Test Bench obiektu o nazwie
person
Opisane techniki testowałem w środowiskach Visual Studio 2005 oraz Visual Studio 2008.