Fandom

Drizzle Wiki

Proposta per un nuovo protocollo di test (TP)

32pagine in
questa wiki
Crea nuova pagina
Discussione0 Condividi

ObiettiviModifica

  • Renderlo più modulare
  • Renderlo più leggibile
  • Rendere più facile per la gente contribuire
  • Fornire una miglior copertura (rifacendo un build con un piano per il coverage, bug e use cases)

RequisitiModifica

Ci sono almeno tre aree che hanno bisogno di testing. Ognuna dipende e poggia sulle aree elencate successivamente.

  1. Test di comandi SQL
  2. Test delle configurazioni, necessaria per testare i comandi
  3. Test dei comandi del sistema operativo, compreso generare e far funzionare le varie configurazioni

Proposta Modifica

Il TP (Test Protocol) di Drizzle servirebbe a rimpiazzare mysql-test.

Una nuova sintassi per i test, che segue la sintassi tradizionale di Unit Test (per esempio suite di test cases ognuna contenente un certo numero di test). I test sono formati dalle condizioni, il setup, il teardown, le operazioni, le assertion e i risultati, tutto in un unico file (*).

Il TP è una sintassi agnostica leggibile dagli umani. C'è bisogno di traduzioni del TP in un linguaggio (esempi: lua, python, perl etc etc) C'è bisogno di una infrastruttura di base che possa interagire con un driver nativo, eseguire statement e comandi del sistema, nonchè fornire accesso ai risultati più vicini al livello di protocollo. Un'implementazione potrebbe essere:

  • Infrastruttura A C con motore DPM embedded (proxy già funzionante con supporto c/lua).
  • L'uso di DPM che parli il protocollo e intefri il supporto ai risultati ad un livello più dettagliato (suggerisce di scegliere Lua)
  • La scelta di un linguaggio per i test è Lua, con una metasintassi semplificata per gli esseri umani.

Sintassi TPModifica

Initialize:
  master_only_simple()
SetUp:
  USE test;
  DROP TABLE IF EXISTS t1;
TearDown:
  DROP TABLE IF EXISTS t1;
Test:
  SELECT 1 AS col
  rows=1
  md5=....
Test:
  SELECT 2 AS col
  rows=1
  md5=999999999999999


Anche se c'è bisogno di parole chiave (Configuration,SetUp,TearDown,Test), ':' e l'indentazione sono assolutamente opzionali per ora (è in stile Python, almeno per quanto riguarda la leggibilità) e aperti per l'input.

Domanda: identifichiamo la sintassi SQL in modo da sapere cosa è SQL e cosa è TP? Esempio: {SELECT 1}

Dettagli sui vari blocchiModifica

InitializeModifica

 Syntax:  Initialize:

Lancia una serie di comandi per TestCase e generalmente include una chiamata a un test case (esempio: master_only_simple) che crea le istanze necessarie e le variabili globali di connessione, che corrispondono ai nomi rappresentati.

Può supportare il successo di un TestCase precedente (come prerequisito ad esempio). Tutte le direttive globali dei TestCase (per esempio expectnoerror # Questo produce un noerror implicito dopo ogni istruzione SQL)

Instances è una mappa delle chiavi e di tutte le impostazioni etc esempio: m1, m2, s1, s2, s3, etc m1 = {host:localhost,port=9900, ...} connections è una mappa delle connessioni alle istanze date esempio c1, c2, c3 etc

c1 = {instance=m1,user=root,password=,schema=x}

Per default Insance e Connection si specificano globalmente, o forse il primo nella mappa è di default

instance=m1 connection=c1

Questo livello di istanze e connessioni è necessario per testare la replica, la scalabilità e la concorrenza per esempio.

Altre opzioni da considerare possono essere comandi dopo ogni istruzione SQL. Un esempio potrebbe essere la sostituzione o l'astrazione di un nome di storage engine (InnoDB, MyISAM) etc.

SetUpModifica

 Syntax:  SetUp

Comandi da eseguire prima di ogni test.

TearDownModifica

 Sytnax: TearDown

Comandi da eseguire dopo ogni test.

TestModifica

 Syntax:   Test  [timeout=x] [testname]

connection=? # Support for concurrency testing rows=N noerror error NNNN

La versione leggibile dagli esseri umani è più una macro. The human readable version is more a macro to expanded language syntax In qualunque momento tu voglia fare una cosa specifica, embedda semplicemente la sintassi del linguaggio (esempio lua)


{SELECT NOW() AS date1} sleep(0.001) data1=rows[1][1] {SELECT NOW() AS data2} data1 != rows[1][1]


esempio

SELECT 1 is rs=SQL("SELECT 1") rows=N is assertEquals(rs.rows, N) noerror is assertNull(c.error) error NNNN is assertEquals(c.error, NNNN)


OutputModifica

Il minimo di cui hai bisogno nell'output è:

   testname (999 ms)   pass|fail

Non ho speso tempo nel concentrarmi sul formato dell'output, sembra che siamo d'accordo nell'utilizzare TAP -http://en.wikipedia.org/wiki/Test_Anything_Protocol

Fornire l'infrastruttura espone le informazioni elencate in 'Variabili dell'Infrastruttura dei Test' e un livello di reporting è possibile.

Variabili dell'Infrastruttura dei TestModifica

Vorrei che le seguenti variabili fossero disponibili per il TP e che con tutte queste variabili si potesse produrre un report.

# Struttura Globale
   RunResult
     SuccessFail
     totalTime
     NoSuites
     NoTestCases
     NoTests
     SuiteResult[]
#Per Ogni Suite Eseguita
 SuiteResult
     SuiteName
     NoTestsCases
     SuccessFail
     totalTime
     TestCaseResult[]
#Per Ogni TestCase Eseguito
 TestCaseResult
   testCaseName
   NoTests
   SuccessFail
   totalTime
   TestResult[]
#Per Ogni Test Eseguito
 TestResult
   testName  (default: testNNNN)
   SuccesFail
   time

Creare i testModifica

  • Un buon numero di test di copertura del codice (475 test, 200mila righe di test case) può facilmente essere rigenerato (lavoro che ho fatto precedentemente)
  • Il parsing dei test case esistenti di MySQL per producce dei test di base (esempio: Test: SQL,rows=,md5 si possono produrre facilmente)
  • La pagina web per inviare i test, semplicemente copia-incolla l'SQL (con i risultati), opzionalmente i dati. Script da parsare nel TP di Drizzle.

Implementazione Modifica

La scelta del linguaggio non è ancora stata fatta. Potrebbe facilmente essere Perl, Python o Lua per esempio, il seguente esempio è con Lua. Questa decisione verrà presa da chi farà il lavoro. Al Drizzle Bof alla OSON, è stato proposto che si possa disporre di diversi linguaggi, il migliore sopravviverà.

Scegliere un interprete per il Test ProtocolModifica

C'è bisogno di poter incapsulare la sintassi del linguaggio nei test case.

Rasformare il linguaggio umano in un linguaggio di programmazione. Esecuzione.

Un'opzione è Lua. Fornisce una sintassi per le unità di test (come mostrato sotto) che è più semplice rispetto agli altri linguaggi. Il codice da integrare è piccolo. Pluggandolo nel dpm proxy, raggiungi importanti obiettivi dei test accedendo ai risultati del protocollo. dpm proxy: http://consoleninja.net/code/dpm/README.html

Sintassi di Lua per le unità di testModifica

Il Testing Protocol deve passare per una traduzione dal linguaggio facilmente leggibile dagli esseri umani a Lua. Una possibile traduzione potrebbe essere simile alla seguente. Notare che questa sintassi non è stata testata

Le unità di test di Lua sono simili a quelle di Java. Documentazione: http://lua-users.org/wiki/UnitTesting

 -- L'unità di test parte
 require('luaunit')
 TestCase = {} --classe
 function TestCase:setUp() 
   --questa funzione è eseguita prima di ogni test
 end
 function TestCase:tearDown() 
   -- questa funzione è eseguita dopo ogni test
 end
 function TestCase:test1()
   rs = SQL("SELECT 1")
   assertEquals( rs.rows, 1 )
   assertEquals( md5(rs.???, "c4c43a9efab8cc70ee1fd9580693e1f2")
   assertEquals( type(rs.rows[1][1]), 'number' )
   assertEquals( rs.rows[1][1], 1)
 end
 luaUnit:run()

Domande & RisposteModifica

D: Come faccio a testare query non deterministiche? (esempio: EXPLAIN per Innodb) R: Le tue assertion non saranno una comparazione byte per byte (che si può fare con md5), puoi ricorrere a dei particolari pattern matching

Storia Modifica

La Test Suite di MySQLModifica

Il vecchio modo

 t/select.test
 ------
 SELECT 1 AS col
 ------
 r/select.result
 ------
 col 
 1
 ------

ProblemiModifica

  • Due file per ogni test
  • Di conseguenza le dimensioni crescono, i file dei risultati crescono
  • Supporto debole per i differenti storage engine
  • Ordinamento arbitratio non supportato (un risultato degli engine)
  • Valori non deterministici non supportati (esempio CURDATE())
  • Molti tipi unici di comandi aggiuntivi con sintassi --

Come funziona l'altra unità di test?Modifica

Usiamo junit (www.junit.org) come esempio per il test delle unità e la suite di tool che fornisce molti layer di test.

  • Una Suita comprende uno o più Test Cases
  • Un Test Case (file unico) ha uno o più test (@Test è l'annotazione usata)
  • Un Test Case può avere un setUp opzionare (@Before) e un tearDown (@After) che vengono eseguiti per ogni test che fa parte del Test Case
  • Ogni test ha un certo numero di comandi e un certo numero di assertion (tutte nel test), esempio: AssertEquals(x,1), AssertNotNull(var) etc
  • Esistono delle opzioni aggiuntive, per esempio per il timeout, la gestione degli errori, etc

Cosa occorre supportare Modifica

  • Gestione delle connessioni
  • Concorrenza
  • Ordinamento arbitrario (esempio: i risultati sono diversi per i diversi engine, ma contengono le stesse righe)
  • Astrazione dei pattern (es: ENGINE=MyISAM|InnoDB

Il vecchio modo:

 let $ENGINE=`select variable_value from information_schema.global_variables where variable_name='STORAGE_ENGINE'`;
 --replace_result $ENGINE ENGINE

Alcuni problemiModifica

Generalmente non teniamo tutto l'output dei risultati dei test. Se per esempio c'è una differenza con md5, e certi test fanno solo delle altre asserzioni che risultano positive, abbiamo perso i dati dei risultati sottostanti. Forse dovremmo tenere una versione serializzata degli effettivi risultati dei test per la comparazione. Ci può essere bisogno di un file testcase.data per ogni testcase.

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Inoltre su Fandom

Wiki casuale