Pokazywanie postów oznaczonych etykietą Coded UI. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą Coded UI. Pokaż wszystkie posty

piątek, 16 grudnia 2011

Coded UI Tests - cz. 2

Podstawy Coded UI Test zostały omówione w poprzednim poście tego bloga tutaj, jednak warto rozwinąć ten temat i trochę usystematyzować wiedzę. W tym poście zakładam, że każdy wie jak stworzyć prosty test oraz czym jest Coded UI Test Builder. Zacznijmy od tego że aby nasze testy przechodziły musimy odpalić instancję testowanej aplikacji :). Możemy oczywiście robić to za każdym razem ręcznie, jednak jest to skrajnie beznadziejne rozwiązanie. Najlepiej przygotować sobie metodę, która będzie odpalać instancję naszej aplikacji jeżeli nie jest ona uruchomiona.

Ok przyjrzyjmy się strukturze plików i sposobowi budowania testów. Przede wszystkim do projektu testowego możemy dodać 2 obiekty. Pierwszy to "Coded UI Test" (CUIT) - czyli klasa opatrzona atrybutem [CodedUITest]. Jest to nasza właściwa klasa testowa. Tutaj właśnie tworzymy nasze testy. Drugi obiekt to klasa "Coded UI Test Map". Nie musimy jej dodawać ręcznie (poprzez Add->New Item...->Coded UI Test Map), bo zostanie ona stworzona automatycznie jeżeli wygenerujemy kod przy pomocy Coded UI Test Builder'a. Wszystkie wygenerowane przez nas akcje i asserty zapisywane są w takiej Mapie. Tworząc CUIT tak naprawde odwołujemy się do wygenerowanego kodu znajdującego się w mapie. W dużych aplikacjach modułowych powinniśmy używać wielu map, gdzie każda reprezentuje inny moduł.
Dla każdej wygenerowanej metody tworzona jest klasa, której instancja przechowuje wartości oczekiwane lub wprowadzane przez użytkownika. Dzięki temu mamy możliwość manipulacji warunkami dla każdej akcji. Instancja każdej z takich klas wystawiona jest jako właściwość w obiekcie naszej mapy.

Jak pisać testy? Jest to bardzo dobre pytanie. Przede wszystkim każdy CUIT opiera się na metodach które wygenerujemy. Każda wygenerowana metoda to akcja którą nagraliśmy za pomocą Coded UI Test Builder. Czyli powinniśmy nagrywać możliwie krótkie akcje, dzięki czemu możemy później kombinować je ze sobą tworząc wiele testów opartych na pojedyńczych akcjach. Wówczas jeżeli zmieni się coś w interfejsie użytkownika np zwykły button zostanie zastąpiony przez kontrolke innego typu, wówczas nie musimy nagrywać ponownie wszystkich testów które korzystały z danego buttona. Wystarczy wygenerować od nowa metode "WcisnijButton" i ewentualnie zmienić jej nazwę na inną (co jest standardową czynnością, którą można błyskawicznie wykonać). Mówiąc bardziej ogólnie: Nie powinno się utożsamiać CUIT z nagraną akcją dostępną w UIMap. CUIT powinien składać się z wielu uniwersalnych akcji nagranych przez użytkownika. Takimi pojedynczymi akcjami mogą być:
-kliknięcie przycisku
-sprawdzenie że kontrolka przyjęła odpowiedni stan
-wprowadzenie textu do TextBoxa
itd.

Ok przykład. Mamy aplikacje napisaną w WPF. Nie wnikamy w jej sens. użytkownik ma do dyspozycji 2 TextBox'y oraz TextBlock. W TextBlock'u wyświetlamy złączone napisy wprowadzone do TextBoxów. Kod aplikacji wygląda mniej więcej tak:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox Name="TextBox1"/>
<TextBox Name="TextBox2"/>
<TextBlock Name="TextBlock">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}{1}">
<Binding Path="Text" ElementName="TextBox1"/>
<Binding Path="Text" ElementName="TextBox2"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</Window>

Chcemy przetestować czy TextBlock rzeczywiście wyświetla złączone napisy z TextBoxów. Tworzymy zatem klasę testową. Następnie generujemy akcje wpisywania tekstu do TextBox1 oraz akcje wpisywania textu do TextBox2. Tworzymy metodę (assert), która porównuje czy w TextBocku jest wpisany "CustomText". Ok czyli w rezultacie mamy 3 metody. Wpisany text do textboxów został przez nas skonkretyzowany podczas nagrywania akcji (dla przykładu można przyjąć że jest to "Custom Text"). Możemy teraz przetestować czy napis w TextBlock jest prawidłowy. Musimy podmienić text który jest testowany. Można to zrobić za pomocą klas parametrów tworzonych automatycznie podczas generowania kodu.
[TestMethod]
public void CodedUITestMethod1()
{
// Arrange
Just.EnterTextIntoTextBox1Params.UITextBox1EditText = "Coded";
Just.EnterTextIntoTextBox2Params.UITextBox2EditText = "UI";
Just.VerifyTextBlockTextExpectedValues.UITextBlockTextDisplayText = "CodedUI";
// Act
Just.EnterTextIntoTextBox1();
Just.EnterTextIntoTextBox2();
// Assert
Just.VerifyTextBlockText();
}

W powyższym przykładzie zmieniłem domyślną nazwę UIMap na Just.
Teraz wyobraźmy sobie że chcemy zrobić testy seryjne. Mamy np całą tabelę z danymi i chcielibyśmy ją "wstrzyknąć" do naszego testu razem z wynikami. Nic prostrzego. W tym wypadku możemy zastosowac dokładnie ten sam mechanizm, który znamy z Unit Testów czyli DataSource.
Najpierw musimy dodać do klasy testowej CUIT właściwość TestContext:
private TestContext testContextInstance;
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}

Instancja klasy TestContext zostanie stworzona automatycznie po uruchomieniu naszych testów, dlatego bez problemu możemy się odwoływac do tej właściwości w naszych metodach testowych.
Aby stworzyć testy seryjne musimy dodać atrybut DataSource do naszej metody testowej. Atrybut ten wskazuje źródło danych, które są dostępne za pomocą właściwości TestContext. Teraz nasz test wykona się dla wszystkich wartości jakie znajdują się w naszym źródle danych. Plik z danymi podpinamy do projektu testowego. Klikamy na niego PPM wybieramy właściwości i ustawiamy "Build Action" na "Content" oraz "Copy to Output Directory" na "Copy if newer".
Plik "Data.csv"
Input1,Input2,ExpectedResult
a,b,ab
one,two,onetwo
, ,

kod:
[DeploymentItem("Tests\\Data.csv"),
DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV","|DataDirectory|\\Data.csv", "Data#csv",DataAccessMethod.Sequential),
TestMethod]
public void CodedUITestMethod1()
{
// Arrange
Just.EnterTextIntoTextBox1Params.UITextBox1EditText = TestContext.DataRow["Input1"].ToString();
Just.EnterTextIntoTextBox2Params.UITextBox2EditText = TestContext.DataRow["Input2"].ToString();
Just.VerifyTextBlockTextExpectedValues.UITextBlockTextDisplayText = TestContext.DataRow["ExpectedResult"].ToString();
// Act
Just.EnterTextIntoTextBox1();
Just.EnterTextIntoTextBox2();
// Assert
Just.VerifyTextBlockText();
}

niedziela, 4 grudnia 2011

Coded UI Test - tworzenie testów UI przy pomocy Visual Studio Ultimate

Poszukując sposobów automatycznego testowania aplikacji natrafiłem na ciekawą funkcjonalność Visual Studio 2010 Ultimate. Mianowicie w tej wersji naszego ulubionego IDE znalazło się miejsce na nowy typ testów - Coded UI Test. Coded UI Test jest to automatyczny test UI, który tworzymy poprzez nagrywanie akcji jakie wykonujemy w naszej aplikacji. Nie musimy pisać ani jednej linijki kodu żeby przetestować jakąś funkcjonalność naszego programu. Jedyne co musimy zrobić jest to przejście przez wszystkie niezbędne kroki w naszej aplikacji, tak aby zweryfikować naszą funkcjonalność. W celu stworzenia Coded UI Test musimy po pierwsze zaopatrzyć się w wersję Ultimate Visual Studio 2010. Z tego co wiem, niestety niższe wersje nie mają funkcjonalności automatycznego testowania. Następnie musimy stworzyć nowy Test Project. W tym celu z menu File wybieramy New a następnie Project. W oknie, które się pokaże, w drzewie po lewej stronie wybieramy Test, a następnie w prawej części okna Test Project
.
Mając stworzony projekt testowy dodajemy do niego nowy Coded UI Test. W Solution Explore-rze klikamy PPM na projekt testowy, a następnie z menu contextowego wybieramy Coded UI Test.
. W oknie, które się pojawi wybieramy Record actions,edit UI map or add assertion lub gdy mamy już gotowe testy możemy wybrać opcję nr 2. Po wybraniu pierwszej opcji okno Visual Studio zostanie zminimalizowane, a w prawym dolnym rogu pulpitu ukaże się następujące okienko.
. Służy ono do nagrywania testu. Naciskając czerwony przycisk rozpoczynamy proces nagrywania testu. W moim przypadku będę testować aplikację, którą testowałem również w poprzednim poście. Wykonuje zatem czynności mające na celu sprawdzenie funkcjonalności dodawania liczb. Po kliknięciu na textbox-a pojawia się nad nim dymek,że dana akcja jest nagrywana.

Po "wyklikaniu" całej ścieżki mającej sprawdzić funkcjonalność klikamy przycisk "Generate code"" (ten najbardziej z prawej strony). Następnie w okienku, które się pojawi

podajemy nazwę naszego testu. Po kliknięciu OK, Visual Studio wygeneruje nam kod odpowiedzialny za nasz test.

W celu odpalenia naszego testu z menu Test wybieramy Run, a następnie Tests in Current Context. Visual Studio przejdzie teraz wszystkie kroki, które zostały nagrane w teście. Ok, niby wszystko ładnie pięknie, ale tak naprawdę nic nie sprawdziliśmy. Jedyne co zrobiliśmy to wykonaliśmy pewne operacje na naszej aplikacji, jednakże nie zweryfikowaliśmy danych otrzymanych w wyniku operacji dodaj. W celu dodania warunku sprawdzającego do naszego testu, musimy dodać tzw. asercję. Aby to zrobić klikamy PPM na wolne pole edytora, pod funkcją this.UIMap.RecordedMethod1() (ta funkcja została wygenerowana podczas nagrywania testu). Następnie z menu contextowego wybieramy

Otwiera nam się znane już wcześniej okienko nagrywania testu. Jednakże tym razem naciśnijmy przycisk celownika i przeciągnijmy go na textbox-a, w którym ma pojawić się wynik dodawania

Nasz textbox zostanie obramowany, natomiast w prawym dolnym rogu pulpitu pojawi się nowe okno pokazujące propertisy naszego przycisku. Wybierzmy właściwość Text ,a następnie naciśnijmy przycisk Add Assertion

W oknie, które się pojawi możemy wybrać warunek, który musi spełnić dana właściwość (w tym przypadku Text), aby test przeszedł. Ustawmy tam wartość np. 3. Następnie klikamy OK oraz nadajemy nazwę naszej assercji.Po wykonaniu tych czynności w kodzie naszego pojawi się dodatkowa linijka

Teraz za każdym razem gdy odpalimy test na samym jego końcu będzie sprawdzana nasza assercja. W przypadku gdy wartość właściwości Text nie będzie równa 3 nasz test nie przejdzie.

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Online Project management