The Hitchhiker's Guide to testable code



Похожие документы
Progettazione : Design Pattern Creazionali

Sviluppo software guidato dal testing. metodologie e strumenti

Modulo 4: Ereditarietà, interfacce e clonazione

Programmazione Orientata agli Oggetti in Linguaggio Java

12 - Introduzione alla Programmazione Orientata agli Oggetti (Object Oriented Programming OOP)

Tecnologia e Applicazioni Internet 2011/12

Main System Monitor Keyboard

1 Applicazione J2EE sul SAP WAS con SAP NWDS

1 EJB e Portal Component Object

Object Oriented Software Design

Chat. Si ha un server in ascolto sulla porta Quando un client richiede la connessione, il server risponde con: Connessione accettata.

Object Oriented Programming

Introduzione JDBC interfaccia java.sql driver caricare i driver

Gli EJB offrono vari vantaggi allo sviluppatore di una applicazione

Test di unità con JUnit4

Programmazione Java Avanzata Spring - JDBC

Concetto di Funzione e Procedura METODI in Java

Uso di JUnit. Fondamenti di informatica Oggetti e Java. JUnit. Luca Cabibbo. ottobre 2012

DESIGN PATTERNS Parte 2. Polimorfismo Pure Fabrication Simple Factory/Concrete Factory Factory Method Abstract Factory Protect Variations + Reflection

Operazioni di input/output. Prof. Francesco Accarino IIS Altiero Spinelli Via Leopardi 132 Sesto San Giovanni

UML Diagrammi delle classi. UML Diagramma classi 1

Uno dei pregi di Java è quello di integrare la documentazione con il codice stesso Formato dei commenti:

Guida alla configurazione della posta elettronica dell Ateneo di Ferrara sui più comuni programmi di posta

!"#$%&&'()#*%+%+!"#$"',,'()#*%+ -")%*&'&'+'$.)+-$$%&&) !"#$%&&'(%)'*+%",#-%"#.'%&'#/0)-+#12"+3,)4+56#7+#.')8'9

DESIGN PATTERN CREAZIONALI INGEGNERIA DEL SOFTWARE INTRODUZIONE SINGLETON. Scopo dei design pattern creazionali

Java threads (2) Programmazione Concorrente

Programmazione a Oggetti Modulo B

L ambizione dei design pattern (letteralmente schemi di programmazione) è quella di offrire soluzioni a problemi ricorrenti che facilitano lo

SOMMARIO Coda (queue): QUEUE. QUEUE : specifica QUEUE

Realizzazione di una classe con un associazione

Modulo 4 Il pannello amministrativo dell'hosting e il database per Wordpress

7 Esercitazione (svolta): Callback. Polling. Java RMI: callback. Server. Server. Client. Client. due possibilità:

Indice. Ingegneria dei requisiti e gestione agile. User-Centered Development Esempi di artefatti. Domain Driven Design. Design for Testability

Programmazione Java: Variabili membro, Metodi La parola chiave final

Siti web centrati sui dati Architettura MVC-2: i JavaBeans

Il Web-Service SDMX dell ISTAT

Basi di dati e Web (Moduli: Laboratorio e Siti Web centrati sui Dati) Prova scritta del 14 luglio 2008

Corso di Laurea Triennale in Ingegneria Informatica. Corso di Ingegneria del software A. A Marina Mongiello

Client e Server comunicano tramite il protocollo SOAP.

I file di dati. Unità didattica D1 1

Poca documentazione: uso di Story Card e CRC (Class Responsibility Collabor) Collaborazione con il cliente rispetto alla negoziazione dei contratti

Organizzazione della lezione. Lezione 18 Remote Method Invocation - 6. (con callback) L accesso al registry per il rebind()

Oggetti Lezione 3. aspetti generali e definizione di classi I

Architettura MVC-2: i JavaBeans

Specifica i tipi di oggetti a creare, utilizzando un istanza prototipo, e crea nuove istanze tramite la copia di questo prototipo.

Fasi del ciclo di vita del software (riassunto) Progetto: generalità. Progetto e realizzazione (riassunto)

Progettazione della componente applicativa

UML Component and Deployment diagram

Esercitazione sui Design Pattern

Organizzazione della lezione. 15. Java Remote Method Invocation (3) Lo schema del Factory Design Pattern - 1. Factory design pattern

Laboratorio di Sistemi Prototipo autenticazione utente Jsp [Java]

Sistema di Accesso Unico ai Bandi

Soluzione dell esercizio del 2 Febbraio 2004

USARE JOOMLA 1.7/2.5 per gestire il vostro sito.

Metodologie di progetto Estensione di classi Implementazione di interfacce Composizione

dall argomento argomento della malloc()

La gestione dell input/output da tastiera La gestione dell input/output da file La gestione delle eccezioni

Lavorare con MySQL Parte Seconda.

19. Introduzione al multi-threading

Progetto di Ingegneria del Software 2. SWIMv2

Guida all uso della piattaforma. portale Weblog & Podcast del MIUR COME UTILIZZARE AL MEGLIO L AMMINISTRAZIONE DEL BLOG

GUIDA PER IL NUOVO SITO DI GESTIONE SERVIZI

Office Web Components in programmi C# da

Il Pattern PROXY. Ex presentazione realizzata dallo studente Paolo Melchiori (matricola 65734) nell a.a

Non si deve fare ALCUN riferimento alla parte specifica di JDBC.

Brochure Internet. Versione The Keyrules Company s.r.l. Pagina 2 di 8

f(x) = 1 x. Il dominio di questa funzione è il sottoinsieme proprio di R dato da

Le Novità Repository (depositi di files) File Legacy del Corso Domande con punteggio negativo. prof. Tommasini Nicola ITIS G.

Ottava Esercitazione. introduzione ai thread java mutua esclusione

Joomla: Come installarlo e come usarlo. A cura di

JNDI. Massimo Merro Programmazione di Rete 214 / 229

Inizializzazione, Assegnamento e Distruzione di Classi

1 JSPDynPage, componenti portale e Java Server Pages

GESTIONE DEI PROCESSI

CORSO DI ALGORITMI E PROGRAMMAZIONE. JDBC Java DataBase Connectivity

Introduzione. Java. Composizione. Esempio -- composizione. G. Prencipe È qualcosa che abbiamo già visto varie volte

GB informazioni e freeware

Corso di Informatica Modulo T3 B2 - Database in rete

01/05/2013 Istruzioni per l installazione

La strada per sviluppare più rapidamente: Unit Test & Continuous Integration

LAVORI ESTIVI DI INFORMATICA PER LA CLASSE IV Sez. Ainf (Prof. Tessore Luca)

Generazione Automatica di Asserzioni da Modelli di Specifica

Reflection in Java. Linguaggi Corso M-Z - Laurea in Ingegneria Informatica A.A

Configurazione di base. Dott. Doria Mauro

Funzioni in C. Violetta Lonati

SISTEMI OPERATIVI. Sincronizzazione in Java (Monitor e variabili condizione in Java)

GUIDA UTENTE WEB PROFILES

Quando si sa chiaramente come si deve comportare l applicazione si può analizzare una possibile soluzione applicativa.

Design Pattern in Java

Luca Mari, Sistemi informativi applicati (reti di calcolatori) appunti delle lezioni. Architetture client/server: applicazioni server

SAPIENZA Università di Roma, Facoltà di Ingegneria

Sviluppo di processi per l automatizzazione del testing per applicazioni Android

Mini guida all utilizzo del nuovo sistema on-line di Ciessevi

Транскрипт:

The Hitchhiker's Guide to testable code semplici regole per scrivere codice semplice da testare Davide Cerbo - davidecerbo@gmail.com - JUG Roma Nicola Raglia - n.raglia@gmail.com - JUG Roma

Non parleremo di... XP Programming Test-Driven Development Agile Scrum etc etc

...ma parleremo di... come scrivere codice TESTABILE perchè l'unico modo per applicare le metodologie dette in precedenza è scrivere i TEST UNITARI e l'unico modo per scriverli è produrre codice TESTABILE

Definizioni assortite Test: processo atto ad individuare carenze funzionali e non funzionali durante la fase di sviluppo del software. Test Unitario: è un test atto a verificare una componente elementare del software possibilmente in termini di isolamento dalle dipendenze Refactoring: è il processo che prevede una ristrutturazione del codice modificando il meno possibile le interfacce

Ancora definizioni assortite Design Pattern: soluzione progettuale generale a un problema ricorrente Mock Object: oggetti destinati a simulare il comportamento di oggetti reali. Durante il test con i mock object abbiamo: o creazione mock o definizione del comportamento del mock object o esecuzione del test o verifica del comportamento del mock object

Esempio di codice brutto

Iniziamo dal costruttore public RubricaImpl(Properties properties, ApplicationContext applicationcontext) { this.user = applicationcontext.getauthenticationcontext().getuser(); this.url = properties.getproperty("url"); this.username = properties.getproperty("username"); this.password = properties.getproperty("password"); try { this.connection = DriverManager.getConnection(url, username, password); catch (SQLException e) { //gestione eccezione this.database = new DatabaseImpl(connection);

Il nostro primo (non) Unit Test public void testconstructor() throws Exception { Properties properties = new Properties(); properties.load(new FileInputStream("database.properties")); ApplicationContext applicationcontext = ApplicationContext.getContext(); Rubrica rubrica = new RubricaImpl(properties, applicationcontext); con i Mock Objects: public void testconstructor() throws Exception { Properties properties = new Properties(); properties.setproperty("user", "dbuser"); properties.setproperty("password","dbpassword"); properties.setproperty("url", "jdbc:db:///test"); ApplicationContext applicationcontext = createmock(applicationcontext.class); AuthenticationContext authcontext = createmock(authenticationcontext.class); expect(applicationcontext.getauthenticationcontext()).andreturn(authcontext); expect(authcontext.getuser()).andreturn(createmock(user.class)); replay(authcontext, applicationcontext); Rubrica rubrica = new RubricaImpl(properties, applicationcontext); verify(authcontext, applicationcontext);

Rispettiamo la legge public RubricaImpl(String url, String username, String password, User user) { this.user = user; this.url = url; this.username = username; this.password = password; Connection connection=drivermanager.getconnection(url,username,password); this.database = new DatabaseImpl(connection); Per rispettare la legge di Demeter un oggetto può solo invocare i metodi: propri dei suoi parametri di ogni oggetto che crea delle sue variabili

Mai dire CONTEXT public RubricaImpl(Properties properties, ApplicationContext applicationcontext) { this.user = applicationcontext.getuser(); this.url = properties.getproperty("url");...... public RubricaImpl(String url, String username, String password, User user) { this.user = user; this.url = url;...... applicationcontext e properties sono oggetti di contesto quindi difficilmente testabili unitariamente e richiedono fatica aggiuntiva nel test con i mock object.

Vietato affaticare public RubricaImpl(String url, String username, String password, User user) {... this.username = username; Connection connection = DriverManager.getConnection(url,userName,password); this.database = new DatabaseImpl(connection); public RubricaImpl(String url, String username, String password, User user) {... this.username = username; this.database = DatabaseManager.getDatabase(url,userName,password); Questa è una soluzione ma non va bene perché si usa un metodo statico

Solo l'indispensabile public RubricaImpl(String url, String username, String password, User user) { this.username =username; this.database = DatabaseManager.getDatabase(url,userName,password); 2 SOLUZIONI DA EVITARE!!! public RubricaImpl(User user) { this.user = user; this.database = DatabaseSingleton.getInstance(); Ecco fatta un po' di pulizia! Non era giusto far conoscere alla Rubrica le informazioni per accedere al database! Ma è spuntato un singleton e questo è male!

Dependency Injection public RubricaImpl(Database database, User user) { this.user = user; this.database = database; Il costruttore è stato alleggerito da responsabilità non proprie. Ma ora come lo usiamo?

Pattern Abstract Factory public class RubricaFactoryImpl implements RubricaFactory { private final DatabaseFactory databasefactory; public RubricaFactoryImpl(DatabaseFactory databasefactory) { this.databasefactory = databasefactory; public Rubrica getrubrica(user user) { return new RubricaImpl(databaseFactory.getDatabase(), user); La responsabilità di creare oggetti sarà sempre data ad una Factory o ad altri pattern creazionali.

Passiamo al Database public class DatabaseFactoryImpl implements DataBaseFactory { private final Properties properties; public DatabaseFactoryImpl(Properties properties) { this.properties = properties; public Database getdatabase(){ String url = properties.getproperty("url"); String username = properties.getproperty("username"); String password = properties.getproperty("password"); Connection connection = null; try { connection = DriverManager.getConnection(url, username, password); catch (SQLException e) { //gestione eccezione return new DatabaseImpl(connection); DatabaseFactoryImpl non è testabile, andrebbe fatto ulteriore refactoring, ma il tempo è poco :(

( 1/2 ) Il Test (quasi) finale public void testconstructor() throws Exception { Database database = createmock(database.class); User user = createmock(user.class); replay(database, user); Rubrica rubrica = new RubricaImpl(database, user); verify(database, user); Non c'è bisogno di descrivere comportamento per gli oggetti mock perchè il costruttore non fa niente altro che costruire l'oggetto. Ma le factory appena create?

( 2/2 ) Il Test (quasi) finale public void testfactory() throws Exception { DatabaseFactory databasefactory = createmock(databasefactory.class); Database database = createmock(database.class); User user = createmock(user.class); expect(databasefactory.getdatabase()).andreturn(database); replay(databasefactory, user, database); RubricaFactory rubricafactory = new RubricaFactoryImpl(databaseFactory); Rubrica rubrica = rubricafactory.getrubrica(user); verify(databasefactory, user, database); assertnotnull(rubrica);

Gli obbiettivi raggiunti Single responsability Assegnare la giusta responsabilità Utilizzare la Dependency Injection Dividere il fare dal creare Evitare stati globali Design by Interface

Andiamo avanti... public void publish(){ Context context = new InitialContext(); Object reference = context.lookup("publisherservice"); PublisherEjb home = (PublishEjb)PortableRemoteObject.narrow(reference,PublishEjb.class); PublisherService publisher = home.create(); publisher.publish(this);

Testiamolo... Totalmente non testabile in termini unitari!!!

Via il Sevice Locator public RubricaImpl(Database database, User user, PublisherService publisher) { this.user = user; this.database = database; this.publisher = publisher; public void publish(){ this.publisher.publish(this); Iniettiamo una classe che abbia la responsabilità di pubblicare. Nel nostro caso lo farà tramite EJB, ma sarà semplice sostituire la tecnologia.

Ancora non è finita... public RubricaImpl(Database database, User user) { this.user = user; this.database = database; public void publishwith(publisherservice publisher){ publisher.publish(this); Passare l'oggetto PublisherService al costruttore è errato perché non è necessario al normale ciclo di vita della Rubrica, ma serve solo nel caso di una richiesta di pubblicazione

Problema solo spostato Abbiamo solo spostato il problema, infatti l'implementazione PublisherServiceEJB sarà intestabile unitariamente......ma fortunatamente la nuova specifica EJB 3.0 ci viene in aiuto eliminando il ServiceLocator Ma non è lo scopo di questo talk spiegare come :D

Il Test finale public void testpublish() throws Exception { Database database = createmock(database.class); User user = createmock(user.class); replay(database, user); Rubrica rubrica = new RubricaImpl(database, user); verify(database, user); PublisherService publisherservice = createmock(publisherservice.class); publisherservice.publish(rubrica); replay(publisherservice, user); rubrica.publishwith(publisherservice); verify(publisherservice, user);

Bibliografia Google Testing Blog http://googletesting.blogspot.com/ ( Fowler Refactoring: Improving the Design of Existing Code (Martin http://www.refactoring.com/ ( Wake Refactoring Workbook (William C. http://xp123.com/rwb/ ( Larman Applicare UML e Pattern (Craig http://www.craiglarman.com ( Pressman ) Principi di ingegneria del software http://highered.mcgraw-hill.com/sites/0072853182/ Wikipedia http://www.wikipedia.org

Strumenti utili Unit Test: www.junit.org Test code coverage: http://cobertura.sourceforge.net/ http://emma.sourceforge.net/ Testability: http://code.google.com/p/testability-explorer/ http://testabilityexplorer.org/report Mock objects: http://www.easymock.org/ http://www.jmock.org/ http://code.google.com/p/mockito/

I nostri contatti Davide Cerbo davidecerbo@gmail.com davide.cerbo@pro-netics.com http://jesty.it Nicola Raglia n.raglia@gmail.com nicola.raglia@pro-netics.com http://sourcengineering.org

Q&A Q&A