Visualizzazione post con etichetta tutorial. Mostra tutti i post
Visualizzazione post con etichetta tutorial. Mostra tutti i post

Python nose: scrivere test senza fatica per il nostro codice

Presto o tardi chi scrive codice deve fare i conti con imprevisti!
Uno dei modi per evitare sorprese e' quello di testare il codice scrivendo dei test che ne confermino la validita' di funzionamento.

Chi scrive codice in Python potra' giovarsi dalle comodita' offerte da Python Nose per scrivere test senza grossa fatica. La particolarita' di Python Nose e' che riesce a scovare le funzioni e le classi di test nel codice basandosi sul loro nome e senza bisogno di importare moduli esterni.

Per esempio...

Supposto che abbiate installato nose, andiamo a cimentarci con una funzione molto semplice ma che puo' riservare sorprese!
Guardate qua:
def fattoriale(n):
"""Funzione ricorsiva per il calcolo del fattoriale di un mnumero
"""
if n == 0:
return 1
else:
return fattoriale(n-1)*n
Che ne pensate? A prima vista sembra scritta bene, ma in realta' riserva qualche sorpresa.
Prima di tutto siamo sicuri funzioni?

Per esserne certi salviamo questa funzione in un file con estensione ".py" e aggiungiamo ad essa una prima funzione di validazione che controlli che i risultati siano corretti.
Affinche' nose si accorga della funzione di test, il suo nome dovra' contenere il prefisso "test" (geniale! :)). Il concetto e' che il test avra' successo la funzione ritornera' dei valori coerenti con quelli che sono calcolabili per altra via. Ad esempio i fattoriali dei numeri 0,1,2,3,4,5 corrispondono ai valori 1,1,2,6,24 e 120.
E' ovvio che se troviamo risultati diversi da questi significa che qualcosa nella funzione non torna.

La funzione che fa il test assomigliera' a questa:
def test_fattoriale():
"""Funzione invocata per testare la correttezza nel calcolo
"""
checks = (1,1,2,6,25,120)
for i, check in enumerate(checks):
f = fattoriale(i)
assert f == check,\
"Il fattoriale di %s e' %s" % (f, check)
Come vedete definiamo nella variabile checks i valori "corretti" e li confrontiamo con quelli che andremo a calcolare con la nostra fantastica funzione!

Il vostro file, fatto questo, assomigliera' a questo:

#!/usr/bin/env python
def fattoriale(n):
"""Funzione ricorsiva per il calcolo del fattoriale di un mnumero
"""
if n == 0:
return 1
else:
return fattoriale(n-1)*n

def test_fattoriale():
"""Funzione invocata per testare la correttezza nel calcolo
"""
checks = (1,1,2,6,25,120)
for i, check in enumerate(checks):
f = fattoriale(i)
assert f == check,\
"Il fattoriale di %s e' %s" % (f, check)
E' arrivato il momento della verita'!!!
Per lanciare il test date il comando nosetest seguito dal nome del file, ad es.:
nosetests prova.py

A questo punto dovreste scoprire che il test e' miseramente fallito!
Il motivo di questo non sta nella funzione bensi' nel test, che e' scritto male... Infatti come ci dice l'output si aspettava che il fattoriale di 4 fosse 25 (non 24 come si puo' ottenere moltiplicando i numeri interi da uno a quattro e come giustamente sostiene la funzione scritta).

Correggiamo la tupla di controllo, sostituendo 25 con 24 e rilanciamo il test. Questa volta tutto dovrebbe filare liscio.

Aggiungiamo test meno banali
Come avete visto la funziona supera brillantemente il test. Pero' fallira' quest'altro test:
def test_tipo():
"""Controlla che la funzione fattoriale ritorni un numero di tipo long
"""
for i in (0,1,2,10,200):
assert type(fattoriale(i)) == long ,\
"Il fattoriale di %s non e' di tipo long!" % i

Questo potrebbe rappresentare un problema in certi casi!
Per far passare alla funzione il test occorre modificarla in questo modo:
#!/usr/bin/env python
def fattoriale(n):
"""Funzione ricorsiva per il calcolo del fattoriale di un mnumero
"""
if n == 0:
return 1L
else:
return fattoriale(n-1)*n

Come vedete nel caso n sia 0 ritorna 1L, (prima ritornava semplicemente 1) ovvero un intero di tipo long. Questo forzera' il tipo del risultato ritornato dalle altre iterazioni, facendoci passare il test!

Fattoriale di un numero molto alto
La nostra funzione non e' ancora a prova di bomba. Facciamola scoppiare!
def test_boom():
"""Controlliamo che la funzione reagisca bene quando si trova a che fare
con numeri grandi
"""
fattoriale(1e10)
Per fare in modo che la funzione gestisca questo test occorrera' gestire l'eccezione che viene sollevata nel caso in cui il numero di cui si vuole calcolare il fattoriale sia troppo alto.

Configurare il weather plasmoid

KDE 4 introduce un plasmoide che vi tiene aggiornati sulla situazione meteo della vostra citta'
Ecco come configurarlo in modo rapido e indolore!
  1. Muovete il puntatore del mouse sul widget: apparira' una estensione che mostra alcune icone. Cercate quella per la configurazione (una chiave inglese) e cliccatela.
  2. Vi troverete di fronte ad una finestra di configurazione in cui il primo campo e' lo Zip Code della citta' che vi interessa. Per scoprire quale Zip Code corrisponde alla vostra citta' andate su Yahoo Weather e cercate la vostra citta'. Una volta che l'avrete trovata dovreste essere reindirizzati alla pagina che mostra le informazioni meteo relative. L'indirizzo di questa pagina contiene lo Zip Code. Nel caso della mia citta', Ferrara, questo indirizzo e':
    http://weather.yahoo.com/Ferrara-Italy/ITXX0027/forecast.html
    e lo Zip Code e' ITXX0027.
  3. Copiate l'indirizzo nell'apposito campo
  4. Eventualmente modificate le unita' di misura passando da gradi Fahrenheit a Celsius. 5 minuti come frequenza di aggiornamento e' un valore piu' che ragionevole.
  5. Cliccate il pulsante Ok
Potete aggiungere tutte le weather widget che volete, ciascuna configurata per una citta' diversa (ad esempio per tenere sotto controllo il meteo nella destinazione del vostro prossimo viaggio).

Digitale terrestre e chipset lite-on per linux


Una semplice soluzione per sistemare una rogna!
Qualora foste possessori di una delle penne USB per il digitale terrestre (altrimenti dette DVB-T tuner) che montano il chipset lite-on [1] e voleste utilizzarla su qualsiasi distribuzione linux vi conviene dare un'occhiata a quanto segue :)

Premesso che abbiate installato tutto il software necessario [2], aprite una console e date il comando:
tail -f /var/log/messages

Collegate la vostra penna usb. Dovrebbe comparirvi una cosa simile:
usb 1-3: new high speed USB device using ehci_hcd and address 2
usb 1-3: configuration #1 chosen from 1 choice
dvb-usb: found a 'LITE-ON USB2.0 DVB-T Tuner' in cold state, will try to load a firmware
dvb-usb: downloading firmware from file 'dvb-usb-dibusb-6.0.0.8.fw'
usb 1-3: USB disconnect, address 2
dvb-usb: generic DVB-USB module successfully deinitialized and disconnected.
usb 1-3: new high speed USB device using ehci_hcd and address 3
usb 1-3: configuration #1 chosen from 1 choice
dvb-usb: found a 'LITE-ON USB2.0 DVB-T Tuner' in warm state.
dvb-usb: will pass the complete MPEG2 transport stream to the software demuxer.
DVB: registering new adapter (LITE-ON USB2.0 DVB-T Tuner)
dvb-usb: no frontend was attached by 'LITE-ON USB2.0 DVB-T Tuner'
input: IR-receiver inside an USB DVB receiver as /class/input/input11
dvb-usb: schedule remote query interval to 150 msecs.
dvb-usb: LITE-ON USB2.0 DVB-T Tuner successfully initialized and connected.

Nonostante l'ultima riga ci dica che il gingillo e' "LITE-ON USB2.0 DVB-T Tuner successfully initialized and connected", dalla lettura della quart'ultima riga si capisce che qualcosa non va: "no frontend was attached by 'LITE-ON USB2.0 DVB-T Tuner'"!

NESSUN PROBLEMA!
Copiate questi comandi in un file ti testo, dandogli il nome dvb-reload [3]
#!/bin/bash
echo "Reload modules for DVB frontend ..."
if [ `id -u` != 0 ]; then
echo "Warning: $0 must be run under root account."
echo "Hint: use \"sudo $0\""
exit 1
fi
LOGGER='/usr/bin/logger'
if [ -x $LOGGER ]; then
$LOGGER "reload dvb_usb_dibusb_mc for dvb re-init"
fi
MODUL='dvb_usb_dibusb_mc'
rmmod -v $MODUL
modprobe -v $MODUL
ls -lR /dev/dvb
echo "Done."
exit 0
#eof

Lo script e' ben curato, ma, volendolo riassumere, i comandi magici sono questi:
MODUL='dvb_usb_dibusb_mc'
rmmod -v $MODUL
modprobe -v $MODUL

In parole povere il modulo del kernel per la gestione dell'apparecchio viene rimosso e ricaricato.

Eseguite lo script come root e leggerete nell'output di tail -f /var/log/messages una cosa del genere.
reload dvb_usb_dibusb_mc for dvb re-init
usbcore: deregistering interface driver dvb_usb_dibusb_mc
dvb-usb: LITE-ON USB2.0 DVB-T Tuner successfully deinitialized and disconnected.
dvb-usb: found a 'LITE-ON USB2.0 DVB-T Tuner' in warm state.
dvb-usb: will pass the complete MPEG2 transport stream to the software demuxer.
DVB: registering new adapter (LITE-ON USB2.0 DVB-T Tuner)
DVB: registering frontend 0 (DiBcom 3000MC/P)...
MT2060: successfully identified (IF1 = 1183)
input: IR-receiver inside an USB DVB receiver as /class/input/input13
schedule remote query interval to 150 msecs.
dvb-usb: LITE-ON USB2.0 DVB-T Tuner successfully initialized and connected.
usbcore: registered new interface driver dvb_usb_dibusb_mc


Come vedete questa volta il frontend e' stato registrato ("DVB: registering frontend 0 (DiBcom 3000MC/P)", sest'ultima riga)

DUE PAROLE
1 - Ho provato questa soluzione con un DVB tuner Toshiba
2 - Come interfaccia grafica per il DVB kaffeine va piu' che bene
3 - Quanto fa schifo l'interfaccia grafica che forniscono per windows? E' un'annetto che non controllo eventuali aggiornamenti, ma Savvy-TV mi sembrava veramente pessima!
4 - Se proprio dovete usare windows so che esiste un'interfaccia grafica diversa che funziona con questo tipo di penne. Non ricordo il nome. Google si'.
5 - Un metodo alternativo che ho usato per un anno e' stato quello di staccare e riattaccare il tuner ripetutamente fino a quando non veniva correttamente inizializzato... una rottura!


[1] e forse anche qualche altro chipset! Ho letto da qualche parte che la procedura per la Pinnacle non dovrebbe differire molto.

[2] Questa e' l'output del comando "rpm -qa|grep dvb", che mi elenca i pacchetti rpm che nel nome contengono la stringa dvb installati sulla mia mandriva: probabilmente basta anche meno!
dvb-firmware-usb-20061120-1plf2007.1
dvb-firmware-frontends-20061120-1plf2007.1
libdvbpsi4-0.1.5-3mdv2008.0
dvbtune-0.5-7mdv2008.1
dvb-apps-1.1.1-5mdv2008.1
libdvbpsi5-0.1.6-1mdv2008.1
dvbsnoop-1.4.00-3mdv2008.1


[3] ho trovato questi comandi in una mailing list in tedesco e data la mia nulla conoscenza della lingua non sono riuscito a risalire all'autore dello script, a cui comunque vanno tutti i nostri ringraziamenti.
Il link al post incriminato e' questo: http://www.ureader.de/msg/125921864.aspx

Installare plone su mandriva

Ecco poche semplici istruzioni passi per avere un sito plone funzionante
Quanto leggerete e' stato testato su Mandriva ma dovrebbe facilmente essere trasferibile su altre distribuzioni.
Dopo aver settato correttamente le vostre sorgenti di pacchetti [1] sara' sufficiente la seguente serie di comandi come root:
urpmi zope-Plone
urpmi python2.4-setuptools # [2]
service zope stop # [3]
zopectl adduser USERNAME PASSWORD # [4]

Ovviamente potete usare valori a piacere per la coppia USERNAME e PASSWORD.

Fatto questo Zope dovrebbe essere a posto.
A questo punto aprite un browser (konqueror, firefox o quello che vi pare...) all'indirizzo http://localhost:9080/manage
Vi sara' chiesto di immettere le credenziali (USERNAME e PASSWORD) inserite prima. Una volta che vi sarete autenticati sulla destra trovate un menu' a tendina con, a fianco, un pulsante "Add".
Dal menu' a tendina selezionate "Plone site" e cliccate su "Add". Vi si aprira' la pagina di configurazione del sito in gestazione, contenente un form con tre campi principali: Id, Title e Description.
Come Id mettete un nome semplice, ad esempio "pippo": andra' a comporre la url del vostro sito in questo modo: http://localhost:9080/pippo. Vi esorto a non inserire nomi complicati strani o con spazi.
Title e description sono frasi che potete inserire per descrivere al meglio il vostro nuovo sito.
Completato il form (per il momento bastano questi tre campi), cliccate sul bottone "Add plone site", situato in fondo alla pagina.

A questo punto andate con il vostro browser all'indirizzo: http://localhost:9080/pippo
Buon divertimento!

P.s.: Ho scritto questa guida perche' reperire queste banali informazioni mi e' costato piu' tempo di quel che pensassi. Qualora incontraste problemi vi prego di segnalarmelo in modo che altre persone non perdano tempo e coraggio approcciandosi a questo fantastico CMS. Grazie!

[1] In caso di necessita' vi consiglio di dare un occhio a questo post
[2] python2.4-setuptools e' un pacchetto necessario per evitare che le pagine non vengano generate correttamente. Se non lo installate vedrete un tipico messaggio di errore Python contente (tra l'altro) la stringa "No traversable adapter found"
[3] zope deve essere fermato prima di aggiungere un utente amministratore
[4] ci mettera' un po'...

Tutorial sui tutorial :)

Essendo un'opinione personale, non prendetevela!

Ultimamente sono stato impegnato nello studio del Php. Il linguaggio di per se' e' semplice, con strutture sintattiche che ricordano da vicino il Perl.

Essendo gia' un conoscitore di altri linguaggi di programmazione e scripting, non avevo bisogno di essere sommerso da discorsi fiume a proposito delle strutture base della programmazione, bensi' di qualche imbeccata che mettesse in luce le peculiarita' di questo linguaggio di programmazione.
Purtroppo quasi tutti i tutorial che si trovano in rete sono dedicati a principianti (o poco piu') e sono, a mio parere, inadatte per chi ha gia' esperienza con altri linguaggi di programmazione.
Prima di cavare un ragno dal buco bisogna setacciare il testo alla ricerca di quelle poche informazioni che interessano veramente.

Questo non e' l'unica pecca che ho riscontrato in documenti similiche parecchie volte presentano difetti che li rendono inefficienti, non solo per chi ha gia' esperienza, ma anche per i novizi. Faro' alcuni esempi!

Vita morte e miracoli
Puo' essere utile e ha pure un discreto fascino inquadrare storicamente la genesi di un linguaggio di programmazione, di come ha conquistato consensi e quote di mercato. Purtroppo, ai fini della produttivita', tutto questo e' perdita di tempo, soprattutto quando in questi preamboli si esaltano gli sviluppatori del portentoso linguaggio di programmazione in oggetto racontandone miti e leggende.
Sarebbe forse meglio, per queste cose, rimandare a wikipedia o al sito del linguaggio in questione.
Un linguaggio andrebbe introdotto spiegando:
  1. perche' e' stato sviluppato;
  2. cosa fa;
  3. cosa non fa;
  4. per chi e' utile;
  5. per chi e' inutile.
Conosco colleghi che hanno iniziato a fare calcolo numerico in Perl. Nulla glielo vieta, ma c'e' sicuramente di meglio. Fossero stati messi sul chi va la' per tempo magari avrebbero scelto un'altra strada. Ora e' troppo tardi, sono abituati ad usare quello e vanno avanti con il paraocchi.

Prolissita' iniziale
Quasi tutti i tutorial partono con un capitolo che spiega come installare il software necessario, quando sarebbe piu' che sufficiente spiegare cosa installare, magari con qualche nota su eventuali configurazioni.
Sarebbe buona (esalando) prassi che chi programma sapesse gia' come fare ad installare un pacchetto software, in caso contrario dovrebbe prima colmare queste lacune.
In aggiunta il modo migliore per installare un software dipende dal sistema operativo che avete sottomano e spesso il metodo di installazione proposto (la compilazione dei sorgenti) e' mostruosamente complicato rispetto alle alternative disponibili.

Faccio un esempio: uso mandriva, sono un pischello a digiuno di programmazione, voglio installarmi un compilatore. Piuttosto che scaricarne i sorgenti per compilarli e' decisamente meglio che usi il gestore di pacchetti che ho a disposizione (urpmi e la sua interfaccia grafica rpmdrake) per installare i binari gia' compilati. Altrimenti, tra dipendenze non risolte e librerie di sviluppo che verranno a mancare, rischio di non venirne piu' fuori!
La ricompilazione diventa necessaria solo in casi particolari che molto difficilmente interesseranno chi e' alle prime armi.

Proposta
Chi si approccia ad un linguaggio di programmazione lo fa per elaborare dati. Quindi un tutorial dovrebbe iniziare spiegando come leggere i dati, come immagazzinarli nei tipi base (stringhe, numeri, array, ecc...), e come restituirli elaborati.

In seguito si dovrebbe istruire il lettore su:
  1. come usare la libreria standard;
  2. tipi di dati piu ' complessi come classi e strutture;
  3. utilizzo di pacchetti aggiuntivi
Chi invece sa gia' programmare ha bisogno di conoscere le peculiarita' sintattiche del linguaggio, oltre ovviamente alla documentazione relativa alle librerie standard.

Spero in breve tempo di riuscire a postare un contributo esemplificativo delle idee espresse in questo post.