Unit Test e AutoCad: si può fare!

10. aprile 2010

Lo sviluppo di nuove feature e/o applicazioni integrate con AutoCad è diventato incredibilmente più produttivo da quando sono state introdotte le librerie ObjectArx in formato .Net.

L'unico (grosso) limite che ho riscontrato fino a poco tempo fa è stata l'impossibilità di utilizzare framework di test e di mocking.

Questo perchè i plugin sviluppati devono necessariamente essere caricati lanciando AutoCad stesso e funzionano nel thread principale della UI (e ovviamente non è possibile mokkare Autocad...).

Fino ad oggi quindi i test li avevo scritti completamente a mano, creando man man tutti gli oggetti necessari.

Recentemente ho trovato questa piattaforma di automazione: Gallio

Oltre a fornire il supporto per tutti i principali framework di test (NUnit, MSTest, xUnit ecc) e ai principali strumenti di mocking e di continous integration, Gallio è in grado di automatizzare l'esecuzione di test all'interno di Autocad.

Il funzionamento alla base è concettualmente semplice: Gallio carica uno shimW all'interno di AutoCad che si occupa di intercettare le chiamate alle API e di eseguire i comandi.

Il testing su Autocad non è integrato nell'IDE di Visual Studio ma si tratta di una lacuna veramente minima in quanto è comunque disponibile un'interfaccia GUI simile a quella di nUnit oltre ovviamente al runner a riga di comando (il che chiude il cerchio in quanto è possibile far eseguire i test su un server di Continuous Integration).

I dubbi sono per ora due.

Il primo riguarda uno scarsa partecipazione e dinamicità nello sviluppo di Gallio; l'ultima release risale a novembre 2009.

In secondo luogo viene un po' meno uno dei principi base dei test unitari: la rapidità di esecuzione.
Per eseguire i test infatti Gallio deve caricare 2 volte AutoCad: una prima volta ad ogni rebuild della libreria dei test ed una seconda volta per eseguirli richiedendo quindi alcuni secondi di attesa.

.net Framework, AutoCAD e ObjectARX ,

Hello World: ovvero cosa serve veramente per far funzionare un'addin managed ObjectARX

25. febbraio 2008

Negli Autodesk Labs è presente l'immancabile applicazione Hello World con cui configurare correttamente l'ambiente di sviluppo.

Nel Lab vengono indicate le DLL da linkare e gli eventuali attributi da aggiungere alle classi o ai metodi come in particolare il CommandMethod con cui definire un comando custom all'interno di AutoCAD.

Ciò che il lab non dice sono però alcuni accorgimenti fondamentali per far funzionare veramente tutto riducendo gli errori. Sono piccole configurazioni che però mi hanno fatto perdere giornate di lavoro.

  1. I metodi associati ad un CommandMethod devono essere pubblici e non devono restituire nessun valore (devono cioè essere delle sub in VB.Net o restituire void in C#)
  2. Oltre a aggiungere le reference alle due librerie acadmgd.dll e acadmgdb.dll è fondamentale impostare la proprietà Copy Local a False altrimenti quando invocate il comando custom AutoCAD vi dice che non esiste nessun comando con quel nome
  3. Un'ultima cosa che mi ha fatto perdere il sonno per giorni... Impostate nella variabile PATH il percorso [program folder]\Autocad 2008 altrimenti potete scordarvi di utilizzare l'ereditarietà nelle form...

.net Framework, AutoCAD e ObjectARX ,

Disabilitare l'invio del report di errore ad Autodesk in caso di crash di AutoCAD

25. febbraio 2008

Ogni volta che si manda in crash AutoCAD  viene visualizzata la form per inviare la segnalazione di errore ad Autodesk.

Nonostante le mille attenzioni che si possono avere per non mandare in crash AutoCAD ciò in realtà accade diverse volte al giorno soprattuto in fase di sviluppo e debug.

Basta dare un'occhiata al video intitolato "10 EASY ways to crash your AutoCAD addin" per farsene un'idea (il video è scaricabile da qui).

Per evitare questa richiesta si può utilizzare il comando "ReportError" che gestisce la corrispondente variabile binaria per abilitare/disabilitare l'invio del report di errore.

ReportError = 0 -> Non viene visualizzata la form di segnalazione

ReportError = 1 -> Viene visualizzata la form di segnalazione

.net Framework, AutoCAD e ObjectARX ,

Database.Save e eFileInternalErr: bug di AutoCAD

19. dicembre 2007

In AutoCAD 2008 eseguendo il metodo managed ObjectARX:

Application.DocumentManager.MdiActiveDocument.Database.Save()

viene sollevata l'eccezione:

eFileInternalErr

ed il dwg non viene salvato.

Si tratta di un bug (l'ennesimo...) dell'API di AutoCAD.

Per aggirare il problema è sufficiente utilizzare il metodo SaveAs passando come nome del file il nome del dwg corrente:

Application.DocumentManager.MdiActiveDocument.Database.SaveAs

(Application.DocumentManager.MdiActiveDocument.Database.Filename, Autodesk.AutoCAD.DatabaseServices.DwgVersion.Current)

Oppure è possibile invocare il comando "_qsave".

E' veramente incredibile che un prodotto software di questo livello contenga dei bug di questo genere. 

[EDIT]

Grazie a Giuliano per questa segnalazione relativa alla documentazione:

"You can't save a database to the same file it was read from, because it may not have been completely read in initially, so saving to the same file poses the risk of concurrently reading/writing to the same file. The SAVE command uses saveAs() to save to a different (e.g., temporary) file and then either deletes or renames the original to *.bak, and then renames the saved file to the original filename. "

Resta valida la soluzione che propongo per salvare sullo stesso file.

AutoCAD e ObjectARX

La compatibilità delle applicazioni tra le release di AutoCAD

15. novembre 2007

Da through-the-interface un estratto sul tema della compatibilità tra le release:

Le applicazioni sviluppate sfruttando l'API AutoCAD devono essere testate (ed alcune volte modificate) per garantirne il funzionamento con nuove release di AutoCAD. Per alcune generazione di AutoCAD abbiamo scelto di non garantire la compatibilità binaria delle applicazioni ogni 3 release (storicamente questo è avvenuto con AutoCAD 2000, 2004 e 2007).

Inoltre le applicazioni sviluppate con diverse API richiedono un impegno diverso per effettuare il porting da una release all'altra. Le applicazioni LISPW sono abbastanza portabili tra le release (anche se i nomi e le posizioni dei file di supporto potrebbero cambiare di volta in volta), così come lo sono le applicazioni COM (come VBA e applicazioni esterne VB). Le applicazioni che usano le API managed (C# o VB.NET) sono un po' meno portabili di quelle ObjectARX (C++).

Le applicazioni ObjectARX sono architetturalmente molto vicine al core di AutoCAD ed è per queste applicazioni che gli sviluppatori - sia esterni che interni ad Autodesk - devono dedicare molte risorse quando viene meno la compatibilità tra le release.

Perchè è necessario interrompere la compatibilità col passato? Ci sono alcune ragioni:

  1. Alcune volte vogliamo semplicemente aggiornare le classi dell'API, per aggiungere nuovi metodi ecc. Mentre è possibile aggiungere metodi non-virtuali durante un passaggio di release compatibile, non è possibile garantire la compatibilità quando vengono aggiunti metodi virtuali perchè viene modificata la v-table
  2. Potremmo aver bisogno di aggiornare l'architettura interna o l'uso della tecnologia. Un esempio di ciò è stata l'introduzione massiccia dell'UnicodeW in AutoCAD 2007. Questo è stato un profondo cambiato nel modo con cui AutoCAD gestisce internamente le stringhe e ha richiesto la modifica della signature di molte funzioni ObjectARX.
  3. Infine si vuole godere dei vantaggi offerti dall'ultima versione del compilatore per compilare AutoCAD. AutoCAD 2000-2002 sono state compilate con Visual Studio 6, AutoCAD 2004-2006 con Visual Studio .NET 2002 e AutoCAD 2007 con Visual Studio 2005. E' importante per Autodesk rimanere allineati con l'ultima versione supportata del compilatore per ottenere supporto da Microsoft su problemi critici ma soprattutto per fornire nuove funzionalità, come ad esempio la possibilità di usare WinForms in AutoCAD e di esporre un API managed.

La domanda adesso è: perchè non viene interrotta la compatibilità ad ogni release? A causa delle difficoltà che temono i clienti e gli sviluppatori. La mancanza di compatibilità di un'applicazione in una nuova release ha impatto sull'accettazione di quella release. Mantenere una finestra di 3 release (che ad oggi equivale a 3 anni) fornisce agli sviluppatori il tempo per concentrarsi sui miglioramenti dell'applicazione a favore del cliente piuttosto che spendere risorse per la migrazione alla nuova piattaforma.

L'articolo completo si trova a questo indirizzo: http://through-the-interface.typepad.com/through_the_interface/2006/06/compatibility_o.html 

Proprio in questi giorni stò migrando un'applicazione scritta in C#-VB.NET che funziona su AutoCAD 2006 alla nuova piattaforma AutoCAD 2008. La mancanza di compatibilità c'è ma è veramente ridotta al minimo (cose tipo enumerati che hanno cambiato nome o poche funzioni con una signature diversa), nulla che non si possa agevolmente gestire utilizzando le direttive del compilatore. In pratica ho definito una direttiva ACAD2006 ed una direttiva ACAD2008 e con quelle decido per quale piattaforma compilare la DLL.

.net Framework, AutoCAD e ObjectARX, C# e VB.net, Visual Studio