• Come un abito cucito su misura, i nostri progetti software uniscono le potenzialità di tecnologie innovative alle specifiche esigenze del cliente.

    Showcase progetti
  • Analizziamo e razionalizziamo con il cliente i processi e le attività della propria azienda, per poi seguirlo nella scelta delle giuste strategie IT da adottare.

    Le nostre competenze
  • Crediamo nelle potenzialità di un percorso formativo che unisca forti basi teoriche e metodologiche ad una continua applicazione pratica di quanto si apprende.

    Dettaglio dei corsi
  • Progettiamo e sviluppiamo sistemi e progetti basati su dispositivi mobile consumer (iPhone, Windows Phone 7 Series), industriali (Windows CE) e custom (basati su microcontrollori 8/16/32 bit).

    Approfondimenti
 

Generazione di report in PDF con il framework .NET

March 4, 2010 17:49 by f.bernabei

Spesso all’interno di applicazioni abbiamo la necessità di generare report/stampe più o meno complesse, ed in particolare molte volte l’esigenza è quella di poter generare direttamente file in formato PDF, magari senza uscire dalla nostra applicazione o generare anteprime intermedie del risultato. Per farlo ci sono svariate soluzioni e strumenti, a partire dalle suite di reportistica professionali che permettono la generazione di report molto sofisticati, fino ad arrivare a librerie che permettono la sola generazione di documenti PDF a fronte però di una complessa programmazione e composizione da codice del documento finale.

Fortunatamente dalla versione 2.0 del framework .Net è possibile utilizzare un motore di reportistica derivato dai “Microsoft SQL Server Reporting Services” e distribuito con Visual Studio che è possibile utilizzare a tale scopo. Questo componente è in realtà un visualizzatore di report con estensione rdlc (variante “locale” dei file rdl utilizzati da Reposrting Services ed in pratica un formato xml che permette di descrivere template per i report) che permette l’esportazione dei report in svariati formati, tra cui anche il PDF; vedremo che con poche righe di codice è possibile pilotare direttamente la creazione di un PDF senza dover neanche aprire il visualizzatore, con il vantaggio rispetto ad altre soluzione di avere un editor visuale nativo in Visual Studio (nel nostro caso utilizzeremo Visual Studio 2008 SP1) per la definizione del report stesso (esistono inoltre strumenti esterni in grado di editare i file rdlc che rendono ipoteticamente possibile la personalizzazione dei report in un secondo tempo da parte dei clienti stessi).

In questo articolo quindi vedremo in “stile tutorial” i vari step necessari per la realizzazione di una semplice applicazione di test che alla pressione di un bottone esegua tutte le operazioni necessarie per generare un report e salvarlo in formato PDF.

Da bravi programmatori decideremo di rendere il report completamente slegato dalla base dati e gli forniremo quello di cui ha bisogno attraverso il passaggio di oggetti DTO creati ad hoc (o magari già presenti ed utilizzati all’interno della nostra applicazione). Nel progetto di esempio creiamo una classe che rappresenta un ipotetico articolo da stampare con il codice seguente:

   1: public class ReportDataDTO
   2: {
   3:     public int IdArticolo { get; set; }
   4:     public string Descrizione { get; set; }
   5:     public string Dettagli { get; set; }
   6:     public double Costo { get; set; }
   7:     public byte[] Immagine { get; set; }
   8: }

A questo punto possiamo aggiungere al progetto anche il file rdlc, cioè il template del report che utilizzeremo poi per la stampa. Per farlo basta aggiungere un nuovo item e scegliere dalla categoria “Reportings” il template per i report rdlc (nel mio caso l’ho chiamato ReportDemo.rdlc). Appena inserito il nuovo item si dovrebbe aprire automaticamente in Visual Studio 2008 l’editor dei report: dovreste avere qualcosa tipo:

Empty_rdlc
Il prossimo passo consiste nell’associare al template del report il DTO che sarà utilizzato come contenitore per lo scambio dei dati, nel nostro caso la classe ReportDataDTO precedentemente creata. Per farlo è necessario aggiungere una nuova sorgente dati (Menu Data –> Add New Data Source…) attraverso l’apposito wizard al quale dovremo dire di utilizzare un oggetto come sorgente dati e nella schermata successiva selezionare esplicitamente il tipo ReportDataDTO che abbiamo precedentemente creato.

wizard_dati_2
Una volta selezionata la nostra classe DTO possiamo premere direttamente il tasto “Finish” per completare l’operazione di aggiunta sorgente dati. Ora nella finestra “Data Sources” del report (Visualizzabile dal menu Data –> Show data Sources) avremo la sorgente reportDataDTO con l’elenco dei campi pubblici disponibili ed utilizzabili nel report. Non ci resta altro che “creare” graficamente il report aggiungendo con il semplice trascinamento i campi disponibili nell’area di lavoro dell’editor. Ecco il mio risultato:

rdlc_final

La parte di puro “design” è giunta al termine, ora dobbiamo iniziare a sporcarci un po’ le mani con del buon codice C#.

Per prima cosa ritocchiamo leggermente le impostazioni di compilazione del file rdlc all’interno del progetto Visual Studio. Per default i file rdlc vengono “inglobati” nell’eseguibile/libreria come risorse di progetto, mentre in molti casi è preferibile a mio parere lasciare il template esterno (e caricarlo “al volo” per la generazione del report) in modo da permettere correzioni o semplici modifiche estetiche al template senza la necessità di dover ricompilare e ridistribuire l’intero binario dell’applicazione. Per farlo dobbiamo selezionare il file rdlc nel ”Solution Explorer” di VS2008 e modificare alcune proprietà dalla apposita toolbox “Properties”; in particolare bisogna cambiare la proprietà “Build Action” dal default “Embedded Resource” in “None”. Inoltre impostiamo anche la proprietà “Copy to Output Directory” al valore “Copy if newer” in modo da fare una copia del file nella cartella dei binari ad ogni compilazione. Ecco le modifiche finali delle proprietà del file rdlc:

rdlc_prop
Ora siamo pronti per la generazione del report. Nell’applicazione del progetto di esempio aggiungiamo un bottone e nel gestore dell’evento “Click” di quest’ultimo iniziamo le operazioni per la generazione del PDF.

Per prima cosa simuliamo il caricamento dei dati da una ipotetica sorgente dati implementando un metodo che restituisca una lista di oggetti DTO, nel nostro caso sarà in realtà solamente uno. Il codice è banale e non fa altro che creare un’istanza della classe DTO, valorizzarne le proprietà (i dati utilizzati nell’esempio tra l’altro sono di un libro che vi consiglio di leggere Open-mouthed) e restituuirlo:

   1: private ReportDataDTO[] estraiDati()
   2: {
   3:     byte[] rawImg;
   4:     using (System.Drawing.Image img = System.Drawing.Bitmap.FromFile("RocketSurgeryCover.jpg"))
   5:     {
   6:         using (MemoryStream ms = new MemoryStream())
   7:         {
   8:             img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
   9:             rawImg = ms.ToArray();
  10:         }
  11:     }
  12:  
  13:     ReportDataDTO dto = new ReportDataDTO
  14:     {
  15:         IdArticolo = 9847,
  16:         Descrizione = "Rocket Surgery Made Easy: The Do-It-Yourself Guide to Finding and Fixing Usability Problems",
  17:         Dettagli = "It's been known for years that usability testing can dramatically...",
  18:         Costo = 21.99,
  19:         Immagine = rawImg
  20:     };
  21:     
  22:     return new ReportDataDTO[] { dto };
  23: }

Ora si passa alla generazione vera e proprio utilizzando la classe LocalReport che permette di elaborare un report rdlc ed effettuarne la renderizzazione. I passi da seguire sono il caricamento del file rdlc esterno impostando la proprietà “ReportPath”, aggiunta della sorgente dati da utilizzare, esecuzione del render specificando i parametri per generare un file in formato PDF ed infine il salvataggio dei dati risultanti dall’operazione precedente su file system, ed il gioco è fatto.

Il codice seguente (metodo “generaReport” richiamato dal gestore d’evento del bottone) implementa esattamente i passi appena descritti:

   1: private void generaReport()
   2: {
   3:     // Simulazione estrazione dati da una qualsiasi sorgente
   4:     ReportDataDTO[] dtoList = estraiDati();
   5:  
   6:     // Creazione istanza LocalReport e caricamento template rdlc e dati
   7:     LocalReport lr = new LocalReport();
   8:     lr.ReportPath = "ReportDemo.rdlc";
   9:     lr.DataSources.Add(new ReportDataSource("DemoReportPDF_ReportDataDTO", dtoList));
  10:  
  11:     // Elaborazione e render del report in formato PDF
  12:     Warning[] warnings;
  13:     string[] streamids;
  14:     string mimeType, encoding, extension;
  15:     string deviceInfo = "<DeviceInfo>" +
  16:                         "  <OutputFormat>PDF</OutputFormat>" +
  17:                         "</DeviceInfo>";
  18:  
  19:     byte[] bytes = lr.Render("PDF", deviceInfo, out mimeType, out encoding, out extension, out streamids, out warnings);
  20:  
  21:     // Salvataggio del report generato su file system
  22:     string reportFileName = Guid.NewGuid().ToString() + ".pdf";
  23:     using (MemoryStream ms = new MemoryStream(bytes))
  24:     {
  25:         using (FileStream fs = new FileStream(reportFileName, FileMode.Create))
  26:         {
  27:             fs.Write(bytes, 0, bytes.Length);
  28:             fs.Close();
  29:         }
  30:     }
  31:  
  32:     MessageBox.Show("Report generato correttamente: " + reportFileName);
  33: }

Le uniche due note da sottolineare sono:

- Nella fase di aggiunta dei dati deve essere specificato il nome con cui la sorgente dati è configurata all’interno dell’rdlc. Questo valore è presente (e modificabile) andando nel designer del report ed accedendo dal menu “Report” alla finestra “Report Data Sources”.

- La classe LocalReport fa parte del ridistribuibile Microsoft Report Viewer (installato da Visual Studio). Per poter ridistribuire l’applicazione in un PC con il solo framework .Net installato c’è bisogno anche di questo pacchetto scaricabile gratuitamente dal sito MSDN (il download si riferisce alla versione relativa al framework 3.5 SP1). Per l’utilizzo nel progetto è necessario aggiungere un riferimento all’assembly “Microsoft.ReportViewer.WinForms”.

E con questo è tutto, non resta che eseguire l’applicazione, premere il pulsante e se tutto è andato come dovrebbe, nella cartella di esecuzione del progetto dovrebbe comparire per incanto un file PDF più o meno così

pdf_result

 

File allegati:


Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Test della UI di una applicazione con Selenium

September 4, 2009 15:17 by F.Bernabei

Al giorno d’oggi predisporre dei test automatici sulle applicazioni che sviluppiamo è divenuto un requisito fondamentale per vari motivi. Primo fra tutti per evitare che a seguito di modifiche al software (per introdurre nuove funzionalità o correzione di bug) si possa in modo automatico, verificare che tutte le funzionalità precedenti (o meglio tutte quelle precedentemente messe sotto test e verificate) continuino a funzionare in modo corretto e che non si siano quindi introdotti ulteriori bug con le modifiche apportate (questi sono detti test di [non] regressione).

In questo articolo parleremo in particolare di test automatizzati dell’interfaccia utente, argomento che ho già introdotto in un mio post precedente pubblicato su DotNetUmbria.org a cui si può far riferimento per un’introduzione di base.
A differenza degli unit test, l’automatizzazione della UI permette di fare controlli ad un “livello più alto” ed integrato, utile per testare in modo ripetitivo un intero caso d’uso della nostra applicazione o aggiungere un set di test completo ad applicazioni già esistenti.
Come illustrato nell’articolo introduttivo appena menzionato, esistono vari framework per raggiungere il nostro scopo  e sicuramente due dei più utilizzati sono WatIn e SelniumHQ (di cui parleremo in modo approfondito nel prosegui dell’articolo). Si tratta di framework che permettono il test di applicazioni WEB come vedremo in seguito, ma va segnalato che esistono soluzioni analoghe anche per il test di applicazioni Windows, come l’ottima Microsoft UI Automation  per il test di applicazioni Windows Presentation Foundation che magari potrebbe essere argomento per un articolo futuro.

Ma torniamo allo scopo principale di questo post, ossia vedere un esempio concreto di implementazione di un test di un’applicazione reale implementato mediante l’uso di Selenium. Come caso d’uso per provare le funzionalità di base del framework ho scritto una piccola applicazione ASP.NET che banalmente permette di inserire del testo in una casella di testo ed alla pressione di un bottone riporta il testo inserito in una etichetta. Il risultato finale in esecuzione è visibile nell’immagine seguente ed il codice è scaricabile direttamente dal link presente al termine dell’articolo.

uitestwebapp

Come si evince dall’immagine in realtà ci sono due bottoni che eseguono l’operazione appena descritta. Questo per poter provare diversi approcci di test in quanto in un caso l’aggiornamento dell’etichetta viene fatto con codice lato server ed il bottone esegue quindi un postback (all’interno di un UpdatePanel Ajax) e nel codice C# della pagina viene aggiornato il testo.
Nel secondo caso invece il lavoro viene eseguito completamente lato client con del codice Javascript, facendo uso anche del comando alert per visualizzare una finestra di messaggio in modo da vedere come interagire con questo elemento in fase di test.

Eccoci ora arrivati all’implementazione vera e propria dei test. Come anticipato in questo caso utilizzeremo SeleniumHQ che mette a disposizioni diversi strumenti per raggiungere il nostro scopo tra cui i principali sono:

Selenium IDE: Un ambiente integrato distribuito come plug-in per FireFox per la creazione rapida di test e suite di test. I test creati possono essere salvati in diversi formati ed editati direttamente dall’IDE ed essere rieseguiti in qualsiasi momento.

Selenium Remote Control (RC): Un insieme di librerie e tools per scrivere e pilotare i test direttamente da codice. Fornisce un insieme di librerie utilizzabili da svariati linguaggi di programmazione (C#, Java, PHP, Ruby e altri) e permette di eseguire i test praticamente su tutti i browser più diffusi.

Selenium Grid: Un sistema per “espandere” Selenium RC e consentire l’esecuzione dei test in parallelo su server multipli.

Partiamo con Selenium IDE in modo da poter subito prendere contatto con le possibilità offerte dal framework. Dopo averlo scaricato ed installato lo troveremo in FireFox nel menu “Tools –> Selenium IDE” e da qui possiamo lanciarlo. SeleniumIDE

Una volta aperto, l’IDE si presenterà più o meno come in figura e già in modalità di registrazione attiva (identificabile dal bottone con “pallino rosso” premuto nella parte destra della toolbar in alto), il che significa che ogni azione che noi faremo nel browser da cui lo abbiamo aperto, verrà registrata nello script corrente e potrà essere riprodotta in modo automatico rieseguendo il test in seguito. Non ci resta che inserire nella barra degli indirizzi di FireFox l’URL a cui raggiungere l’applicazione (nel nostro caso http://localhost:53771/ visto che stiamo effettuando il test di una applicazione in esecuzione in Visuall lStudio e che gira quindi su una porta creata dinamicamente del Web Development Server), premere invio per avviare la navigazione ed eseguire tutte le azioni che devono essere registrate per essere poi ripetute in seguito. Per esempio i seguenti passi:

  1. Scrivere qualcosa nella casella di testo (nell’esempio ho inserito “Bernabei”)
  2. Premere sul bottone con etichetta “Saluta via javascript”
  3. Premere OK sull’alert che appare
  4. Verificare che sull’etichetta appaia il testo “Ciao Bernabei!”

Quest’ultimo punto ovviamente non corrisponde ad un’interazione che facciamo con il browser, quindi dobbiamo “spiegare” a Selenium come farlo e questo si traduce banalmente nel premere il tasto destro del mouse sull’etichetta che vogliamo controllare. Nel menu contestuale di FireFox appariranno anche tutte le azioni che Selenium può “eseguire” su quel determinato elemento, fra le quali quella che ci verifyTextPresentinteressa che è “verifyTextPresent”. Selezionando il comando viene aggiunto nello script correntemente in registrazione l’istruzione richiesta che effettua il controllo specificato al passo numero 4.

Ora lo script è pronto per essere salvato per rieseguirlo in futuro (per farlo basta caricarlo nell’IDE e premere l’apposito pulsante “Play” della toolbar) o editato manualmente all’interno dell’ambiente. In quest’ultimo caso è possibile farlo aggiungendo i comandi alla lista visualizzata, specificando appunto il comando da eseguire selezionabile da una lista molto ampia di azioni possibili (il set di comandi disponibili è chiamato “selenese”), il target ossia l’elemento della pagina a cui il comando si riferisce ed il valore se necessario per il comando specifico. Alternativamente si può modificare lo script agendo direttamente sul “sorgente” accessibile selezionando il tab “Source” dell’IDE e modificando manualmente i comandi che verranno eseguiti dallo script (questa modalità ovviamente richiede la conoscenza dei comandi messi a disposizione dal framework in quanto non è presente un qualcosa tipo IntelliSense che può aiutare a compilare lo script.

Prima di concludere vale la pena dare uno sguardo al sorgente dello script che per default viene rappresentato usando una sintassi HTML. In pratica si tratta di un HTML contenente un tag TABLE in cui ogni riga TR corrisponde ad un comando da eseguire e contiene tre celle TD che rappresentano comando, target e valore.

Lo script appena creato viene rappresentato in HTML nel modo seguente:

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   3:  
   4: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   5: <head profile="http://selenium-ide.openqa.org/profiles/test-case">
   6:     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
   7:     <link rel="selenium.base" href="http://localhost:53771/" />
   8:     <title>New Test</title>
   9: </head>
  10:  
  11: <body>
  12: <table cellpadding="1" cellspacing="1" border="1">
  13:     <thead>
  14:         <tr><td rowspan="1" colspan="3">New Test</td></tr>
  15:     </thead>
  16:     <tbody>
  17:         <tr>
  18:             <td>open</td>
  19:             <td>/</td>
  20:             <td></td>
  21:         </tr>
  22:         <tr>
  23:             <td>type</td>
  24:             <td>txtNome</td>
  25:             <td>Bernabei</td>
  26:         </tr>
  27:         <tr>
  28:             <td>click</td>
  29:             <td>//input[@value='Saluta via javascript']</td>
  30:             <td></td>
  31:         </tr>
  32:         <tr>
  33:             <td>assertAlert</td>
  34:             <td>Stai per essere salutato...</td>
  35:             <td></td>
  36:         </tr>
  37:         <tr>
  38:             <td>verifyTextPresent</td>
  39:             <td>Ciao Bernabei!</td>
  40:             <td></td>
  41:         </tr>
  42:     </tbody>
  43: </table>
  44: </body>
  45: </html>

Dallo stesso IDE è possibile visualizzare lo script in un altro formato riutilizzabile poi da Selenium RC per eseguire il test direttamente da codice. Ad esempio scegliendo il formato C# la rappresentazione dello stesso script è la seguente:

   1: using System;
   2: using System.Text;
   3: using System.Text.RegularExpressions;
   4: using System.Threading;
   5: using NUnit.Framework;
   6: using Selenium;
   7:  
   8: namespace SeleniumTests
   9: {
  10:     [TestFixture]
  11:     public class Untitled
  12:     {
  13:         private ISelenium selenium;
  14:         private StringBuilder verificationErrors;
  15:         
  16:         [SetUp]
  17:         public void SetupTest()
  18:         {
  19:             selenium = new DefaultSelenium("localhost", 4444, "*chrome", "http://localhost:53771/");
  20:             selenium.Start();
  21:             verificationErrors = new StringBuilder();
  22:         }
  23:         
  24:         [TearDown]
  25:         public void TeardownTest()
  26:         {
  27:             try
  28:             {
  29:                 selenium.Stop();
  30:             }
  31:             catch (Exception)
  32:             {
  33:                 // Ignore errors if unable to close the browser
  34:             }
  35:             Assert.AreEqual("", verificationErrors.ToString());
  36:         }
  37:         
  38:         [Test]
  39:         public void TheUntitledTest()
  40:         {
  41:             selenium.Open("/");
  42:             selenium.Type("txtNome", "Bernabei");
  43:             selenium.Click("//input[@value='Saluta via javascript']");
  44:             Assert.AreEqual("Stai per essere salutato...", selenium.GetAlert());
  45:             try
  46:             {
  47:                 Assert.IsTrue(selenium.IsTextPresent("Ciao Bernabei!"));
  48:             }
  49:             catch (AssertionException e)
  50:             {
  51:                 verificationErrors.Append(e.Message);
  52:             }
  53:         }
  54:     }
  55: }

Da notare che se l’IDE viene impostato per rappresentare lo script nei formati per Selenium RC non sarà più possibile utilizzare la visualizzazione di default dell’IDE stesso, quella in formato tabellare che permette di aggiungere comandi selezionandoli da una ComboBox.

L’utilizzo dell’IDE consente dunque di creare in modo rapido delle suite di test (è possibile caricare più script alla volta nell’IDE ed eseguirli tutti in una volta) da rieseguire all’occorrenza per verificare il comportamento della UI. Se questo non fosse sufficiente, o se si volesse organizzare un test per controllare il funzionamento dell’applicazione su più di un browser anche diverso da FireFox, basterà utilizzare le API messe a disposizione dal Remote Control per personalizzare in modo estremamente capillare il comportamento del test.

In allegato a questo articolo è possibile scaricare i sorgenti del progetto WEB di test utilizzato e due script che “utilizzano” in modo diverso l’applicazione testandone una volta il comportamento implementato con il postback asincrono e l’altra come nell’esempio descritto in precedenza che fa uso di javascript.

Buon test a tutti Winking!

 

File allegati:

 


Currently rated 4.5 by 2 people

  • Currently 4.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Utilizzo di Twitter da un’applicazione .NET

August 28, 2009 15:39 by F.Bernabei

Per un piccolo progetto interno abbiamo la necessità di interfacciarci con twitter ed eseguire alcune operazioni comuni come ad esempio ottenere i tweet che stiamo seguendo oppure aggiornare il nostro stato.

Dopo un rapido sguardo alle API messe a disposizione ho pensato: “possibile che non ci sia qualcuno che ha già scritto una bella libreria per utilizzare codeste API da .NET?”. Detto fatto, con l’aiuto del prode Google sono partito alla ricerca ed ho trovato tweet#, bellissima libreria tipizzata e con interfaccia fluente che mette a disposizione (credo) tutte le funzionalità accessibili con le API native (a cui ovviamente si appoggia).

Di seguito un esempio di utilizzo per ottenere la lista di tweet seguiti da uno specifico utente:

   1: var twitter = FluentTwitter.CreateRequest()
   2:     .AuthenticateAs("username", "password")
   3:     .Statuses().OnFriendsTimeline()
   4:     .AsJson();
   5:  
   6: IEnumerable<TwitterStatus> response = twitter.Request().AsStatuses();

Si tratta in conclusione di una libreria ben fatta e molto potente per aggiungere il supporto a Twitter al nostro software… ora non resta che utilizzarla.


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5