2012-06-30 5 views
5

Esistono diversi strumenti su come generare dati di esempio per una determinata espressione regolare. Alcuni includono:Generazione di dati di esempio da regex per verificare le stringhe di input concentrandosi su casi limite definiti in regex

Tuttavia, mentre essi possono essere sufficienti per seminare un set di dati, non aiuta il codice di prova tanto che dipende la regex stesso, come la convalida .

Si supponga di avere un generatore di codice che genera un modello con una proprietà. L'utente specifica un'espressione regolare per convalidare la proprietà. Supponiamo ora che il generatore di codice stia tentando di generare test per garantire che la convalida abbia esito positivo e fallisca in modo appropriato. Sembra ragionevole che lo strumento si concentri sui casi limite all'interno della regex per evitare di generare dati non necessari.

Ad esempio, si consideri una regex ^([a-z]{3,6})$ poi i casi limite comprendono:

  • qualsiasi stringa costituita esclusivamente da [az] una lunghezza pari a 2 (guasto)
  • qualsiasi stringa costituita esclusivamente da [az] una lunghezza pari a 3 (successo)
  • qualsiasi stringa costituita esclusivamente da [az] una lunghezza pari a 4 (successo)
  • qualsiasi stringa costituita esclusivamente da [az] una lunghezza pari a 5 (successo)
  • un stringa ny costituito solo [az] una lunghezza pari a 6 (successo)
  • qualsiasi stringa costituita esclusivamente da [az] una lunghezza pari a 7 (guasto)
  • qualsiasi stringa non costituito [az] (guasto)
  • qualsiasi stringa non inizia con [az] ma finisce con [az] (guasto)
  • qualsiasi stringa che inizia con [az] ma non termina con [az] (guasto)

La ragione concentrandosi sul confine casi è che qualsiasi stringa che consiste solo di [az] con una lunghezza maggiore di 6 verifica il limite superiore della lunghezza della stringa definita nella regex. Quindi testare una stringa di lunghezza 7, 8, 9 sta davvero testando la stessa condizione (limite).

Questa era una regex arbitraria scelta per la sua semplicità, ma qualsiasi ragionevole regex può agire come input.

Esiste un framework/strumenti che il generatore di codice può utilizzare per generare stringhe di input per i casi di test dei diversi livelli dei sistemi generati. I casi di test arrivano da soli quando il sistema non viene più generato e modificato successivamente nel ciclo di sviluppo.

+0

Qual è il punto di questo? Stai provando se la tua regex lib funziona correttamente? O stai scrivendo qualche convalida alternativa (senza regex) e la regex originale è l'unica specifica su cosa sia valido o no? – Qtax

+0

Lo scopo principale è generare test che verifichino la logica di validazione generata dal generatore di codice. Quindi, quando il generatore di codice non viene più utilizzato e lo sviluppatore cambia la logica di convalida, un test potrebbe non riuscire a indicare che potrebbe esserci una regressione. I test non presuppongono che una regex venga utilizzata per la convalida. – bloudraak

+0

L'espressione regolare può essere utilizzata anche in diversi livelli del sistema, ad esempio JavaScript non invadente nel browser, applicazione desktop (WPF), Cmdlet PowerShell, modelli MVC ASP.NET e servizi WCF. Il generatore di codice genera test per verificare che ciascuno esegua la convalida prima di inviare i dati al sistema remoto. – bloudraak

risposta

1

Se ho compreso correttamente la tua domanda, vuoi generare un input per il sistema basato sulla regex di validazione in modo da poter automatizzare il test dell'unità.

Non è questo a sconfiggere lo scopo dei test di unità? Se qualcuno cambia la regex, non vuoi che la convalida fallisca?

In ogni caso, la semplice risposta è che la generazione di una stringa da una regex è quasi impossibile. Se potesse essere fatto, sarebbe estremamente complesso.Ad esempio, si consideri questo regex:

(?<=\G\d{0,3})(?>[a-z]+)(?<=(?<foo>foo)|)(?(foo)(?!)) 

E 'molto semplice per me pensare di una stringa che sarebbe partita (e/o generare partite):

abc123def456ghi789jkl123foo456pqr789stu123vwx456yz

Il le corrispondenze sarebbero:

  • "abc"
  • "def"
  • "ghi"
  • "jkl"

Ma come è possibile generare una stringa dall'espressione? Non c'è un chiaro punto di partenza: richiede un'intelligenza estrema (per un computer) più un pizzico di creatività per elaborare una soluzione. Qualcosa di semplice per un umano, ma molto, molto difficile per un computer. Anche se si potrebbe venire con un algoritmo informatico che avrebbe generato una stringa corrispondente, potrebbe facilmente essere simile a questa:

un

Questo genera un match, ma fa un pessimo lavoro di esercitare la regex. Lo \d{0,3} non viene mai realmente provato e lo \G viene sempre utilizzato solo per corrispondere all'inizio dell'input (anziché alla fine dell'ultima corrispondenza). (?<=(?<foo>foo)) non viene mai testato (e se lo fosse, risulterebbe in una non corrispondenza).

Sarebbe anche facile da generare una stringa che non corrisponde:

Ma, ancora una volta, questo non davvero messo la regex attraverso i suoi passi.

Non conosco abbastanza bene la teoria del computer per dimostrarlo, ma credo che questo cada nel P v NP class of problems. È relativamente facile generare un'espressione regolare per abbinare una raccolta di stringhe complesse, ma è difficile generare una raccolta di stringhe complesse per abbinare un'espressione regolare.

+0

Per quanto riguarda i test delle unità, nessuno dice che tutto deve essere scritto manualmente. Uso spesso PEX per generare test unitari per complimentarmi con quelli che ho scritto. Garantisce una logica che non ho mai pensato è coperto, evidenzia gli effetti collaterali come eccezioni indesiderate e, di conseguenza, migliora l'affidabilità del mio codice. Lo stesso vale per le espressioni regolari ... – bloudraak

+0

@WernerStrydom - Ok, posso accettarlo. – JDB

Problemi correlati