Test dell'unità con un problema di ottimizzazione

3

Supponiamo che sto facendo un algoritmo che identifica il soggetto di una foto. Potrebbe essere qualsiasi cosa che un computer non funzioni bene, ma non mi aspetto di ottenere sempre la risposta giusta: l'80% va bene. Supponiamo inoltre che l'accuratezza dei passaggi intermedi sia anche alquanto sfocata. C'è un modo per incorporare i test unitari?

L'opzione che viene immediatamente in mente è quella di aggiungere 1 a un conteggio e ogni volta che passa un "test", incrementare il conteggio. Quando finisce, dividi per il totale e prova 'passa / test > 0.8 ', ma sembra kludgey.

EDIT: Grazie a tutti per le vostre parole gentili e le risposte ben motivate. Il mio problema particolare, mentre è confuso, non ha nulla a che fare con le immagini e attualmente sto ottenendo circa l'80% di pass. Il valore a breve termine per me in uno schema di test sarebbe sapere se i piccoli aggiustamenti fossero più vantaggiosi a livello globale o catastrofici. Il valore del test a lungo termine dovrebbe essere ovvio.

    
posta user121330 25.02.2014 - 22:46
fonte

6 risposte

3

Come altri hanno notato, TDD si concentra principalmente sui test unitari. Tuttavia, ciò non significa che i test di integrazione black-box non dovrebbero essere coperti. Né dovrebbe necessariamente coprire la stessa natura deterministica di un test unitario.

In termini di test unitario

Supponendo che nulla nel tuo algoritmo sia casuale, dovrebbe essere possibile scrivere unit test per i componenti del tuo software che superano il 100%. Non ci dovrebbero essere motivi per cui è necessario raggiungere un punteggio dell'80%.

Tuttavia, questi test sono specifici dell'implementazione dell'algoritmo, per loro stessa natura. Con un dato input ci si aspetterebbe sempre lo stesso risultato. Descrivi la situazione in cui le cose porteranno a una partita e le situazioni in cui si allontanerebbero da una partita.

Se l'algoritmo cambia, ti aspetteresti che anche alcuni dei test unitari cambino.

In termini di test dell'integrazione black-box

Sembra che ci possa essere un requisito per un test lungo le linee di:

  • Dato questo set di immagini x, mi aspetto una percentuale di corrispondenza positiva dell'80%
  • Non m'importa quale abbia una corrispondenza positiva, solo che la soglia è stata raggiunta.

Dovresti eseguire ogni immagine, verificare se il tuo algoritmo ti ha dato una corrispondenza con il risultato previsto o meno. Tieni un conto e segna, secondo il tuo suggerimento.

Questo test descrive i requisiti funzionali minimi dell'algoritmo e sarebbe completamente indipendente dall'implementazione.

Quindi sì, sembra un test del tutto appropriato e una misura del successo di tutto il software.

    
risposta data 26.02.2014 - 18:50
fonte
6

TDD non è una tecnica di progettazione.

Mentre può aiutare a produrre un design efficace (e convalidare la veridicità di quel progetto, e verificare che il tuo software funzioni ancora dopo il refactoring), devi comunque pensare alla struttura dei tuoi programmi e trovare una sorta di rappresentazione algoritmica per i problemi specifici che stai cercando di risolvere.

Non puoi semplicemente aspettarti che una soluzione a un problema informatico non banale emerga organicamente da un refact rosso-verde, specialmente se questo problema riguarda l'euristica. Naturalmente, se hai qualche idea su come la soluzione emergerà, puoi modellare questa idea con i test unitari, ma non puoi aspettarti di ottenere perle dalla sabbia se non hai nemmeno una vongola.

In ogni caso, non puoi avere un test che superi l'80% delle volte e chiamare un test unitario di successo. Quello che puoi fare sono cinque test, quattro dei quali producono un risultato, e uno dei quali produce l'altro, o un test che restituisce alcuni parametri (diversi da passaggi / fallimenti) che puoi affermare essere 0.8. Ciò fornisce il tuo rapporto dell'80%, pur mantenendo gli stati "vai, non-vai".

    
risposta data 25.02.2014 - 22:56
fonte
6

A meno che il tuo codice non usi una tecnica randomizzata, è deterministico, anche se per un dato input è difficile specificarlo o prevederlo. Quindi, quando vediamo un dato input produrre un dato risultato, se forniamo lo stesso input vedremo di nuovo lo stesso risultato. Questo è vero anche per un algoritmo di apprendimento o un'applicazione di database, in cui "lo stesso input" indica lo stesso input applicato al sistema nello stesso stato.

Se il tuo algoritmo utilizza una tecnica randomizzata, l'approccio abituale è quello di disattivare l'aspetto di seme casuale di esso per il test, in modo che i test diano sempre lo stesso risultato "casuale". (Non inseriremo il codice nel codice sorgente, perché il codice dovrebbe essere modificato e testato di nuovo ogni volta che abbiamo eseguito il test e così via).

Quindi dovresti avere una serie di test ripetibili. Per lo stesso input allo stesso algoritmo dovresti vedere lo stesso risultato.

Ma sembra che tu stia confondendo la natura confusa del tuo algoritmo con il non-determinismo. Anche un algoritmo fuzzy dovrebbe dare gli stessi risultati dagli esatti stessi input.

Un secondo problema sembra essere che l'algoritmo è ancora in fase di sviluppo. Questo presenta lo stesso problema della regressione testando qualsiasi codice in sviluppo. Con semplici modifiche al codice dovresti essere in grado di prevedere l'effetto sui casi di test esistenti. Ma a causa della complessità dell'analisi del codice di logica fuzzy potresti non essere in grado di prevedere il risultato preciso del cambiamento. In questo caso, è possibile documentare ogni test con il suo risultato rispetto a ciascuna versione del codebase e preparare test modificati che sfruttano le modifiche dell'algoritmo.

    
risposta data 26.02.2014 - 11:09
fonte
1

TDD di solito parla di unit test, che possono essere test white-box. Stai parlando di un test di integrazione black-box.

Ad un certo punto avrai un vero algoritmo. Se funziona correttamente, passerà alcuni input e fallirà altri. Questo è ciò che test. Se ottiene l'80% giusto dipenderà dagli input testati. Indipendentemente dal fatto che il risultato sia accettabile per gli input reali del mondo reale che incontrerai non sarà qualcosa che i tuoi test unitari copriranno, anche se potresti ovviamente ottenere un campione di input reali e metterli alla prova con i metodi di primo livello.

    
risposta data 25.02.2014 - 23:07
fonte
1

Per questo tipo di problemi, forse un approccio interiore al TDD può essere più efficace. Probabilmente hai bisogno di diverse parti deterministiche per costruire la tua soluzione completa, puoi costruire quelle parti con il TDD "normale".

Inoltre puoi fare un test completo del tuo algoritmo usando un set predefinito di immagini, con questo puoi controllare se i risultati raggiungono qualche soglia. Con questo puoi verificare questa soglia ad ogni cambio, le parti più difficili è forse selezionare le raccolte di immagini che rappresentano i diversi possibili scenari in cui si suppone che il tuo algoritmo dia buoni risultati.

Con questo secondo test non puoi andare passo passo per la progettazione e l'algoritmo, sono davvero utili per verificare gli scopi ma non sono realmente utili per la progettazione e l'algoritmo. TDD non è una tecnica per la progettazione di algoritmi come il classico esempio di sudoko di Ron Jeffries (uno dei membri originali del team Kent Beck C3 che ha reso popolare la tecnica TDD).

Nel curriculum, puoi usare TDD per costruire e forse progettare alcune delle piccole parti multiple di cui ha bisogno l'algoritmo completo, e puoi usare un semplice test per verificare il comportamento, ma usare TDD per costruire un algoritmo completo non è "magico" , è necessario studiare le diverse tecniche per la costruzione di algoritmi.

    
risposta data 25.02.2014 - 23:15
fonte
1

Se il tuo algoritmo sta per "fallire" l'80% delle volte, come fai a sapere che funziona? È per la stessa immagine o l'80% delle immagini non funzionerà con il tuo algoritmo? Se la stessa immagine non funziona, come è possibile che tu sappia che non è un problema nel tuo algoritmo?

TDD formalizza la tua procedura di codifica, in quanto hai il codice di prova che usi per verificare che il tuo codice funzioni come previsto. Quando stai codificando il tuo algoritmo, lo esegui con alcune immagini per vedere quali sono i risultati, giusto? TDD vorrebbe scrivere qualcosa che automatizzasse quel processo per te. In questo modo, non dimentichi di eseguire un test case o diventare pigro e saltare alcuni perché i "test" diventano ripetitivi.

Per il tuo algoritmo, la stessa immagine dovrebbe finire con gli stessi risultati ogni volta non dovrebbe? Oppure, se stai usando un generatore casuale che causa il non-determinismo, la stessa immagine e lo stesso seme dovrebbero produrre gli stessi risultati più e più volte. Sarebbe anche in grado di fornire un esempio di un'immagine che "fallirebbe" e come se passi questo è un segno di un bug nell'algoritmo.

I tuoi test sono un'automazione di come verificherai che il programma funzioni come tu lo intendi.

Ad un certo livello, la maggior parte dei programmatori pratica TDD. Semplicemente non scrivono / programmano i loro test in modo che altri possano usarli.

    
risposta data 25.02.2014 - 23:24
fonte

Leggi altre domande sui tag