Upload
tieto-corporation
View
897
Download
2
Embed Size (px)
DESCRIPTION
Theoretical knowledge and practical examples about using more complicated functionalities of JMeter tool. Presentation in Polish from a webinar that is dedicated to persons which have participated in our first training and have some previous experience with automation of web applications tests using JMeter tool. http://www.slideshare.net/TietoCorporation/automation-of-functional-tests-using-j-meter-tool Tomasz Stupak is Senior Test Engineer working for 5 years in Tieto. During his profession career he has experience with software and hardware testing.
Citation preview
© 2
010
Tie
to C
orpo
ratio
n
Automatyzacja testów funkcjonalnychz wykorzystaniem narzędzia JMeter, CZĘŚĆ II
Tomasz Stupak
Senior Test EngineerTieto
© 2010 Tieto Corporation2 Tomasz Stupak 11.04.2023
Spis Treści• Wstęp
3• JMeter advanced
4• Nagrywanie skryptu
5• Przygotowanie środowiska
6• Konfiguracja HTTP Request Defaults
7• Konfiguracja HTTP Proxy Server
8• Konfiguracja przeglądarki
9• Start serwera proxy
10• Nagrywanie skryptu
11• Nagrany skrypt
12• Odtwarzanie nagranego skryptu
13• Wyniki testu
14• Parametryzacja testu
15• Sposoby tworzenia zmiennych
16• Parametryzacja nazwy serwera
17• Zastąpienie nazwy serwera zmienną
18• Parametryzacja szukanej frazy
19• Zastąpienie szukanej frazy zmienną
20• Uruchamianie sparametryzowanego testu
21• Zmiana wartości zmiennej
22• Wskazówka
23• Wskazówka – UWAGA!
24• Wskazówka - rozwiązanie
25
© 2010 Tieto Corporation3 Tomasz Stupak 11.04.2023
Spis Treści• Wykorzystanie asercji
26• Wstęp
27• Dodanie asercji
28• Response Assertion
30• Konfiguracja Response Assertion
31• Size Assertion
32• Konfiguracja Size Assertion
33• Duration Assertion
34• Konfiguracja Durtion Assertion
35• Uruchomienie testu z asercjami
36• Wykorzystanie Kontrolerów Logicznych
38• Wstęp
39• Dodawanie Kontrolerów Logicznych
40• Dodanie Kontrolera Once Only Controller
41• Dodanie Kontrolera Interleave Controller
42• Dodanie Kontrolera Loop Controller
43• Dodanie Kontrolera If Controller
44• Uruchomienie testu z Kontrolerami Logicznymi
45• Wykorzystanie Timerów
46• Wstęp
47• Dodawanie Timerów
48• Dodanie Timera Synchronizing Timer
49• Dodanie Timera Constant Timer
50• Uruchomienie testu z Timerami
51
© 2010 Tieto Corporation4 Tomasz Stupak 11.04.2023
Spis Treści• Symulacja „żywych” użytkowników
52• Wstęp
53• Przygotowanie środowiska
54• Dodanie Timera Gaussian Random Timer
55• Konfiguracja Gaussian Random Timer
56• Symulacja żywych użytkowników
58• W następnym odcinku
59• W następnym odcinku
60
© 2
010
Tie
to C
orpo
ratio
n
Wstęp
5Tomasz Stupak 11.04.2023
© 2010 Tieto Corporation6 Tomasz Stupak 11.04.2023
JMeter advanced• Wykorzytanie bardziej skomplikowanych elementów
aplikacji:
• Nagrywanie skryptów za pomocą elementu HTTP Proxy Server
• Parametryzacja testu
• Użycie asercji
• Użycie Logic Controllers
• Użycie Timerów
• Symulacja „żywych” użytkowników
© 2
010
Tie
to C
orpo
ratio
n
Nagrywanie skryptu
7Tomasz Stupak 11.04.2023
© 2010 Tieto Corporation8 Tomasz Stupak 11.04.2023
Przygotowanie środowiska• Utwórz nowy projekt i dodaj
następujące elementy:• Thread Group do Test Planu• HTTP Proxy Server (Non-Test Elements)
do WorkBench• Dodaj do Thread Group następujące
elementy:• HTTP Request Defaults (Config Element)• HTTP Cookie Manager (Config Element)• Recording Controller (Logic Controller)• View Results Tree (Listener)
© 2010 Tieto Corporation9 Tomasz Stupak 11.04.2023
Konfiguracja HTTP Request Defaults• Web Server -> Server Name or IP:
• bash.org.pl
© 2010 Tieto Corporation10 Tomasz Stupak 11.04.2023
Konfiguracja HTTP Proxy Server• Test plan content -> Target Controller:
• Use Recording Controller• Test plan content -> Grouping:
• Store 1st sampler of each group only
© 2010 Tieto Corporation11 Tomasz Stupak 11.04.2023
Konfiguracja przeglądarki• W tym przykładzie użyto przeglądarki Mozilla Firefox• Narzędzia -> Opcje -> Zaawansowane -> Sieć ->
Ustawienia• Ręczna konfiguracja serwerów proxy
• Serwer proxy HTTP: Localhost• Port: 8080
© 2010 Tieto Corporation12 Tomasz Stupak 11.04.2023
Start serwera proxy• HTTP Proxy Server -> Start
• JMeter będzie przechwytywał ruch HTTP z przeglądarki• Port nasłuchu można zmienić w ustawieniach HTTP Proxy
Server (pole Port)• Po zakończeniu nagrywania naciśnij Stop oraz przywróć
poprzednie ustawienia w przeglądarce• JMeter domyślnie potrzebuje 1000 ms (1s) przerwy między
poszczególnymi „kliknięciami”
© 2010 Tieto Corporation13 Tomasz Stupak 11.04.2023
Nagrywanie skryptu• Otwórz w przeglądarce stronę http://www.bash.org.pl
• Pod Recording Controller pojawił się HTTP Request• W celu większej przejrzystości skryptu zmień nazwę samplera np.
na „Strona glowna”• Kliknij link „najnowsze”• Kliknij link „losowe”• Kliknij link „szukaj”• W pole wyszukiwania wpisz np. „mazowsze” i naciśnij
„szukaj”• Zatrzymaj serwer proxy• Nadaj requestom przejrzyste nazwy• Zapisz skrypt
© 2010 Tieto Corporation14 Tomasz Stupak 11.04.2023
Nagrany skrypt• Nagrany skrypt powinien wyglądać tak:
© 2010 Tieto Corporation15 Tomasz Stupak 11.04.2023
Odtwarzanie nagranego skryptu• Start testu:
• Run -> Start• CTRL+R
• Stop testu:• Run -> Stop• CTRL+.
• Wyczyszczenie wyników• Run -> Clear All• CTRL+E
© 2010 Tieto Corporation16 Tomasz Stupak 11.04.2023
Wyniki testu
© 2
010
Tie
to C
orpo
ratio
n
Parametryzacja testu
© 2010 Tieto Corporation18 Tomasz Stupak 11.04.2023
Sposoby tworzenia zmiennych• Test Plan - > User Defined Variables
• Zmienne globalne dla całego Test Planu
• Thread Group -> Add -> Config Elements -> User Defined Variables• Zmienne lokalne dla danego wątku
© 2010 Tieto Corporation19 Tomasz Stupak 11.04.2023
Parametryzacja nazwy serwera• Test Plan -> User Defined Variables -> Add
• Name: host• Value: bash.org.pl
© 2010 Tieto Corporation20 Tomasz Stupak 11.04.2023
Zastąpienie nazwy serwera zmienną• Thread Group -> HTTP Request Defaults
• Wartość pola „Server Name or IP” zastąp wartością zmiennej host• Stosuje się notację ${NAZWA_ZMIENNEJ}
• Przydatne np. w przypadku zapewnienia szybkiej przenaszalności skryptu z serwera testowego na serwer produkcyjny
© 2010 Tieto Corporation21 Tomasz Stupak 11.04.2023
Parametryzacja szukanej frazy• Test Plan -> User Defined Variables -> Add
• Name: search• Value: mazowsze
© 2010 Tieto Corporation22 Tomasz Stupak 11.04.2023
Zastąpienie szukanej frazy zmienną• Thread Group -> Recording Controller -> Szukaj (HTTP
Request) -> Send Parameters With the Request
• Wartość parametru q zastąp wartością zmiennej search:
© 2010 Tieto Corporation23 Tomasz Stupak 11.04.2023
Uruchamianie sparametryzowanego testu• Wyczyść wyniki poprzedniego testu (jeśli to konieczne)
• Run -> Clear All (CTRL+E)• Uruchom sparametryzowany test:
• Run -> Start (CTRL+R)• Sprawdź wyniki requestu wyszukiwania frazy:
• View Results Tree -> Szukaj -> Request• Nazwa serwera oraz wartość parametru q powinny zostać prawidłowo
pobrane z użytych zmiennych• View Results Tree -> Szukaj -> Response data (zmień na HTML)
• Powinna zostać pobrana odpowiednia strona
© 2010 Tieto Corporation24 Tomasz Stupak 11.04.2023
Zmiana wartości zmiennej• Zmień wartość zmiennej serach np. na „do sadu”:
• W przypadku problemów z kodowaniem znaków, użyj „%20” zamiast znaku spacji („do%20sadu”)
• Uruchom test i sprawdź wyniki requestu wyszukiwania frazy
© 2010 Tieto Corporation25 Tomasz Stupak 11.04.2023
Wskazówka• Przed nagraniem skryptu dodaj zmienną z wartością
wyszukiwanej frazy• Nagraj skrypt wpisując w pole wyszukiwania wartość
zdefiniowanej wcześniej zmiennej• Wartość parametru q powinna automatycznie przybrać postać
zdefiniowanej wcześniej zmiennej
© 2010 Tieto Corporation26 Tomasz Stupak 11.04.2023
Wskazówka – UWAGA!• Serwer Proxy szuka wszystkich wystąpień wartości danej
zmiennej i zmienia je• Może to doprowadzić do niepożądanej sytuacji:
• Dodaj zmienną o dowolnej nazwie i wartości search• Nagraj skrypt wpisując w pole wyszukiwania „search”
• Wartość zmiennej została wpisana także do ścieżki
© 2010 Tieto Corporation27 Tomasz Stupak 11.04.2023
Wskazówka - rozwiązanie• HTTP Proxy Server -> Test plan content
• Zaznacz „Regex matching”• Serwer proxy będzie traktorał zmienne jako wyrażenia regularne
• Wykorzystując wyrażenia regularne, sprecyzuj które występowania powinny być zastępowane zmienną• ^search$• Serwer proxy będzie zastępował tylko pojedyncze stringi „search”• Nie będzie zastępował np. „/search/”, używanego w ścieżce
• Przed odtworzeniem nagranego skryptu, przywróć wartość zmiennej do poprzedniego stanu
© 2
010
Tie
to C
orpo
ratio
n
Wykorzystanie asercji
28Tomasz Stupak 11.04.2023
© 2010 Tieto Corporation
Wstęp• Asercje służą do dodatkowego sprawdzania poprawności
wyników, zwracanych przez requesty• Przetwarzane są po każdym requeście w danym zakresie• Aby asercja stosowana była do jednego requestu, dodaj ją
jako jego podelement• Asercje domyślnie stosowane są do requestu głównego, a nie jego
podelementów• Można to zmienić w seksji „Apply to”
• Błędne wyniki asercji powodują pojawienie się błędu dla danego requestu
• W celu monitorowania błędów asersji można też użyć Listenera: Assertion Results
© 2010 Tieto Corporation30 Tomasz Stupak 11.04.2023
Dodanie asercji• W nagranym wcześniej skrypcie dodaj asercje do requestu
wyszukiwania frazy:• Thread Group -> Szukaj -> Add -> Assertions
• Dodaj następujące asercje:• Response Assertion• Size Assertion• Duration Assertion
• Do Thread Group dodaj teże Listener: Assertion Results:• Thread Gruop -> Add -> Listeners -> Assertion Results
© 2010 Tieto Corporation31 Tomasz Stupak 11.04.2023
© 2010 Tieto Corporation32 Tomasz Stupak 11.04.2023
Response Assertion• Porównuje wybraną część odpowiedzi na request ze
zdefiniowanym wzorce w wybrany sposób.• Sekcja „Apply to” pozwala określić do których requestów
odnosi się dana asercja (głównego, czy także podelementów)
• Sekcja „Response Field to Test” pozwala określić do jakiej części odpowiedzi odnosi się dana asercja
• Sekcja „Pattern Matching Rules” określa sposób, w jaki dany wzorzec jest porównywany:• Contains / Matches – wzorzec traktowany jest jako wyrażenie
regularne• Equals / Substring – wzorzec traktowany jest jako tekst
• Sekcja „Patterns to Test” definiuje wzorce do porównania
© 2010 Tieto Corporation33 Tomasz Stupak 11.04.2023
Konfiguracja Response Assertion• Patterns to Test -> Add
• Dodaj wzorzec, który będzie sprawdzany w odpowiedzi requestu
© 2010 Tieto Corporation34 Tomasz Stupak 11.04.2023
Size Assertion• Sprawdza, czy odpowiedź na request zajmuje odpowiednią
ilość bajtów• Sekcja „Apply to” pozwala określić do których requestów
odnosi się dana asercja (głównego, czy także podelementów)
• Sekcja „Size to Assert” określa rozmiar oraz sposób porównania:• Równe• Różne• Większe (lub równe)• Mniejsze (lub równe)
© 2010 Tieto Corporation35 Tomasz Stupak 11.04.2023
Konfiguracja Size Assertion• W pole „Size in bytes” wpisz przykładową ilość bajtów• W „Type of Comparison” wybierz „>”
© 2010 Tieto Corporation36 Tomasz Stupak 11.04.2023
Duration Assertion• Sprawdza, czy odpowiedź na request pojawiła się przed
upłynięciem podanego czasu• Sekcja „Apply to” pozwala określić do których requestów
odnosi się dana asercja (głównego, czy także podelementów)
• Jeśli odpowiedź pojawi się po upłynięciu podanego czasu, zwracany jest błąd
• Czas podawany jest w milisekundach
© 2010 Tieto Corporation37 Tomasz Stupak 11.04.2023
Konfiguracja Durtion Assertion• W pole „Duration in milliseconds” wpisz przykładowy czas
© 2010 Tieto Corporation38 Tomasz Stupak 11.04.2023
Uruchomienie testu z asercjami• Wyczyść wyniki poprzedniego testu (jeśli to konieczne)
• Run -> Clear All (CTRL+E)• Uruchom sparametryzowany test:
• Run -> Start (CTRL+R)• Sprawdź wyniki requestu wyszukiwania frazy:
• View Results Tree -> Szukaj• W tym przykładzie wszystkie asercje powinny zwrócić błąd
• Sprawdź wyniki Listenera: Assertion Results• Dla requestu wyszukiwania frazy powinny być zwrócone błędy
asercji
© 2010 Tieto Corporation39 Tomasz Stupak 11.04.2023
Zawartość Listenerów:• View Results Tree (po lewej)• Assertion Results (poniżej)
• Zmień parametry asercji i po ponownym uruchomieniu skryptu obserwuj wyniki
© 2
010
Tie
to C
orpo
ratio
n
Wykorzystanie Kontrolerów Logicznych
40Tomasz Stupak 11.04.2023
© 2010 Tieto Corporation41 Tomasz Stupak 11.04.2023
Wstęp• Kontrolery Logiczne określają logikę decydującą o tym,
kiedy wysłać request• Mogą zmienić kolejność wykonywania requestów• Mogą modyfikować requesty• Mogą powodować powtórzenie wykonania requestów• Można je łączyć w celu uzyskania danych rezultatów
© 2010 Tieto Corporation42 Tomasz Stupak 11.04.2023
Dodawanie Kontrolerów Logicznych• Istnieją dwa sposoby dodawania Kontrolerów Logicznych
• Dodawanie pustego Kontrolera Logicznego i umieszczenie Samplerów jako jego podelementy
• Dodanie Kontrolera Logicznego jako rodzica danego Samplera• Thread Group -> Add -> Logic Controller
• Po dodaniu Kontrolera Logicznego, można umieszczać Samplery jako jego podelementy
• Sampler -> Insert Parent -> Logic Controller• Kontroler Logiczny zostanie dodany jako rodzic danego Samplera
• W poprzednich przykładach użyty został jeden Kontroler Logiczny:• Recording Controller
© 2010 Tieto Corporation43 Tomasz Stupak 11.04.2023
Dodanie Kontrolera Once Only Controller• Once Only Controller sprawia, że
jego podelementy uruchamiane są tylko przy pierwszej iteracji testu
• Dodaj Once Only Controller jako rodzica requestu „Strona glowna”:• Strona glowna -> Insert Parent ->
Once Only Controller• Ustaw liczbę iteracji wątku na 3
• Thread Group -> Loop Count: 3
© 2010 Tieto Corporation44 Tomasz Stupak 11.04.2023
Dodanie Kontrolera Interleave Controller• Interleave Controller sprawia, że
jego podelementy uruchamiane są naprzemiennie co każdą iterację (kolejno)
• Dodaj Interleave Controller jako rodzica requestów „Najnowsze” i „Losowe”• Najnowsze -> Insert Parent ->
Interleave Controller• Metodą „przenieś i upuść” dodaj
request „Losowe” jako podelement Kontrolera Interleave Controller (Add as Child)
• Podobnie działa Random Controller (uruchamia losowo)
© 2010 Tieto Corporation45 Tomasz Stupak 11.04.2023
Dodanie Kontrolera Loop Controller• Loop Controller uruchamia
podelementy daną ilość razy w ramach danej iteracji
• Dodaj Loop Controller jako rodzica requestu „Strona wyszukiwania” i ustaw liczbę iteracji na 2• Strona wyszukiwania -> Insert
Parent -> Loop Controller• Loop Controller -> Loop
Count: 2
© 2010 Tieto Corporation46 Tomasz Stupak 11.04.2023
Dodanie Kontrolera If Controller• If Controller decyduje, czy
jego podelementy mają być uruchomione, czy nie
• Dodaj If Controller jako rodzica requestu „Szukaj” i ustaw warunek uruchomienia, jeżeli zmienna search ma wartość „test”:• Szukaj -> Insert Parent -> If
Controller• If Controller -> Condition: "$
{search}" == "test"
© 2010 Tieto Corporation47 Tomasz Stupak 11.04.2023
Uruchomienie testu z Kontrolerami Logicznymi• Uruchom test i sprawdź
wyniki Listenera: View Results Tree:• Request „Strona glowna”
wykonał się tylko w pierwszej iteracji
• Requesty „Najnowsze” i „Losowe” wykonywały się naprzemiennie co iterację
• Request „Strona wyszukiwania” wykonał się dwukrotnie co daną iterację
• Request „Szukaj” nie wykonał się, ponieważ warunek nie został spełniony
© 2
010
Tie
to C
orpo
ratio
n
Wykorzystanie Timerów
48Tomasz Stupak 11.04.2023
© 2010 Tieto Corporation
Wstęp• Timery używane są do tworzenia przerw między
wykonywaniem requestów• Domyślnie JMeter wysyła requesty bez przerw, co może
spowodować przeciążenie serwera• Gdy użyty jest więcej niż jeden Timer, JMeter sumuje ich
wartości• Dodawane jako podelementy Samplerów lub Kontrolerów• Timery przetwarzane są przed danym Samplerem• Timery, które nie są przydzielone do Samplera, nie są
przetwarzane w ogóle
© 2010 Tieto Corporation50 Tomasz Stupak 11.04.2023
Dodawanie Timerów• Aby przydzielić Timer do danego Samplera, dodaj go jako
jego podelement:• Sampler -> Add -> Timer
• Timer będzie przetwarzany przed danym Samplerem• Aby uruchomić Timer po danym Samplerze, dodaj go do
następnego Samplera
© 2010 Tieto Corporation51 Tomasz Stupak 11.04.2023
Dodanie Timera Synchronizing Timer• Synchronizing Timer blokuje wątki, do
czasu aż określona liczba wątków zostanie zablokowana, po czym wznawia je jednocześnie
• Ustaw liczbę wątków na 3• Thread Group -> Number of Threads: 3
• Dodaj Synchronizing Timer jako podelement requestu „Strona glowna”:• Strona glowna -> Add -> Timers ->
Synchronizing Timer• Ustaw blokowanie 3 wątków:
• Synchronizing Timer -> Number of Simulated Users to Group by: 3
© 2010 Tieto Corporation52 Tomasz Stupak 11.04.2023
Dodanie Timera Constant Timer• Constant Timer opóźnia wykonanie
danego requestu o ustaloną ilość czasu
• W celu wprowadzenia losowego opóźnienia, użyj Gaussian Random Timer lub Uniform Random Timer
• Dodaj Constant Timer jako podelement requestu „Strona Wyszukiwania”:• Strona wyszukiwania -> Add -> Timer ->
Constant Timer• Ustaw opóźnienie na 1 sekundę:
• Constant Timer -> Thread Delay: 1000• Czas podawany jest w milisekundach
© 2010 Tieto Corporation53 Tomasz Stupak 11.04.2023
Uruchomienie testu z Timerami• Uruchom test i obsersuj wyniki
Listenera: View Results Tree:• Dzięki Timerowi: Synchronizing
Timer request najpierw wykonały się 3 requesty „Strona glowna”
• Przed każdorazowym wykonaniem requestu „Strona wyszukiwania” miała miejsce 1-sekundowa pauza
© 2
010
Tie
to C
orpo
ratio
n
Symulacja „żywych” użytkowników
© 2010 Tieto Corporation
Wstęp• Zachowanie „żywego” użytkownika nieco różni się od
zachowania nagranego skryptu• Użytkownik wysyła requesty do serwera w różnych
odstępach czasu, a powtarzane przez niego czynności prawie nigdy nie są identycznie rozmieszczone w czasie
• „Ręczna” konfiguracja JMetera w celu symulacji „żywego” użytkownika zajęłaby dużo czasu
• Przy odpowiednim wykorzystaniu dostępnych opcji, można znacznie zautomatyzować proces symulacji „żywych” użytkowników
© 2010 Tieto Corporation56 Tomasz Stupak 11.04.2023
Przygotowanie środowiska• Otwórz nowy projekt i dodaj
oraz skonfiguruj elementy potrzebne do nagrywania skryptu
• Opcjonalnie sparametryzuj skrypt dodając odpowiednie zmienne
• Ustaw proxy przeglądarki, aby requesty mogły być rejestrowane przez JMetera
© 2010 Tieto Corporation57 Tomasz Stupak 11.04.2023
Dodanie Timera Gaussian Random Timer• Gaussian Random Timer
powoduje opóźnienie wykonania danego requestu o zdefiniowaną wartość czasu oraz zdefiniowane odchylenie standardowe
• Dodaj Guassian Random Timer jako podelement HTTP Proxy Server:• HTTP Proxy Server -> Add ->
Timer -> Gaussian Random Timer
© 2010 Tieto Corporation58 Tomasz Stupak 11.04.2023
Konfiguracja Gaussian Random Timer• Gaussian Random Timer generuje opóźnienie będące
sumą:• Rozkład normalny (średnia 0.0, odchylenie 1.0) * Deviation (wartość
podana przez użytkownika)• Stałe opóźnienie (wartość podana przez użytkownika)
• W sekcji „Thread Delay Properties” ustaw następujące wartości:• Deviation: 1000• Constant Delay Offset: ${T}
• T jest zmienną, w której JMeter przechowuje faktyczny czas, jaki minął od wysłania ostatniego requestu
© 2010 Tieto Corporation59 Tomasz Stupak 11.04.2023
• W ten sposób do każdego requestu nagranego przez HTTP Proxy Server dodawany będzie Gaussian Random Timer z faktycznym opóźnieniem, jakie miało miejsce podczas nagrywania, losowo zmodyfikowana o wartość z pola „Deviation”
© 2010 Tieto Corporation60 Tomasz Stupak 11.04.2023
Symulacja żywych użytkowników• Włącz HTTP Proxy Server i
nagraj przykładowy skrypt• Zauważ, że do każdego
requestu HTTP dołączany jest Gaussian Random Timer z taką wartością Constant Delay Offset, jaka faktycznie miała miejsce podczas nagrywania
• Można usunąć lub zdezaktywować Timer pierwszego requestu:• Gaussian Random Timer ->
Remove (Delete)• Gaussian Random Timer -> Disable
© 2
010
Tie
to C
orpo
ratio
n
W następnym odcinku
© 2010 Tieto Corporation62 Tomasz Stupak 11.04.2023
W następnym odcinku• JMeter advanced+ – testowanie bazy danych +
wykorzystanie wyrażeń regularnych (RegExp):
• Konfiguracja środowiska bazodanowego na potrzeby testów
• Łączenie się JMetara z bazą danych za pomocą JDBC Connection Configuration
• Wysyłanie zapytań do bazy danych zapomocą JDBC Request
• Ekstrakcja potrzebnych informacji z wykorzystaniem wyrażeń regularnych
© 2
010
Tie
to C
orpo
ratio
n
Tomasz Stupak
Senior Test EngineerTieto