Il presente articolo è stato tradotto automaticamente.

Esecuzione dei test

Modulo .NET test con IronPython

James McCaffrey

Download codice disponibile dalla Raccolta di codice di MSDN
Selezionare il codice in linea

Contenuto

Il modulo in test
Ad hoc modulo interattivo test
Automazione di test Lightweight modulo
Disposizione dei

Il linguaggio di scripting Python dispone di funzionalità che rendono una scelta eccellente per eseguire diversi tipi di test del software. Vi sono diverse implementazioni di Python disponibili inclusi CPython, l'implementazione più comune su computer che eseguono sistemi operativi simile a UNIX e IronPython, un'implementazione rilasciato in ritardo 2006 che le destinazioni in Microsoft .NET Framework. Nell'articolo di mese questo verrà illustrato come utilizzare IronPython per verificare i moduli basati su .NET dalla entrambi Python riga di comando e negli script Python lightweight. È possibile utilizzare avere esperienza con un linguaggio script come JavaScript, Windows PowerShell, VBScript, Perl, PHP oppure Ruby, ma È non presupporre che conoscenza qualsiasi Python. Dare un'occhiata alla Figura 1 per ottenere un'idea di in cui sono diretto. STO utilizzando IronPython eseguire un test ad hoc e rapido di un metodo che confronta due mani scheda in un modulo standard .NET denominato TwoCardPokerLib. È possibile descrivere i comandi mostrati nella Figura 1 in dettaglio più avanti in questa colonna, ma per ora è possibile osservare che è possibile in modo interattivo aggiungere un riferimento a una DLL che contiene il modulo di .NET, creare istanze di due oggetti di magazzino da tale modulo e chiamare un metodo di confronto per determinare se una mano battute altri mano. Ora esaminiamo rapido nella Figura 2 . Tale schermata è raffigurato l'esecuzione di uno script IronPython leggero che impiegato di minuti solo da creare. Anche in questo caso, passare su tutti i dettagli più avanti, ma è possibile osservare che è possibile eseguire modulo classico test mediante la lettura dei dati di test case da un file di testo, creare istanze di due oggetti di disponibilità dal modulo TwoCardPokerLib, chiamare il metodo di confronto e quindi confrontare i risultati effettivi con i risultati previsti per determinare i risultati di test case passare o non riuscita.

Figura hoc test 1 con IronPython sulla riga di comando

>>> import sys
>>> sys.path
['C:\\IronPython', 'C:\\IronPython\\Lib']
>>> sys.path.append(r'C:\ModuleTestingWithPython\TwoCardPokerLib\bin\  Debug')
>>> sys.path
['C:\\IronPython', 'C:\\IronPython\\Lib', 'C:\\ModuleTestingWithPython\\  TwoCardPokerLib\\bin\\Debug']
>>>
>>> import clr
>>> dir()
['_', '__builtins__', '__doc__', '__name__', 'clr', 'site', 'sys']
>>>
>>> clr.AddReferenceToFile("TwoCardPokerLib.dll")
>>> from TwoCardPokerLib import *
>>> dir()
['Card', 'Hand', '_', '__builtins__', '__doc__', '__name__', 'clr',   'site', 'sys']
>>>
>>> c1 = Card()
>>> c2 = Card("9d")
>>> print c1,c2
As 9d
>>>
>>> h1 = Hand(c1,c2)
>>> h2 = Hand("Ah","8c")
>>> expected = 1
>>> actual = h1.Compare(h2)
>>>
>>> if actual == expected: print "Pass\n",
... else: print "Fail\n"
...
Pass
>>>
>>> ^Z

C:\IronPython>

fig02.gif

Nella figura 2 automazione di test con uno script IronPython

Nelle sezioni che seguono, descriverò la libreria di classi TwoCardPokerLib testare in modo da comprendere esattamente ciò che è da testare. Quindi tratterò i comandi IronPython interattivi che HO utilizzato nella Figura 1 . Successivamente è possibile presentare e spiegare in dettaglio lo script Python breve che ha prodotto l'output nella Figura 2 . Il codice sorgente completo per il harness di test e la libreria sottoposti a test sono download che accompagna questo articolo.

Verrà disposto i con una breve descrizione di come poter adattare ed estendere le idee presentate in base alle specifiche esigenze proprio test. Sono sicuri che si scoprirà che Python test le tecniche qui presentate sarà un'aggiunta grande per il software verifica set di competenza.

Il modulo in test

Ora esaminiamo la raccolta in seguito a verifica. HO deciso di creare una .NET libreria di classi per il testing che dispone di sufficiente funzionalità per visualizzare i tipi di problemi di che affrontare quando si esegue modulo reale test in un ambiente di produzione, ma non in modo molto complessità che i dettagli della raccolta nascondere i test problemi. È possibile immaginata una partita ipotetica poker due scheda in cui ogni giocatore riceve solo due schede da quattro, deck standard e 52 scheda. Naturalmente questo porta a una progettazione orientata con una classe della scheda, una classe di disponibilità e un metodo di confronto per determinare quale dei due oggetti di magazzino è migliore. HO deciso che ogni mano due scheda sarebbe essere classificata come scaricamento una seria consecutivi schede dello stesso seme, una coppia di due schede con la stessa classificazione, un scaricamento due schede dello stesso seme, una seria due schede di consecutivi e quindi ACE alto verso il basso su quattro elevato. Si noti che una mano tre elevato non è possibile perché tre due è una seria e ACE 3 è un elevato di ACE. Anche tali un semplice esempio è piuttosto interessante da implementare. IronPython può essere utilizzato per verificare in modo efficace librerie .NET indipendentemente dal linguaggio implementazione di e IronPython può essere utilizzato per verificare le librerie COM classiche. Il codice sorgente per la classe scheda nel catalogo multimediale TwoCardPokerLib è elencato nella Figura 3 .

Figura 3 la classe scheda della libreria in test

public class Card
{
  private string rank;
  private string suit;
  public Card() {
    this.rank = "A"; // A,2, . . ,9,T,J,Q,K
    this.suit = "s"; // c,d,h,s
  }
  public Card(string s) {
    this.rank = s[0].ToString();
    this.suit = s[1].ToString();
  }
  public override string ToString() {
    return this.rank + this.suit;
  }
  public string Rank {
    get { return this.rank; }
  }
  public string Suit {
    get { return this.suit; }
  }
  public static bool Beats(Card c1, Card c2) {
    if (c1.rank == "A") {
      if (c2.rank != "A") return true;
      else return false;
    }
    else if (c1.rank == "K") {
      if (c2.rank == "A" || c2.rank == "K") return false;
      else return true;
    }
    else if (c1.rank == "Q") {
      if (c2.rank == "A" || c2.rank == "K" || c2.rank == "Q") return false;
      else return true;
    }
    else if (c1.rank == "J") {
      if (c2.rank == "A" || c2.rank == "K" || c2.rank == "Q" || c2.rank == "J")
        return false;
      else
        return true;
    }
    else if (c1.rank == "T") {
      if (c2.rank == "A" || c2.rank == "K" || c2.rank == "Q" ||
        c2.rank == "J" || c2.rank == "T")
        return false;
      else return true;
    }
    else { // c1.rank is 2, 3, . . 9
      int c1Rank = int.Parse(c1.rank);
      int c2Rank = int.Parse(c2.rank);
      return c1Rank > c2Rank;
    }
  } // Beats()

  public static bool Ties(Card c1, Card c2) {
    return (c1.rank == c2.rank);
  }
} // class Card

Per mantenere il codice breve e le idee principali deselezionare, eseguita alcuni collegamenti che è non scrivere in un ambiente di produzione, ad esempio se tutti i controlli di errore. La classe della scheda è stata progettata intenzionalmente per illustrare molte delle funzionalità comuni di un modulo .NET tipica. Si noti vi è un costruttore di scheda predefinito, che consente di creare un Asso di picche scheda oggetto. È un costruttore che accetta una stringa come TD per creare un oggetto che rappresenta un dieci della scheda di diamanti. È possibile implementare proprietà get per esporre il rango e il seme di un oggetto scheda. Ed è possibile implementare metodi Beats e riferimenti statici che possono essere utilizzati per determinare se un oggetto scheda battute o collega un altro oggetto scheda. La classe di magazzino è troppo lunga per presentare nella sua interezza, in modo descriverò solo le parti chiave della classe. La classe di magazzino dispone solo due campi di membro:

public class Hand {
  private Card card1;
  private Card card2;
  // constructors, methods, etc.
}

SI crea il presupposto importante card1 è la maggiore di (o probabilmente uguale a) i due oggetti scheda. Questo semplifica notevolmente la logica del mio metodo Hand.Compare. La classe di magazzino dispone di costruttori più, una situazione tipica, è necessario considerare quando si esegue il test del modulo. Il costruttore di disponibilità predefinito crea una mano con due schede di picche ace–of:

public Hand() {
  this.card1 = new Card(); 
  this.card2 = new Card();
}

È possibile implementare due altri costruttori di disponibilità Consenti a entrambi passare in due oggetti scheda o due stringhe:

public Hand(Card c1, Card c2) {
  this.card1 = new Card(c1.Rank + c1.Suit);
  this.card2 = new Card(c2.Rank + c2.Suit);
}
public Hand(string s1, string s2) {
  this.card1 = new Card(s1);
  this.card2 = new Card(s2);
}

Nella Figura 4 è possibile implementare quattro metodi helper privati. Come si vedrà metodi privati non sono esposti a uno script di test IronPython.

Nella figura 4 private metodi

private bool IsPair() { return this.card1.Rank == this.card2.Rank; }
private bool IsFlush() { return this.card1.Suit == this.card2.Suit; }
private bool IsStraight() {
  if (this.card1.Rank == "A" && this.card2.Rank == "K") return true;
  else if (this.card1.Rank == "K" && this.card2.Rank == "Q") return true;
  // etc: Q-J, J-T, T-9, 9-8, 8-7, 7-6, 6-5, 5-4, 4-3, 3-2
  else if (this.card1.Rank == "A" && this.card2.Rank == "2") return true; 
  else return false;
}
private bool IsStraightFlush() { return this.IsStraight() &&
  this.IsFlush();
}

Come una generale regola empirica, quando esegue il modulo che si verifica non in modo esplicito verifica metodi privati. Il concetto è che gli eventuali errori nei metodi di supporto verranno esposte quando si verifica il metodo pubblico che utilizza l'Assistente. Il metodo Hand.Compare è ovviamente difficile. È codificato privati metodi di supporto Beats e riferimenti e quindi utilizzarli implementare il metodo pubblico di confronto:

public int Compare(Hand h) {
  if (this.Beats(h))
    return 1;
  else if (this.Ties(h))
    return 0;
  else if (h.Beats(this))
    return -1;
  else
    throw new Exception("Illegal path in Compare()");
}

È possibile utilizzare il vecchio paradigma di funzione strcmp(s,t) di linguaggio C per il "left disponibilità parametro (il "this" oggetto) Hand.Compare—if battute il parametro "right (l'esplicita disponibilità parametro di input), il confronto restituisce 1. Se il parametro destra battute il parametro sinistro Confronta restituisce-1. Se due oggetti di magazzino sono uguali in base delle regole, Confronta restituisce 0. La maggior parte delle operazioni viene eseguita tramite il metodo Beats privato, che è illustrato nella Figura 5 .

Figura 5, il metodo Beats

private bool Beats(Hand h) {
  if (this.IsStraightFlush()) {
    if (!h.IsStraightFlush()) return true;
    if (h.IsStraightFlush()) {
      if (Card.Beats(this.card1, h.card1)) return true;
      else return false;
    }
  } // this.IsStraightFlush()
  else if (this.IsPair())
    // code  
  else if (this.IsFlush())
   //  code
  else if (this.IsStraight())
    // code    
  else 
    // code for Ace-high down to Four-high
  }

  return false;
}

Il codice per Beats è su una pagina lunga ed è possibile estrarre i dettagli se sta esaminando il relativo download del codice. Deliberatamente inserito un errore di logica metodo angosciate privato:

else if (this.IsFlush() && h.IsFlush() &&  
  this.card1.Rank == h.card1.Rank)          // error
    return true;

Se i due oggetti disponibilità confrontati sono entrambi cancellazioni, quindi è possibile verificare se entrambe le mani necessario alla stessa classificazione per la scheda elevata. Tuttavia non verificare la seconda scheda di ogni mano È necessario disporre:

else if (this.IsFlush() && h.IsFlush() &&  
  this.card1.Rank == h.card1.Rank &&
  this.card2.Rank == h.card2.Rank)         // correct
    return true;

Questo errore di logica genera l'errore di test case illustrato nella Figura 2 . HO creato multimediale utilizzando Visual Studio per creare un progetto di libreria denominato TwoCardPokerLib in TestingWithPython C:\Module, in un file TwoCardPokerLib.dll a C:\ModuleTestingWithPython\TwoCardPokerLib\bin\Debug.

Ad hoc modulo interattivo test

Ora vediamo come è possibile esaminare e testare librerie .NET utilizzando IronPython. In particolare, esaminiamo ciascuno dei comandi mostrati nella schermata nella Figura 1 . La prima parte dell'output mostrato nella Figura 1 indica che STO utilizzando versione 1.1.1 di IronPython.

IronPython è un download gratuito disponibile in CodePlex, il progetto open source sponsorizzato da Microsoft, in codeplex.com/IronPython. Esso richiede .NET Framework 2.0 e viene eseguito in qualsiasi computer che supporta tale versione di Framework. L'utilizzo di Windows Vista. È effettivamente non installare IronPython, piuttosto semplicemente scaricare un unico file compresso nel computer ed estrarre del contenuto in qualsiasi directory pratico. Nel mio caso È possibile memorizzati tutti i file IronPython e sottodirectory in C:\IronPython. Richiamato l'interprete della riga di comando Python (ipy.exe) e specificata una facoltativa - X: argomento TabCompletion per attivare il completamento della scheda. Se si digita ipy.exe -h verrà visualizzato un elenco di tutte le opzioni. All'avvio IronPython eseguirà uno script di avvio speciali, denominato site.py, se esiste uno script di questo tipo. HO utilizzato il file di site.py standard fornito con IronPython, senza alcuna modifica.

Dopo IronPython inizializzato, esaminare le informazioni di percorso di sistema IronPython correnti:

>>> import sys
>>> sys.path
['C:\\IronPython', 'C:\\IronPython\\Lib']

Innanzitutto, è possibile inviare un comando sys di importazione in modo che abbia accesso ai metodi all'interno del modulo di sys IronPython speciale. Successivamente è possibile visualizzare l'elenco dei percorsi IronPython esaminerà durante la ricerca di file che non sono nella directory corrente. È possibile considerare questo come meccanismo di IronPython locale è piuttosto simile alla variabile di ambiente PATH del sistema operativo Windows. Poiché richiamato IronPython con la caratteristica TabCompletion, se HO voluto sapere quali proprietà e metodi sono disponibili all'utente corrente dal modulo sys, È stato immesso sys. e premere ripetutamente il tasto <tab>. Successivamente È stabilire IronPython in cui si trova il modulo di .NET sottoposti a test:

>>> sys.path.append(r'C:\ModuleTestingWithPython\TwoCardPokerLib\bin\Debug')
>>> sys.path
['C:\\IronPython', 'C:\\IronPython\\Lib', 'C:\\ModuleTestingWithPython\\TwoCardPokerLib\\bin\\Debug']

È possibile utilizzare il metodo path.append del modulo sys per aggiungere una nuova directory all'elenco di ricerca IronPython. Si noti il carattere r in prima dell'argomento stringa da accodare. In Python è possibile utilizzare le offerte di sola o offerte doppia attorno a stringhe. Tuttavia, diversamente da alcuni linguaggi, Python valuterà caratteri di escape, ad esempio \n all'interno di stringhe virgolette e racchiuso tra virgolette doppie. Per garantire che una stringa viene interpretata esclusivamente come valore letterale (una stringa elaborata nella terminologia Python) è possibile utilizzare il modificatore r come HO fatto in precedenza. Dopo aver accodato la nuova directory È possibile verificare che non sono state apportate eventuali errori di digitazione inviando un comando sys.path. Successivamente è possibile preparare caricare la DLL testare dai metodi di attivazione primo che possono caricare i moduli di .NET:

>>> import clr
>>> dir()
['_', '__builtins__', '__doc__', '__name__', 'clr', 'site', 'sys']

È possibile inviare un comando di clr (per common language runtime) importazione e ora è possibile avere accesso al modulo di clr, che dispone di numerosi metodi che possono caricare assembly .NET. Quindi è possibile utilizzare dir() Python comando per visualizzare dei moduli È attualmente disponibile. Si noti che non attualmente hanno accesso alla raccolta TwoCardPokerLib. Ora È possibile utilizzare il modulo di clr per accedere a multimediale sottoposti a test:

>>> clr.AddReferenceToFile("TwoCardPokerLib.dll")
>>> from TwoCardPokerLib import *
>>> dir()
['Card', 'Hand', '_', '__builtins__', '__doc__', '__name__', 'clr', 'site', 'sys']

È possibile utilizzare il metodo AddReferenceToFile per attivare l'ambiente IronPython corrente chiamare la DLL TwoCardPokerLib. Se È stato immesso addreferencetofile, ad esempio, non sarebbe hanno utilizzato un errore ad-attributo (metodo) viene fatta distinzione tra maiuscole e minuscole, Python.

Dopo aver aggiunto un riferimento per il modulo sottoposti a test, È necessario utilizzare l'istruzione import per rendere disponibile il modulo. Impossibile è tipizzato importazione TwoCardPokerLib ma si digita dall'importazione TwoCardPokerLib * invece. Se si utilizza il modulo primo, più semplice, È necessario completo tutto il modulo, TwoCardPokerLb.Hand, ad esempio, invece di digitare solo magazzino. Mi omettere il nome del modulo padre quando si digita consente di forma da <module>-importazione-<classes> di comando di importazione. Si noti che dopo eseguire un comando dir(), è possibile visualizzate le classi di scheda e disponibilità all'interno del modulo TwoCardPokerLib saranno disponibili all'utente. Ora possibile esercitare il modulo in seguito a verifica creando due oggetti scheda:

>>> c1 = Card()
>>> c2 = Card("9d")
>>> print c1,c2
As 9d

È possibile utilizzare il costruttore di scheda predefinito per creare un'istanza un oggetto denominato c1. Ricordare che il costruttore di scheda predefinito crea un Asso di picche oggetto dalla sezione precedente. È possibile utilizzare il costruttore scheda non predefinito per creare un oggetto che rappresenta un nove di diamanti. Osservare che è possibile non utilizzare una parola chiave come "New" per creare istanze di oggetti come farebbe in alcuni linguaggi. Se È stato utilizzato il breve "importare TwoCardPokerLib" istruzione precedente, sarebbe stato chiamato il costruttore come " c1 = TwoCardPokerLib.Card() ". È possibile utilizzare l'intrinseco istruzione di stampa Python per visualizzare i due oggetti scheda. Dietro le quinte, l'istruzione stampa IronPython effettivamente chiama il metodo Card.ToString() che HO implementato nel Catalogo multimediale di classe. Ora creare istanze di due oggetti di disponibilità e chiamare il metodo Hand.Compare:

>>> h1 = Hand(c1,c2)
>>> h2 = Hand("Ah","8c")
>>> expected = 1
>>> actual = h1.Compare(h2)  

È possibile passare i due oggetti scheda che appena creato in un costruttore di disponibilità per creare una prima mano e quindi è possibile utilizzare la versione di parametro di stringa del costruttore per creare un'istanza lancetta dei secondi. Poiché una mano di 9 ACE battute una mano di otto ACE, è possibile che il metodo di confronto per restituire 1 è possibile archiviare tale valore in una variabile denominata prevista. Si noti che Python è un linguaggio tipizzato in modo dinamico, pertanto è possibile non dichiarare tipi di dati. È possibile chiamare il Hand.Compare metodo e archivio il risultato in una variabile denominata effettivo. È possibile visualizzare i metodi disponibili nella classe di disponibilità digitando magazzino. la riga di comando e quindi premendo il tasto <tab>. Sarebbe vedere i metodi pubblici, ad esempio confrontare e ToString ma non si visualizzate metodi privati quali Beats e riferimenti. A questo punto È possibile determinare un risultato del passaggio e non riuscita per il test interattivo ad hoc:

>>> if actual == expected: print "Pass\n",
... else: print "Fail\n"
...
Pass
>>>

La sintassi di quindi se Python in una riga di comando è un po'inusuale, pertanto verrà spiegato nella sezione successiva. Ma essenzialmente è possibile verificare se il valore nella variabile denominata effettivo è uguale al valore della variabile denominata previsto. Se in questo caso, visualizzato un messaggio di "passaggio"; in caso contrario è possibile stampare "errori. Si noti che HO incluso un carattere di nuova riga in ciascuna stringa. Intermediate "..." risposta dall'interprete IronPython indica che È necessario un comando non completato e l'interprete è in attesa di completare il comando.

Automazione di test Lightweight modulo

A questo punto seguito illustrato scrivere script IronPython leggero per testare alle librerie di classe. NET. Lo script in figura 6 viene prodotto l'output mostrato nella Figura 2 .

Nella figura 6 file harness.py

# harness.py
# test TwoCardPokerLib.dll using data in TestCases.txt

print "\nBegin test run\n"
import sys
print "Adding location of TwoCardPokerLib.dll to sys.path"
sys.path.append(r'C:\ModuleTestingWithPython\TwoCardPokerLib\bin\Debug')

import clr
print "Loading TwoCardPokerLib.dll\n"
clr.AddReferenceToFile("TwoCardPokerLib.dll")
from TwoCardPokerLib import *

print "=================================="
fin = open("TestCases.txt", "r")
for line in fin:
  if line.startswith("$"):
    continue
  (caseID,input,method,expected,comment) = line.split(':')
  expected = int(expected)
  (left,right) = input.split(',')
  h1 = Hand(left[0:2],left[2:4])
  h2 = Hand(right[0:2],right[2:4])
  print "Case ID = " + caseID
  print "Hand1 is " + h1.ToString() + "   " + "Hand2 is " + h2.ToString()
  print "Method = " + method + "()"
  actual = h1.Compare(h2)

  print "Expected = " + str(expected) + " " + "Actual = " + str(actual)
  if actual == expected:
    print "Pass"
  else:
    print "** FAIL **"


  print "=================================="

fin.close()
print "\nEnd test run"
# end script

È possibile iniziare lo script di harness IronPython test con i commenti:

# harness.py
# test TwoCardPokerLib.dll using data in TestCases.txt

Il # è il carattere Commenti per script Python. Python sia riga-base, commenti eseguire fino alla fine di una riga. Python supporta inoltre multiriga commenti utilizzando singolo triplo offerte. Script Python utilizzare un'estensione di file .PY e possono essere create utilizzando qualsiasi editor di testo, compresi il blocco note. Mio harness test legge i dati di test case da un file esterno denominato TestCases.txt:

0001:AcKc,AdAs:Compare:1:  "royal flush" > pair Aces
0002:Td9d,Th9h:Compare:0:  straight flush diamonds == straight flush hearts
$0003:Ah2c,As9c:Compare:1:   straight > Ace high
0004:9h6h,9d7d:Compare:-1:  flush 9-6 high < flush 9-7
0005:KcJh,As5d:Compare:-1: King high < Ace high

In questo campo è solo cinque test case, ma in uno scenario di produzione avrebbe centinaia o migliaia. Esistono 7,311,616 o 524 gli input validi per Hand.Compare, illustra impracticality di testing con attenzione anche semplici moduli.

Ogni riga rappresenta un singolo test case. Ogni campo è delimitato dal carattere due punti. Il primo campo è un ID di test case. Il secondo campo è una stringa che contiene informazioni per due oggetti di disponibilità, separati da un carattere punto e virgola. Il terzo campo indica quale metodo da verificare. Il quarto campo è il valore previsto. Quinto campo è facoltativo e un commento di test case. Avviso test case 0003 è preceduta da un carattere $. Verrà Cerca il carattere nel mio harness di test e saltare questi casi di test. Test case 0004 genera un risultato di errore causa dell'errore logica deliberatamente (esclusivamente per scopi dimostrativi) che è possibile inserita all'interno del metodo di Hand.ties chiamato dal metodo Hand.Compare sottoposti a test. L'archiviazione dei dati di test case in un file di testo è semplice e rapido. Potrebbero inoltre sono incorporati i dati di test case direttamente nel mio harness, oppure memorizzati i casi in un file XML e così via. Python facilmente possibile gestire qualsiasi schema di archiviazione di test case. Successivamente è possibile visualizzare un messaggio la shell di comando:

print "\nBegin test run\n"

Poiché Python stringhe possono essere delimitate da double offerte o virgolette e caratteri di escape vengono valutati in entrambi gli stili offerta, la scelta tra i tipi di offerta è effettivamente una questione di preferenze. In genere utilizzare offerte doppia tranne quando sono intendo per utilizzare il modificatore r per rendere la stringa di un valore letterale, nel qual caso tendono a utilizzare virgolette singole. Successivamente lo script di harness Python test aggiunge la posizione del mio DLL testare al percorso di sistema Python:

import sys
print "Adding location of TwoCardPokerLib.dll to sys.path"
sys.path.append(r'C:\ModuleTestingWithPython\TwoCardPokerLib\bin\Debug')

Qui è possibile impostare come hardcoded la posizione di DLL in seguito a verifica. È possibile passare gli argomenti della riga di comando al mio script python e accedervi con la matrice sys.argv incorporato. Ad esempio, se fosse necessario richiamare il mio script come

  > ipy.exe   harness.py   C:\Data   MyLib.dll

quindi sys.argv[0] sarebbe contenente il nome del mio script harness.py, sys.argv[1] potrebbe contenere il primo argomento (C:\Data) e sys.argv[2] potrebbe contenere il secondo argomento (MyLib.dll). Quindi stabilire mio harness per caricare il modulo di test:

import clr
print "Loading TwoCardPokerLib.dll\n"
clr.AddReferenceToFile("TwoCardPokerLib.dll")
from TwoCardPokerLib import *

Caricare una libreria basata su .NET utilizzando IronPython in diversi modi. Il metodo di clr.AddReferenceToFile è a semplice ed efficace a quando il sys.path contiene la posizione della raccolta per aggiungere, ma il modulo di clr contiene inoltre inclusi clr.AddReference, clr.AddReferenceByName, clr.AddReferenceByPartialName e clr.AddReferenceToFileAndPath alternative. Qui utilizzerò la * caratteri jolly per caricare tutte le classi dalla raccolta TwoCardPokerLib, ma È possibile caricare classi specifiche da loro nomi. Python dispone di numerosi metodi per elaborare un testo file riga per riga. È possibile utilizzare funzione di apertura file intrinseco e passare è il nome di un file di test case e un argomento r per indicare che l'apertura del file per la lettura:

print "=================================="
fin = open("TestCases.txt", "r")
for line in fin:
  # process line here

Altre modalità più comuni includono w per la scrittura e una per l'accodamento. L'argomento modalità è facoltativo e per impostazione predefinita r in modo che Impossibile hanno lasciato fuori. È possibile trovare un riferimento valido per funzionalità di linguaggio, sintassi e le funzioni intrinseche Python in docs.python.org. Il risultato della funzione aperto è un handle di file che è possibile assegnare a una variabile denominata fin. Quindi è possibile utilizzare un ciclo scorrere la riga dalla riga for. È denominato mio campo-archiviazione variabile "riga", ma Impossibile hanno utilizzato qualsiasi nome di variabile valido. Si noti che un capriccio sintattica di Python: invece di utilizzare, ad esempio Inizio, Fine token {. .. } o iniziale. .. fine come la maggior parte delle lingue, Python utilizza il carattere due punti in combinazione con rientri per indicare l'inizio e fine dei blocchi di dichiarazione. All'interno il ciclo di elaborazione principale, è possibile per utilizzare la startswith intrinseco stringa funzione per verificare se la riga corrente dal file test case inizia con un carattere di segno di dollaro:

if line.startswith("$"):
  continue

È possibile trovare un $, è possibile utilizzare la continue istruzione per saltare le istruzioni rimanenti nel per ciclo e di lettura la riga successiva dal file test case. Python dispone di un completo insieme di strutture di controllo ciclo e decisioni. È possibile analizzare la riga di dati test case nei relativi campi singoli:

(caseID,input,method,expected,comment) = line.split(':')
expected = int(expected)

È possibile utilizzare una caratteristica brillante di Python una tupla e la funzione stringa divisa intrinseco per analizzare rapidamente i dati. È stato sono eseguire l'attività utilizzando un approccio di matrice tradizionali come vedere di seguito, ma RITENGO che l'approccio tupla Python sia più breve di comprensione più immediata.

tokens = line.split(':')
caseID = tokens[0]
input = tokens[1]
method = tokens[2]
expected = tokens[3]
comment = tokens[4]

È possibile utilizzare la funzione int() per convertire la variabile denominata prevista da stringa di tipo nel tipo int in modo che È possibile confrontare in effettivo. Altre funzioni di conversione di tipo utili includono str(), float(), long() e bool(). Successivamente eseguire un'operazione di analisi seconda per estrarre le mani di input due:

(left,right) = input.split(',')
h1 = Hand(left[0:2],left[2:4])
h2 = Hand(right[0:2],right[2:4])

Dopo il primo analisi con divisione, l'input variabile contiene un valore stringa come KcJh, As5d. Pertanto, è possibile chiamare dividere nuovamente con un argomento e memorizzare i risultati di due variabili chiamato a sinistra e destra. A questo punto la variabile di stringa denominata sinistra contiene KcJh e destra contiene As5d. A differenza di molti linguaggi, Python non dispone di un metodo della sottostringa. Al contrario, i Python utilizza l'indicizzazione matrice per estrarre sottostringhe. Matrice di indicizzazione inizia da 0, in modo da Se a sinistra la variabile contiene KcJh quindi all'espressione di sinistra [0: 2] kc e l'espressione left [2:4] raccolti Jh raccolti. Si noti che per estrarre una sottostringa da una stringa più grande, specificare l'indice del primo carattere in stringa di dimensioni maggiore (come prevedibile) ma uno più l'indice del carattere finale. Una volta ottenuto stringhe che rappresentano schede individuali, li è possibile passare al costruttore magazzino. Successivamente È visualizzato i dati di input per la shell:

print "Case ID = " + caseID
print "Hand1 is " + h1.ToString() + "   " + "Hand2 is " + h2.ToString()
print "Method = " + method + "()"

Utilizza Python il + il carattere a eseguire la concatenazione di stringhe, in modo che nelle istruzioni di stampa tre precedente sono stampa tre stringhe. La funzione di stampa può accettare più argomenti separati dal, carattere, pertanto Impossibile immesse istruzioni, ad esempio per produrre lo stesso output:

print "Case ID = " , caseID

A questo punto sono pronto per chiamare il metodo sottoposti a test:

actual = h1.Compare(h2)
print "Expected = " + str(expected) + " " + "Actual = " + str(actual)

Si noti che perché implementato il metodo Hand.Compare come un metodo di istanza, è possibile chiamarlo dal contesto dell'oggetto disponibilità h1. Se È stato codificato compare come metodo statico sarebbe stato chiamato in questo modo:

actual = Compare(h1,h2)

Si noti che a questo punto le variabili effettive e previste sono di tipo int essendo effettivamente il restituito valore dal metodo di confronto definito per restituire un tipo int e previsto che è stato eseguire il in modo esplicito cast su un int. Di conseguenza cast effettivo e alle stringhe in modo che È possibile concatenare una stringa unico output. Ora è possibile visualizzare il risultato di test case passare o non riuscita:

if actual == expected:
  print "Pass"
else:
  print "** FAIL **"

print "=================================="

Python utilizza rientri per indicare all'inizio e alla fine di blocco di istruzioni. Se si dispone numerose esperienza di programmazione in altre lingue, utilizzo Dell'python di rientro può sembrare un po'dispari inizialmente. Ma la maggior parte dei tester È stato descritto dire che problemi insoliti sintassi del Python acquisire familiari abbastanza rapidamente.

Se desidera tenere traccia del numero totale di test case che passano, È possibile inizializzare i contatori all'esterno il ciclo di elaborazione principale in questo modo:

numPass = numFail = 0

e quindi modificare la struttura quindi se:

if actual == expected:
  numPass += 1
  print "Pass"
else:
  numFail += 1
  print "** FAIL **"

Quindi possibile stampare i risultati all'esterno del ciclo di elaborazione:

print "Num pass = " , numPass ,  " num fail = " ,  numFail

Si noti che Python non supporta sintassi simile numPass ++ o ++ numPass incremento di una variabile di int. Qui sono semplicemente stampa i risultati la shell di comando, ma È possibile scrivere facilmente risultati in un file di testo, file XML, database SQL o altro archivio. Ora fine harness il test dei:

fin.close()
print "\nEnd test run"
# end script

È possibile chiudere il riferimento file di test case per liberare il punto di manipolazione di file e stampare un messaggio indicante che il test è completo. La struttura di script è molto semplice ma Python include caratteristiche che consentono di gestire lingue con alfabeti complessi. Ad esempio, in un ambiente di produzione sarebbe disposto in modo definito mio intero script in un gestore eccezioni:

try
  # harness code here
except
  # handle any exceptions here 

Inoltre, Python supporta funzioni definiti dal programmatore, pertanto Impossibile avere strutturato mio harness come una funzione principale più funzioni di supporto.

Disposizione dei

Test automatizzato modulo è probabilmente il tipo più fondamentale di automazione di test del software. Ogni volta che desidera valutare l'idoneità di un linguaggio di programmazione per l'automazione di test, è possibile verificare innanzitutto come la lingua riguarda test del modulo. Secondo me, IronPython supera questo test litmus con flying colors. Linguaggio di programmazione è perfetto per tutte le attività e scenari di test. Ciò detto, IronPython dispone di numerose funzionalità che renderla una scelta eccellente come linguaggio di test del modulo.

Consenti all'utente di fine per accennando come lightweight modulo test di automazione con IronPython si riferisce a unit test. Unit test con Framework quali NUnit vengono spesso inseriti direttamente all'interno del codice di modulo. Fase di sviluppo basato su test e unit test è principalmente un'attività di sviluppo. Utilizzo di un approccio di test unità durante la fase di sviluppo non absolve è da responsabilità dell'esecuzione di test del modulo completa e dedicato. Si tratta di cui Python proviene in. In altre parole, il modulo test con Python è completa una, non un sostituto per unit test. Quando vengono utilizzati insieme due approcci diversi è possibile creare software migliori e più affidabili.

Inviare domande e commenti per John a testrun@Microsoft.com.

Dr. James McCaffrey funziona per Volt Information Sciences, Inc., in cui ha gestisce formazione tecnica per ingegneri software di utilizzo di Microsoft. Ha lavorato di numerosi prodotti Microsoft inclusi Internet Explorer e MSN Search. John è autore di .NET Test Automation Recipes. È possibile contattarlo all' jmccaffrey@volt.com o v-jammc@microsoft.com.