czwartek, 28 sierpnia 2014

Logowanie

• Logi aplikacji zachowują informacje dotyczące przebiegu jej działania. Dzięki ich posiadaniu można post factum przeanalizować historię czynności podjętych przez aplikację i na jej podstawie np. zdiagnozować błąd programu lub użytkownika
• Wśród informacji które powinny być przekazywane przez aplikację, można zaliczyć:
  - Wszelkiego rodzaju komunikaty błędów, w szczególności wyjątki. W większości przypadków informacji tych nie eksponuje się użytkownikowi, ale nie można ich porzucić - bez nich diagnozowanie przyczyny błędu byłoby utrudnione lub wręcz niemożliwe
  - Informacje o istotnych parametrach (poprawnego) działania aplikacji - mogą one być przydatne np. do sporządzenia statystyk wykorzystania i wydajności aplikacji
  - Szczegółowe informacje o sekwencji wykonywania jednostek aplikacji (np. metod) - pozwalają np. na śledzenie aktywności podejmowanych przez użytkowników (tzw. kontrola odpowiedzialności użytkownika)
  - Szczegółowe informacje o zmianach stanu aplikacji (np. wynikach obliczeń) - pozwalają one na diagnozowanie błędów na poziomie algorytmu (tzw. debugowanie, odpluskwianie)
(Zapisywanie logów nie jest alternatywą, tylko uzupełnieniem śledzenia wykonania za pomocą specjalizowanych narzędzi - debugger. Tylko poprzez zapisane logi można poznać historię działania aplikacji w środowisku produkcyjnym)
• Wypisywanie komunikatów do wyjścia standardowego (System.out.print()) NIE jest poprawnym rozwiązaniem logowania
  - Brak automatyzacji, wsparcia dla programów logowania
  - Brak kontroli nad emisją komunikatów
  - Z reguły niezamierzona ekspozycja komunikatów przed użytkowaniem aplikacji
  - Nieoptymalne działanie
• Poprawne rozwiążanie wymaga zastosowania specjalizowanej implementacji logowania



 

wtorek, 15 lipca 2014

Odczyt danych z pliku .properties

1. Plik properties:
dane.properties
zawartość:
test.1=testuje1
test.2=testuje2
położenie:
(path to project)\(project name)\src\test\properties\data.properties

2. Plik klasa Prop.java:
Prop.java
zawartość:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class Prop {
    
    static Properties testData;
    static String propDirectory;
    static String dataFile;

    static {
        propDirectory = System.getProperty("user.dir") + "/src/test/properties/"; //katalog z plikiem properties
        try {
            loadTestData(); //odczyt danych z pliku
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    private static void loadTestData() throws FileNotFoundException, IOException {
        testData = new Properties();
        dataFile = "/data.properties";
        testData.load(new FileInputStream(propDirectory + dataFile));
    }
    //metoda używana do ładowania konkretnej wartości z pliku properties 
    protected static String getData(String key) {
 return testData.getProperty(key);
    }
}

położenie bez znaczenia (najlepiej wśród innych plików konfiguracyjnych dla projektu).

3. Plik z odczytem przykładowo:
App.java
zawartość:
import static (project name).Prop.getData; //statyczny import używanej metody dla skrócenia wpisów

public class App {
    public static void main( String[] args ){
        System.out.println(getData("test.1"));
    }
}
położenie bez znaczenia...

Wynik:
[exec:exec]
testuje1
------------------------------------------------------------------------
BUILD SUCCESS

czwartek, 5 czerwca 2014

Typy danych i operacje na nich

Java jest językiem programowania:
- o statycznie określonym typie (statically typed) tzn. że wartość zmiennej bądź wyrażenia ma już określony typ w momencie kompilacji (w językach dynamicznie typizowanych typ zmiennej bądź wyrażenia może zostać dopiero określony w momencie przypisania wartości bądź obliczenia wartości wyrażenia, w więc podczas wykonania programu)
- o ściśle określonym typie (strongly typed), gdzie typ:
   * ściśle określa zakres zawartości jakie zmienna może przechowywać, bądź wyrażenie mieć (np: zakres wartości typu byte to <-128;127>
   • ściśle określa zbiór operacji jakie mogą być wykonywane (np: operator - nie jest zdefiniowany dla łańcuchów znaków)
   • oraz oznaczenie tych operacji (np: operator + dla liczb całkowitych i łańcuchów znaków)

W języku Java istnieją tylko dwa rodzaje typów wartości:
  - proste (primitives)
  - referencje (references)
Dodatkowo istnieje jeden specjalny typ którego nazwa nie jest określona (ale mówi się o typie null):
  - typ wyrażenia null
  - ponieważ typ wyrażenia null nie ma nazwy, więc nie można
    • tworzyć zmiennych takiego typu
    • rzutować na ten typ
  - referencja null jest jedyną wartością jaką posiada wyrażenie typu null
  - referencja null może być rzutowana na referencję do dowolnego typu


Typy proste (primitive types) są predefiniowane w języku Java, a nazwy są słowami kluczowymi
  - nie można tworzyć identyfikatorów o takich nazwach


Typ logiczny boolean

Ten typ reprezentuje wartość logiczną o dwóch wartościach:
- prawda (true)
- fałsz(false)
Operatory dla typu boolean to:
- porównania (equalilty) == i =
- logiczne zaprzeczenie (logical complement) !
- logiczne & (AND), ^ (XOR), | (OR)
- warunkowe && (AND i || (OR)
- warunkowy operator ?:
- operator konkatenacji + dla typu String
Właściwości:
• Nie istnieją żadne konwersje z typu boolean do typów numerycznych i na odwrót
• Jedynym możliwym sposobem "konwersji" z typu numerycznego do typu boolean jest wykonanie operacji x!=0
• Jedynym możliwym sposobem "konwersji" z typu referencja do typu boolean jest wykonanie operacji x!=null
• Operator konkatenacji + dla String
  - jeżeli jednym z argumentów operatora + jest typ String to następuje automatyczna konwersja wartości typu boolean do jego reprezentacji jako String, tzn: "true" albo "false" w zależności od jego wartości logicznej
• Operator & zwraca wartość prawda jeżeli oba argumenty mają wartość prawda i zwraca fałsz w pozostałych przypadkach
• Operator | zwraca wartość fąłsz jeżeli oba argumenty mają wartość fałsz i zwraca prawda w pozostałych przypadkach
• Operator ^ zwraca wartość prawda jeżeli wartości argumentów są różne i zwraca fałsz w pozostałych przypadkach
• Warunkowy operator && działa jak & z tym, że wartość prawego argumentu nie jest obliczana, gdy lewy ma wartość fałsz
• Warunkowy operator || działa jak | z tym, że wartość prawego argumentu jest obliczana tylko wtedy, gdy lewy ma wartość fałsz
Literał stanowi reprezentację wartości typu prymitywnego, łańcucha znaków (String) bądź typu null w kodzie źródłowym programu
W Java wyróżnia się następujące typy literałów:
  - Liczby
    • całkowite
    • zmiennoprzecinkowe
  - wartości boolowskie
  - znaki
  - łańcuchy znaków
  - null
Typ boolean ma tylko dwie wartości reprezentowane przez literały:
  - true - odpowiada wartości logicznej prawda
  - false - odpowiada wartości logicznej fałsz
Literał boolowski ma zawsze typ wartości boolean

Typy numeryczne całkowite:
  - byte: 8-bitowa liczba całkowita ze znakiem
  - short: 16-bitowa liczba całkowita ze znakiem
  - int: 32-bitowa liczba całkowita ze znakiem
  - long: 64-bitowa liczba całkowita ze znakiem
  - char: 16-bitowa liczba całkowita bez znkau reprezentująca jednostkę kodową UTF-16
Zakres liczb całkowitych ze znakiem to:
  - byte: 8, [-128;127]
  - short: 16, [-32768;32767]
  - int: 32, [−2147483648;2147483647]
  - long: 64, [−9223372036854775808;9223372036854775807]
Zakres licz całkowitych bez znkau to:
  - char: 16, ['\u0000';'\uffff'] (tzn: [0;65535])
Operatory działające na typie całkowitym:
• Operatory porównania - wartość wyrażenia boolean <, <=, >=, >, ==, !=
• Operatory numeryczne - wartość wyrażenia int lub long
  - jedno-argumentowe: + - (-x)
  - multiplikatywne: * / % (np: x*y; x/y; x%y)
  - addyktywne: + - (np: x+y; x-y)
  - inkrementujący ++ z prefiksem i sufiksem (np: ++x; x++)
  - dekrementujący -- z prefiksem i sufiksem (np: --x; x--)
  - bitowe przesunięcie ze znakiem i bez << >> >>>
  - bitowa negacja ~(not)
  - bitowe operatory logiczne & (AND), | (OR), ^ (XOR)
  - operator warunkowy ?:
• Operator rzutowania - konwertuje liczbę całkowitą na dowolny typ numeryczny
• Operator konkatenacji + dla Sting
  - Jeżeli jednym z argumentów operatora + jest typ String to następuje automatyczna konwersja argumentu typu całkowitego do jego reprezentacji jako String w formacie dziesiętnym. Wynikiem działania operatora jest nowy String będący połączeniem argumentów operatora +
Właściwości:
• Jeżeli przynajmniej jeden z argumentów operatora numerycznego (z wyjątkiem przesunięcia bitowego) jest typu long, to operacja przeprowadzana jest z 64 bitową precyzją i wynikiem jest wartość typu long. Jeżeli drugi z argumentów nie jest typu long, to jest on rozszerzany do typu long (tzw. numeryczna promocja)
• W każdym innym przypadku operacje przeprowadzane są z 32 bitową precyzją w wynikiem jest wartość typu int. Jeżeli którykolwiek z argumentów nie jest typu int, to jest on rozszerzany do tego typu
• Każda wartość typu całkowitego może być rzutowana na dowolny typ numeryczny. Nie ma rzutowania na typ boolean, jak to jest w niektórych językach programowania np C++
• Operatory całkowite nie wykazują w żaden sposób przekroczenia zakresów (overflow, underflow)
• Operator całkowity może być źródłem wyjątku w następujących przypadkach:
  - kiedy wymagana była operacja odpakowania (unboxing), a jej wynikiem było null - NullPointerException
  - kiedy prawym argumentem operatora / lub % jest wartość 0 - ArithmeticException
  - operatory inkrementacji i dekrementacji mogą powodować wyjątek OutOfMemoryError w przypadku wykonywania opakowania (boxing) a nie ma wystarczająco dożo pamięci do jej wykonania

Typy numeryczne zmiennopozycyjne:
  - float: 32-bitowa liczba zgodna z IEEE754
  - double: 64-bitowa liczba zgodna z IEEE754

Operator /:
• Dla liczb całkowitych mamy do czynienia z dzieleniem całkowitym, tzn. wynikiem jest liczba będąca częścią całkowitą z dzielenia (zaokrąglenie w kierunku 0)
• Jeżeli dzielna i dzielnik są liczbami niezerowymi różnych znaków to wynik jest ujemny. Jeżeli są tych samych znaków to wynik jest dodatni z jednym wyjątkiem
  - dzielenia najmniejszej liczby ujemnej (wartość dowolnego zakresu danego typu całkowitego: int bądź long) przez -1. W tym przypadku wynikiem jest najmniejsza liczba ujemna

Operator %:
• Operator % to reszta z dzielenia całkowitego: 3 % 2 ->1
• Działa on na takiej zasadzie, że: (a/b)*b+(a%b)=a
• Oznacza to, że wynik może być:
  - dodatni tylko wtedy, gdy dzielna jest dodatnia
  - ujemny tylko wtedy, gdy dzielna jest ujemna
• Dla przykładu:
8%5 ->3
-8%5 -> -3
8%-5 -> 3
-8%-5 -> -3

•• 

Identyfikatory

Identyfikator to dowolnej długości ciąg znaków składający się z liter i cyfr, przy czym pierwszym znakiem musi być litera i ciąg znaków. Identyfikator nie może tworzyć: słowa kluczowego, literału typu boolean i literału typu null.

Za literę Java uznaje się znak Unicode spełniający kryterium:
- Character.isJavaIdentifierStart(int), np:
   • znak ASCI o kodach \u0041-\u005a ('A'-'Z')
   • znak ASCI o kodach \u0061-\u007a ('a'-'z')
   • znaki: \u005f ('_') i \u0024('$')

Pozostałe znaki muszą spełniać kryterium:
- Character.isJavaIdentifierPart(int), np:
   • są literami Java
   • są cyframi Java - znaki ASCI o kodach \u0030-\u0039 ('0'-'9')

W identyfikatorach, z uwagi na czytelność kodu, NIGDY nie stosujemy znaków '$' bądź '_'

W wielu językach programowania dopuszczalne są pewne konstrukcje, które z punktu widzenia stylu programowania są wręcz zabronione

W programowaniu najważniejsza zawsze jest czytelność kodu, chyba że ktoś chce specjalnie uczynić kod mało czytelnym - ale do tego są specjalne narzędzia (code obfuscation)

Wielkość znaków ma znaczenie - nie wykorzystujemy tego, aby tworzyć zmienne o nazwach brzmiących tak samo

Nie zaleca się stosowania narodowych znaków diaktrycznych, mimo że jest to możliwe (to też litery)

Przykładowe poprawne identyfikatory:
int variables = 10;
boolean false = false;
Float realNumber = null;
char cAmEl = '\u0041';
long _123456 = 123456;
String Ładne_dęby = "Ładne dęby";

Przykładowe błędne identyfikatory:
short short&y = 12;
long 654_321 = 654321;

Wersje Javy

Java SE (Standard Edition) - platforma ogólnego przeznaczenia, dedykowana to tworzenia i uruchamiania aplikacji użytkownika końcowego

Java EE (Enterprise Edition) - platforma rozszerzona w stosunku do Java SE o sieciowy serwer aplikacji, dedykowana do tworzenia i uruchamiania aplikacji biznesowych

Java ME (Micro Edition) - platforma dedykowana do tworzenia i uruchamiania aplikacji uruchamianych w warunkach ograniczonych zasobów (urządzenia mobilne, przemysłowe, itp)

Java FX - platforma dedykowana do tworzenia i uruchamiania aplikacji tzw. bogatych (rich) aplikacji internetowych


Platformę Java SE można pobrać w dwóch postaciach:
  - JRE (Java Runtime Environment) - przeznaczona wyłącznie do uruchamiania programów w języku Java
  - JDK (Java Development Kit) - przeznaczona do kompilowania i uruchamiania programów w języku Java, zawiera JRE


Podczas instalacji w systemie windows należy pamiętać o zmiennych systemowych:
  - JAVA_HOME
  - PATH

Polecenia:
java -version wypisuje wersję Javy
java -help pomoc
java -verbose szczegółowe komunikaty podczas uruchamiania

wtorek, 11 lutego 2014

Selenium: lokalizacja elementu

<br /> <html><br /> <body><br /> <form id="loginForm"><input name="username" type="text" /> <br /> <input name="password" type="password" /> <br /> <input name="continue" type="submit" value="Login" /> <br /> </form></body> <br /> <html> <br />
findElement(By.className(String className));
findElement(By.cssSelector(String selector));
findElement(By.id('loginForm'));
findElement(By.linkText('Continue'));
findElement(By.name('username'));
findElement(By.name('password'));
findElement(By.name('continue'));
findElement(By.partialLinkText('Conti'));
findElement(By.tagName(String name));
findElement(By.xpath("/html/body/form[1]"));
findElement(By.xpath("//form[1]"));
findElement(By.xpath("//form[@id='loginForm']"));

findElement(By.xpath("//form[input/@name='username']"));
findElement(By.xpath("//form[@id='loginForm']/input[1]"));
findElement(By.xpath("//input[@name='username']"));

findElement(By.xpath("//input[@name='continue'][@type='button']"));
findElement(By.xpath("//form[@id='loginForm']/input[4]"));

Visitor

TODO

Template

TODO

Strategy

TODO

State

TODO

Observer

TODO

Memento

TODO

Mediator

TODO

Iterator

TODO

Interpreter

TODO

Command

TODO

Chain Of Responsibility

TODO

Proxy

TODO

Flyweight

TODO

Facade

TODO

Decorator

TODO

Composite

TODO

Bridge

TODO

Adapter

TODO