Wprowadzenie do projektu QualitySpy

Transkrypt

Wprowadzenie do projektu QualitySpy
Wprowadzenie do projektu
QualitySpy
Na podstawie instrukcji implementacji prostej funkcjonalności.
1. Wstęp
Celem tego poradnika jest wprowadzić programistę do projektu QualitySpy.
Będziemy implementować krok po kroku prostą funkcjonalność związaną z serwisem GitHub.
W trakcie tłumaczenia będę komentował i opisywał strukturę projektu.
Dla uproszczenia będę pomijał początek nazwy pakietu pl.wroc.pwr.qualityspy i będę
odnosił się do tylko ostatniego członu.
2. Co będzie implementowane
Zaimplementujemy funkcjonalność wyświetlającą liczbę repozytoriów które posiada dany
użytkownik na GitHubie i liczbę obserwujących dla każdego z repozytoriów.
Instrukcja została oparta o przykładowe użycie biblioteki do obsługi API Githuba:
https://github.com/eclipse/egit-github/tree/master/org.eclipse.egit.github.core
3. Rewizja
Przykład jest tworzony w oparciu o najnowszą rewizję na dzień 28.06.2015. Jest to rewizja
numer 185.
4. Nowe pole konfiguracyjne
W tym punkcje zajmiemy się dodaniem nowego pola do plików konfiguracyjnych.
Przejdźmy do pakietu common
BugtrackerProperties
z
modułu
common
i
wybierzmy
interfejs
Interfejsy XXXProperties wraz z klasą Properties definiują strukturę pliku
konfiguracyjnego. Interfejsy opisują jakie dane można pobrać z konfiguracji, natomiast klasa
dodatkowo opisuje jak te dane są zapisywane w pliku (mówiąc dokładniej definiuje nazwę
klucz. Konfiguracja jest zapisywana w postaci klucz – wartość).
Dodajmy zatem metodę o definicji public
getGithubExampleUser.
String
getXXX(); np. o nazwie
Zapisanie zmian w tym pliku powinno od razu skutkować wyświetleniem błędu w klasie
Properties. Przejdźmy zatem do tej klasy.
Jako że klasa implementuje interfejsy XXXProperties, musimy zaimplementować dodaną
właśnie metodę.
Jeśli spojrzymy na strukturę klasy zauważymy, że metody występują trójkami: getXXX(),
setXXX(String value) i getXXXKey(). Pierwsza i druga kolejno pobiera i zapisuje
wartość korzystając z metod getProperty(String key) i setProperty(String key,
String value), trzecia metoda zwraca wartość klucza dla wybranej opcji konfiguracji (jak
wcześniej wspomniałem dane zapisywane są w postaci klucz – wartość).
Dodajmy zatem trójkę takich metod:
Zdefiniujmy metodę public String getGithubExampleUser() która zwraca tekst
„exampleUser”.
Następnie zdefiniujmy metody getGithubExampleUser i setGithubExampleUser tak
jak jest to opisane w komentarzu powyżej i posiłkując się przykładami z innych pól
konfiguracyjnych np. z pola JiraPassword.
Następnie musimy to pole konfiguracyjne obsłużyć przez interfejs graficzny. W tym celu
przejdźmy do klasy ConfigJPanel z pakietu gui w modue gui.
Rysunek 1 ConfigJPanel
Ta klasa zawiera całą implementacje funcjonalności związaną z obsługą pól edycyjnych ich
edycją i walidacją. Sam zapis wywoływany jest w klasie MenuJPanel, która wywołuje metodę
saveChangesOfComponent klasy ConfigJPanel, która iteruje po wierszach tabeli
widocznej na powyższym zrzucie ekranu, dzięki czemu dodanie do niej nowego wiersza z opcją
konfiguracyjną spowoduje już zapisywanie tej opcji do pliku.
Odnajdźmy metodę addRowJiraToConfigTable, metoda ta powoduje dodanie wierszy do
tabeli edycyjnej po wybraniu zakładki Jira.
Zakładka Jira obsługuje zarówno pobieranie danych z IssueTrackera Jiry jak i Githuba poprzez
odpowiedni wybór opcji bugtracker.
Metoda ta zawiera szereg wywołań metody addRowToConfigTable, która jako argumenty
przyjmują klucz i wartość pola konfiguracyjnego. Wykorzystajmy zatem wcześniej stworzone
metody getGithubExampleUserKey i getGithubExampleUser.
Dodajmy zatem nowe wywołanie wyżej wspomnianej metody.
Zbudujmy cały projekt i uruchommy go zgodnie z instrukcją przekazaną prze prowadzących
zajęcia. (Niepoprawne uruchomienie np. poprzez wybranie Run ze środowiska
programistycznego spowoduje nie pojawienie się i/lub błędne pojawienie się przykładowych
konfiguracji)
Wybierzmy jedną z przykładowych konfiguracji TestGitHub/1.0.
Na zakładce Jira powinno pojawić się nowe pole konfiguracyjne:
Rysunek 2 GUI z nowym polem
Wprowadźmy przykładową wartość np. defunkt i naciśnijmy przycisk ENTER lub przejdźmy
do innego pola konfiguracyjnego. Tylko w ten sposób zapiszemy zmiany w polu.
Następnie wybierzmy ikonę Dyskietki.
Konfiguracja jest za każdym razem czytana z pliku, dlatego niezbędne jest wcześniejsze
zapisanie konfiguracji przed uruchomieniem funkcjonalności związanej ze ściąganiem danych.
Przejdźmy do folderu config/TestGitHub/1.0 i otwórzmy w edytorze tekstu plik
qs.properties.
Rysunek 3 Ścieżka do pliku qs.properties
Rysunek 4 Plik qs.properties
5. Implementacja przykładowej funkcjonalności
Nasza przykładowa funkcjonalność
wykorzystującym GitHuba.
jest
związana
z
komponentem
bugtracker
Funkcjonalność ściągająca zagadnienia dla wybranego repozytorium już jest
zaimplementowana, jest tam obsłużone tworzenie klienta dla githuba i serwisu repozytoriów,
dlatego właśnie tam małym kosztem dołożymy naszą przykładową funkcjonalnośc.
Dla tych co nie zaglądali do przykładów biblioteki z linku w rozdziale Co będzie
implementowane:
Rysunek 5 Przykładowe użycie Github klienta
Rozpocznijmy implementacje. Przejdźmy do modułu bugtracker
bugtracker.github wybierzmy klasę GithubConnector.
i
z
pakietu
Moduły odpowiedzialne za ściąganie danych takie jak: bugtracker, metrics, version-control, ci
zawierają klasy XXXConnector. Są to klasy których zadaniem jest zainicjowanie właściwego
klienta z daną usługą np. bugtracker serwisu Github, połączenie z usługą Jenkins itp. i
wystawienie metod pozwalających na pobranie danych z tych usług. Dane te muszą zostać
także odpowiednio przekonwertowane na model który jest zapisywany w bazie danych.Dla
przykładu GithubConnector w metodzie init tworzy połączenie z serwisem Github za
pomocą klasy GithubClient, która pochodzi z zewnętrznej biblioteki. Konfiguruje to
połączenie a następnie udostępnia metodę getIssuesWithFullDescription, która z
kolei pobiera zagadnienia z githuba także za pomocą funkcjo z biblioteki
service.getIssues(repository,
issueFilter); a następnie wykorzystuje
odpowiedni
konwerter
do
konwersji
na
format
modelu
parser.convertGithubIssueToIssueDescription(issue).
Dodajmy zatem do tej klasy pole przechowujące listę Repozytoriów wybranego użytkownika:
private List<Repository> repos;
A następnie w metodzie init po zainicjowaniu klienta Githuba i serwisu repozytoriów
wykonajmy metodę z Rysunku: Przykładowe użycie Github klienta:
repositoryService.getRepositories(String user)
A skąd pobrać usera? Zauważmy, że do konstruktora GithubConnectora podawany jest
obiekt klasy Properties, dokładnie tej klasy którą modyfikowaliśmy w poprzednim
rozdziale, dzięki czemu mamy dostęp do metody getGithubExampleUser().
Przed wywołaniem sprawdźmy tylko czy przekazane pole nie jest puste.
Rysunek 6 Kod po modyfikacjach
Doskonale. Po tych modyfikacjach po utworzeniu GithubConnectora zostaje pobrana lista
repozytoriów. Utwórzmy teraz metodę, która będzie wyświetlała odpowiednie informacje.
Utwórzmy metodę o definicji: public void showWatchersList(); Metoda nie zwraca
nic, ponieważ wykorzystamy klasę ErrorWindow przeznaczoną do wyświetlania błędów w
GUI.
Przeitreujmy po repozytoriach z listy repos i dla każdego z nich odczytajmy wartość zwracaną
przez metodę getWatchers(). Dane pod postacią nazwa repozytorium – liczba wrzućmy do
pojedynczego Stringa. W tym celu polecam użyć klasy StringBuilder, która jest klasą
przeznaczoną właśnie do wielokrotnego sklejania łańcucha tekstowego. Można także na
potrzeby ćwiczenia wykorzystać po prostu operator +, jednak zalecam zapoznać się z w/w
klasą.
Klasa ErrorWindow jest klasą typu Singleton. Aby uzyskać instancję klasy Singleton
posłużymy się metodą statyczną ErrorWindows.getInstance().
Następnie aby wykorzystać ErrorWindow wykorzystamy metodę handleError. Ta metoda
przyjmuje dwa argumenty typu Exception i typu Errors.
Klasa Errors jest klasą zdefiniowaną w module common, tak jak i sama klasa ErrorWindow w
pakiecie errorHandling. Klasa ta jest klasą abstrakcyjną i służy do implementacji
zachowania przycisków TryAgain i EndProcess.
Klasa ErrorWindow służy do wyświetlania komunikatu wyjątku, dlatego musimy opakować
nasz tekst w jakiś wyjątek, dlatego posłużymy się wywołaniem new
Exception(watchersList).
Jeśli chodzi o drugi argument, należy przekazać nową instancję klasy Errors z pustą
implementacją jej metod.
Rysunek 7 Użycie ErrorWindow
W tym momencie implementacja samej przykładowej funkcjonalności jest gotowa. Pozostaje
nam tylko wywołanie.
6. Wywołanie nowej funkcjonalności
Wróćmy do modułu gui, tym razem jednak do pakietu integration.
W tym pakiecie znajdują się klasy FetchXXXThread. Te klasy poza klasą FetchDataThread,
która ma inne znaczenie w metodzie fetcherRun implementuje to co się dzieje po wybraniu
jednego z przycisków Fetch w GUI. Wspomniana klasa FetchDataThread to klasa która
opakowuje klasy FetchXXXThread w odpowiedni wątek i obsługę błędów.
Otwórzmy klasę FetchJiraThread. Jak wcześniej wspomniałem funkcjonalność ściągania
zagadnień z bugtrackera Jira i Github są połączone ze sobą.
W metodzie fetcherRun przejdźmy do warunku gdzie wykryte zostało że pole
konfiguracyjne bugtracker ma wartość „github”. Zauważmy że tworzony jest
GithubConnector na referencji klasy bazowej IBugTrackerConnector. Pamiętajmy że
stworzona funkcjonalność pozwala nam wyciągnąć dane za pomocą metody, dodanej
wyłącznie do klasy GithubConnector. Musimy zatem obsłużyć tę funkcjonalność w tym
warunku.
Na początku zrzutujmy referencję issueConnector na referencję klasy GithubConnector,
a następnie wywołajmy metodę showWatchersList();, ponownie pod warunkiem, że
pole githubExampleUser nie jest puste.
Rysunek 8 Kod po modyfikacjach.
Ponownie zbudujmy projekt i uruchommy według instrukcji podanej na zajęciach. Wybierzmy
konfigurację TestGitHub/1.0.
Przejdźmy na zakładkę Jira i wprowadźmy exampleUser: „defunkt”. Pamiętajmy że musimy
nacisnąć ENTER lub wyjść z pola edycyjnego, a następnie nacisnąć ikonę zapisu.
Wybierzmy przycisk Fetch JIRA. po chwili powinno pojawić się okno błędu z listą repozytoriów
i liczbą ich obserwatorów.
Rysunek 9 Okno błędu

Podobne dokumenty