niedziela, 30 października 2011

Maven - Eclipse

Maven jest narzędziem do budowy oprogramowania.
Cechy Mavena:
  • standaryzuje rozmieszczenie katalogów w systemie, nazewnictwo bibliotek i archiwów,
  • umożliwia podział projektu na moduły, z których każdy ma własną konfigurację,
  • wszystkie dane związane z budową aplikacji i  potrzebnymi wtyczkami umieszczone są w pliku konfiguracyjnym POM (Project Object Model).,
  • proces budowania oparty jest na wtyczkach,
  • istnieje możliwość dziedziczenia i system zależności pozwalający ograniczyć powtarzanie kodu,
  • pozwala generować raporty,

Instalacja:
w Eclipsie wybieramy Help->Install New Software... Dodajemy stronę: http://m2eclipse.sonatype.org/sites/m2e  -> zaznaczamy wszystko ->instalujemy.

Pierwszy projekt:
File->New->Other...->Maven->Maven Project
Wybieramy archetyp, czyli rodzaj budowanej aplikacji (w tym przypadku do budowy prostego programu wystarczy zaznaczony maven-archetype-quickstart)

Uzupełniamy podstawowe informacje o projekcie:
  • GroupID - id organizacji tworzącej projekt np. com.mycompany.app,
  • ArtifactId - nazwa projektu,
  • modelVersion - wersja modelu POM,
  • Package – nazwa automatycznie utworzonej paczki z domyślną klasą,
Te i inne dane wpisane przy tworzeniu można później zmienić w pliku POM.xml.

Po utworzeniu projektu w pliku POM.xml mamy jeszcze pozycje:
  • packaging - rodzaj wynikowego archiwum jar,war,...
  • url - adres strony projektu
  • properties - project.build.sourceEncoding - zastosowane kodowanie
Struktura katalogów:
Dodanie biblioteki:
Aby dodać bibliotekę używaną w projekcie wystarczy dopisać ją do POM, a Maven sam już ją ściągnie i zamontuje. Aby to zrobić należy wpisać w sekcji <dependencies> </dependencies> nową zależność:

Dodanie biblioteki JUnit:
<dependency>
<groupId>junit</groupId>   <!--nazwa archiwum-->
<artifactId>junit</artifactId> <!--nazwa archiwum-->
<version>3.8.1</version>   <!--wersja archiwum-->
<scope>test</scope>   <!--zasięg widoczności artefaktu-->
</dependency>

Zakres widoczności <scope> dzielimy na:
  • test  - obecna tylko przy uruchomieniu testów, nie włączana do wynikowego archiwum,
  • compile - włączana do archiwum,
  • provided - udostępniona przez środowisko uruchomieniowe, nie włączana do archiwum,
  • system - udostępniania przez system,
  • import - dołącza artefakt typu POM,

Moduły:
Dzięki Maven można tworzyć projekty złożone z modułów, czyli innych projektów, projekty podrzędne dziedziczą z nadrzędnego.
POM projektu głównego:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>pl.kodujemy</groupId>
<artifactId>ProjektGlowny</artifactId>
<packaging>pom</packaging>   <!-- projekt nadrzędny trzeba zmienić na pom-->
<version>1.0-SNAPSHOT</version>
<name>kodujemy</name>
<url>http://maven.apache.org</url>
<modules>  <!-- litsta modułów projektu -->
<module>widok</module>
<module>model</module>
<module>kontroler</module>
</modules>
...
</project>

POM podrzędny:
<project>
<parent>   <!-- nazwa rodzica -->
<groupId>pl.kodujemy</groupId>
<artifactId>ProjektGlowny</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>pl.kodujemyy</groupId>
<artifactId>widok</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>widok</name>
<url>http://maven.apache.org</url>
...
</project>

Aby stworzyć moduł do projektu:
New->Other...->Maven->Maven Module
Wybieramy Parent Project - czyli projekt pod który chcemy się podpiąć, pamiętając, aby wcześniej zmienić wartość jego <packaging> na pom.

Funkcje:
Z poziomu menu kontekstowego PPM->Run As mamy do wyboru kilka funkcji Mavena do wyboru:
  • assembly,
  • build,
  • clean,
  • generate sources,
  • install – skopiowanie utworzonego artefaktu do lokalnego repozytorium,
  • package – utworzenie wynikowego artefaktu, np.: archiwum jar lub war,
  • test – wykonanie testów jednostkowych,

Raporty:
Maven umożliwia wygenerowanie raportów np:
  • maven-javadoc-plugin – tworzy dokumentacje javadoc,
  • maven-checkstyle-plugin – raport stylu kodu: obecność komentarzy, użycie zmiennych, importów...
  • maven-pmd-plugin – wykrywa fragmenty pisane metodą „kopiuj/wklej”, pomijane bloki kodu...
  • findbugs-maven-plugin – wykrywa typowe błędy statyczne,
  • maven-surefire-report-plugin – raport wykonania testów,

Sekcja raportów:
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.0-beta-2</version>
<configuration>
<reportPlugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.7</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>2.1</version>
<configuration>
<aggregate>true</aggregate>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.6</version>
</plugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
</project>

sobota, 29 października 2011

Java – konsola

Wczytywanie pojedynczych znaków z konsoli:
package kkk;

import java.io.*;
class BRReadLines{
    public static void main(String args[]) throws IOException {
 char c;
 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 System.out.println("Wpisz znaki, 'q' to quit.");
 do {
     c = (char) br.read();
     System.out.println(c);
 } while (c != 'q');
    }
}
Wczytywanie łańcuchów znaków z konsoli:
package kkk;

import java.io.*;
class Main {
    public static void main(String args[]) throws IOException {
 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 String str;
 System.out.println("Enter lines of text.");
 System.out.println("Enter 'stop' to quit.");
 do {
     str = br.readLine();
     System.out.println(str);
 } while (!str.equals("stop"));
    }
}
Znalezione na http://math.hosted.pl/math_2/programowanie_obiektowe/wyklad10.pdf
import java.util.Scanner;

public class Czytanie {
    public static void main(String args[]) {
 Scanner s = new Scanner(System.in);
 System.out.print("Imię i nazwisko: ");
 String i = s.next();
 String n = s.next(); // wczytywanie słów
 System.out.println(i+" "+n);
 System.out.println("Pseudo:");
 String r = s.next(); 
 System.out.println(r);
 System.out.print("Wiek: ");
 int w = s.nextInt(); // wczytwanie liczby całkowitej
 System.out.print("Zarobki: ");
 double z = s.nextDouble(); // rzeczywistej
 System.out.print("Opis: ");
 String o = s.nextLine(); // wiersza
    }
}
Znalezione na: http://student.pwsz.elblag.pl/~jopi/?co=obiektowe&id=021&p=1

wtorek, 18 października 2011

Logi - Log4j

Chronologiczny zapis informacji z działania systemu. Dane zapisywane w pliku, bazie danych, czy wyświetlane na konsoli z informacjami o przebiegu działania programu, sytuacjach gdzie występują błędy, albo jakiekolwiek inne ważne wg nas informacje. Może się przydać gdy w działającym już programie wystąpi błąd, a odtworzenie sytuacji kiedy on wystąpił jest trudne. Logi mogą być zastępowane przez nowsze co jakiś czas.

Przykład:
Klasa w której wywołujemy zapis logów:
package logi;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class Log4jTest {
// inicjalizacja logera
static final Logger logger = Logger.getLogger(Log4jTest.class); 
public static void main(String[] args) {

// plik konfiguracyjny
 PropertyConfigurator.configure("log4j.properties"); 

// wywołanie logów
 logger.trace("Info - TRACE");   
 logger.debug("Info - DEBUG");
 logger.info("Info - INFO");
 logger.warn("Info - WARN");
 logger.error("Info - ERROR");
 logger.fatal("Info - FATAL");
    }
}
Plik konfiguracyjny "log4j.properties":
#Ustalamy gdzie i jakie komunikaty beda wywolywane CA-konsola 
log4j.rootLogger=DEBUG, CA 

#Ustawienia dla konsoli
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
#Typ komunikatu
log4j.appender.CA.layout.ConversionPattern=%-4r [%t] %-5p  %x - %m%n
Wyniki wypisany na konsoli:
1    [main] DEBUG   - Info - DEBUG
2    [main] INFO    - Info - INFO
2    [main] WARN    - Info - WARN
2    [main] ERROR   - Info - ERROR
2    [main] FATAL   - Info - FATAL 
Zapisanie loga do pliku.
Zmieniamy plik konfiguracyjny „log4j.properties
#Ustalamy gdzie i jakie komunikaty beda wywolywane CA-konsola 
log4j.rootLogger=DEBUG, CA, FA

#Ustawienia dla konsoli
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=%-4r [%t] %-5p  %x - %m%n

#Ustawienie dla pliku z logami
log4j.appender.FA=org.apache.log4j.FileAppender
log4j.appender.FA.File=plikzlogami.log
log4j.appender.FA.layout=org.apache.log4j.PatternLayout
log4j.appender.FA.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

#Ustawiamy poziom od ktorego komunikaty maja pojawiac sie w pliku
log4j.appender.FA.Threshold = WARN
Wyniki jakie otrzymamy w pliku. Plik „plikzlogami.log” stworzyliśmy w katalogu z projektem
1    [main] WARN  logi.Log4jTest  - Info - WARN
1    [main] ERROR logi.Log4jTest  - Info - ERROR
2    [main] FATAL logi.Log4jTest  - Info - FATAL
Hierarchia komunikatów loggera od najmniej ważnego:
  • TRACE,
  • DEBUG,
  • INFO,
  • WARN,
  • ERROR,
  • FATAL

Wyjaśnienie konwencji zapisu:
''%d %5p %c{2}:%L - %m%n''
  • %d – czas wystąpienia zdarzenia
  • %p – poziom zdarzenia, (5 - liczba znakow dla pola)
  • %c – nazwa loggera zdarzenia (liczba hierarchii od końca {x})
  • %L – numer linii w pliku źrodłowym
  • %m – opis zdarzenia
  • %n – sparator linii zależy od platformy (\n lub \r\n)

sobota, 15 października 2011

Testowanie programu – JUnit

Testy jednostkowe to testy pojedynczych, najmniejszych metod w programie. Testowanie polega na porównaniu wyników jakie zwróci metoda (nie chodzi tylko o return, ale o wszystko na co ma wpływ, czyli np. czy dobrze zapisze wartość do bazy, czy usunie obiekt z listy) z wynikami oczekiwanymi zawartymi w teście. Przed rozpoczęciem testu można przygotować jego środowisko, czyli warunki w jakich metoda ma pracować (stworzeni obiektów, połączeń z bazą z których może korzystać).
Klasy testowe JUnit to zwykłe klasy, w których za pomocą specjalnych adnotacji określa się testy.

Podstawowe adnotacje: 
  • @BeforeClass – metoda wykonywana raz przed wszystkimi testami,
  • @Before – metoda wykonywana przed każdym testem,
  • @Test – oznaczenie testu,
  • @After – metoda wykonywana po każdym teście,
  • @AfterClass –metoda wykonywana raz po wszystkich testach,
  • @Ignore – wyłączenie testu,


Podstawowe metody używane w testach:
  • fail(wiadomość); – informuje, że metoda jest niepoprawna, zwraca komunikat „wiadomość”
  • assertTrue(warunek); - test poprawny gdy warunek = true,
  • assertTrue(wiadomość, warunek); - jeżeli warunek = true test jest poprawny, inaczej zwróci błąd i komunikat „ wiadomość”
  • assertEquals(wiadomość, spodziewane, aktualne); - porównuje wartość spodziewaną z wartością aktualną, porównuje kolejne wartości w listach, przy będzie wyświetli dodatkowo wiadomość,
  • assertEquals(wiadomość, spodziewane, aktualne, tolerancja); - porównuje wartości float i double i jeżeli róznica miedzy nimi nie jest większa niż tolerancja test jest pozytywny,
  • assertNull(wartość); – jeżeli wartość = null test jest pozytywny,
  • assertNotNull(„wiadomość”,wartość); – jeżeli wartość != null test jest pozytywny, jeżeli wartość = null wyświetli wiadomość,
  • assertSame(wiadomość, oczekiwana, aktualna); – sprawdza czy obiekt oczekiwany i aktualny jest takiego samego typu (czyli np. String int), jeżeli nie wyświetli wiadomość
  • assertNotSame(wiadomość, oczekiwana, aktualna); – sprawdza czy obiekt oczekiwany i aktualny jest różnego typu (czyli np. String int), jeżeli nie wyświetli wiadomość


Cechy testów:
  • Automatyzacja – uruchamianie testów musi być łatwe,
  • Kompletność – należy testować wszystko co może zawieść,
  • Powtarzalność – wielokrotne wykonanie testu daje te same wyniki,
  • Niezależność – od środowiska i innych testów,


Nazewnictwo:
  • KlasaPierwszaTest - Klasa w której testujemy klasę o nazwie „KlasaPierwsza”,
  • testMetodaPierwsza – metoda, która testuje metodę o nazwie „metodapierwsza”


Przykład:
Dla interfejsu:
public interface UserService {
class IllegalUsernameException extends RuntimeException {}
void addUser(User user) throws IllegalUsernameException;
User getUser(String username) throws IllegalUsernameException;
} 
Klasa wygenerowana automatycznie w Eclipse (ppm na nazwę klasy w menagerze -> New -> JUnit Test Case):
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class UserServiceTest {
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    }
    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }
    @Before
    public void setUp() throws Exception {
    }
    @After
    public void tearDown() throws Exception {
    }
    @Test
    public void testAddUser() {
                        fail("Not yet implemented");
    }
    @Test
    public void testGetUser() {
                        fail("Not yet implemented");
    }
}
Klasa testowa:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import org.junit.Before;
import org.junit.Test;
public class UserServiceTest {
    @Before
    public void setUp() throws Exception {
                        ArrayList<User> listUsers = Main.getListUsers();
                        listUsers = new ArrayList<User>();
                        Main.setListUsers(listUsers);
    }
    @Test
    public void testAddUser() {  
                        UserServiceImpl impl = new UserServiceImpl();
                        User u1 = new User();
                        impl.addUser(u1);
                        ArrayList<User> listUsers = Main.getListUsers();
                        assertNotNull( listUsers.get(0));
    }
    @Test
    public void testGetUser() {
                        UserServiceImpl impl = new UserServiceImpl();
                        User u1 = new User();
                        String imie = "kkk";
                        u1.setName(imie);
                        impl.addUser(u1);
                        User u2 = impl.getUser(imie);
                        ArrayList<User> listUsers = Main.getListUsers();
                        assertTrue( listUsers.get(0)==u2);
    }
}

czwartek, 6 października 2011

Skróty klawiszowe w Eclipse

Skróty klawiszowe zdecydowanie ułatwiają prace przy kodzie. Oto moje propozycje do codziennego stosowania:
Ctrl+Spacja – czyli auto-uzupełnianie tekstu. Chyba najważniejszy skrót w historii :) Bardzo ułatwia pisanie. Nie trzeba martwić się o literówki. Wystarczy wpisać początek interesującej nas formułki i po naciśnięciu tej kombinacji wyświetlona zostanie lista propozycji dokończenia tekstu. Dodatkowo pozwala szybko wpisywać całe często używane komendy np.:
syso + Ctrl+spacja   > System.out.println()

Inne ciekawe skróty:
Ctrl+/ - zakomentowanie zaznaczonych linii za pomocą "//"
Ctrl+Shift+F – formatuje kod według zapisanych wcześniej reguł
Ctrl+D - usunięcie całej linii w której znajduje się kursor (bez konieczności jej zaznaczenia)
Ctrl+Shift+O - porządkowanie importów
Ctrl+F6, Ctrl+E - wyświetla okno dzięki któremu możemy przeskoczyć no innego otwartego edytora. 

Poniżej przedstawiam listę wszystkich skrótów klawiszowych w Eclipse znalezioną na:

Aby zmienić, bądź ustawić własne skróty klawiszowe należy wybrać:
Windows › Preferences › General › Keys, wybrać Command, który chcemy ustawić i w polu Binding wpisać skrót.
Dla przykładu ustawiłem skrót do automatycznego generowania Getterów i Setterów dla istniejących pól jako Alt+Shift+S.