Come dovrei unità testare un metodo di modifica bitmap?

6

La mia classe Sprite ha un metodo:

private void updateWithBitmap(Bitmap b, int x, int y)

Questo 'posiziona sopra' la bitmap che è stata passata, l'angolo in alto a sinistra della bitmap passata essendo in posizione x, y della bitmap padre.

Ora voglio test delle unità di scrittura per verificare che questo metodo funzioni correttamente.

Ad esempio, dovremo controllare che venga generata un'eccezione quando la bitmap passata è più grande, oppure è fuori dai limiti della bitmap padre.

    [TestMethod]
    [ExpectedException(typeof(System.ArgumentOutOfRangeException))]
    public void TestUpdateWithBitMap_SmallerParent_ThrowsOutOfRangeException()
    {
       Sprite parent =  new Sprite(new Bitmap(10,10));
       Bitmap child = new Bitmap(20, 20); 
       parent.updateWithBitmap(child,0,0)


    }

    [TestMethod]
    [ExpectedException(typeof(System.ArgumentOutOfRangeException))]
    public void TestUpdateWithBitMap_PassedBitMapOutOfBounds_ThrowsOutOfRangeException()
    {
        Sprite parent =  new Sprite(new Bitmap(10,10));
        Bitmap child = new Bitmap(3, 3); 
        parent.updateWithBitmap(child, 9,9)


    }

Bene finora.

Ma vogliamo anche verificare che il metodo sia aggiornato correttamente.

Ad esempio, se l'immagine più a sinistra è la nostra bitmap padre e la metà è la bitmap figlio e chiamiamo il nostro metodo con:

parent.updateWithBitmap(child, 3,3);

otteniamo la bitmap più a destra di conseguenza.

La domanda è:

È appropriato archiviare questi bitmap come risorse e quindi controllare che i risultati siano uguali?

ad es.

    [TestMethod]        
    public void TestUpdateWithBitMap_UpdatesCorrectly()
    {
        Sprite parent =  new Sprite(Properties.Resources.TestBitmapParent1);
        Bitmap child = Properties.Resources.TestBitmapChild1; 
        parent.updateWithBitmap(child, 3,3)
        #something like Assert.Equal(parent.getBitmap(), Properties.Resources.TestBitmapResult1); 



    }
    
posta dwjohnston 20.06.2014 - 06:49
fonte

3 risposte

4

Is it appropriate to store these bitmaps as resources

Bene, qualunque cosa funzionerà per te è appropriata, non è vero? I test delle unità dovrebbero essere veloci, funzionali, dovrebbero essere facili da mantenere e ampliare e, se falliscono, dovrebbero rendere più semplice l'analisi delle cause alla radice.

  • "veloce" può essere soddisfatto utilizzando bitmap molto piccoli

  • "funzionale": per includere casi significativi, le bitmap non devono essere effettivamente troppo piccole. Per il tuo caso, immagino che le bitmap con una lunghezza laterale di minimo 3 o 4 abbiano probabilmente un senso.

  • facile da mantenere e da estendere: beh, finché il tuo set di strumenti consente una facile manipolazione di bitmap, la memorizzazione di bitmap in una risorsa e il recupero di nuovo, non dovrebbe essere molto un problema

  • "semplifica l'analisi della causa principale": per questo, potrebbe essere necessario fare alcune disposizioni. Se solo "controlli se i risultati di un confronto bitmap sono uguali", potresti non vedere facilmente come appare il tuo "testBitmap" e perché non corrisponde ai risultati attesi. Ma dovrebbe essere piuttosto semplice aggiungere del codice che nel caso in cui il test di uguaglianza fallisca, scrive la tua bitmap di prova su disco in modo da poterlo controllare facilmente con un visualizzatore di immagini (sia visivamente, sia creando qualcosa come una "immagine di differenza" tra la bitmap prevista e la bitmap di test)

Ovviamente, l'alternativa sarebbe quella di creare alcuni test per pixel con colori e coordinate codificati, ma anche se funzionerà sicuramente, IMHO non è più facile da mantenere e può diventare molto noioso.

Alcuni post correlati su altri siti SE:

link

link

    
risposta data 20.06.2014 - 08:22
fonte
0

Come ho capito, stai usando il tuo sprite personalizzato e non qualche sprite da DirectX o da DirectXMobile .

Che cosa potresti provare:

1) Se la tua classe fornisce un indicizzatore per pixel come SomeColorInfo this[int x, int y] o il metodo ToBitmap() :

Potresti provare a usare il genitore e il bambino piccoli (come pochi pixel per pochi pixel) dove potresti calcolare manualmente tutti i pixel desiderati e confrontare le immagini risultanti e desiderate (sprite). Ad esempio, supponendo per semplicità che si utilizzino immagini in scala di grigi:

[TestMethod]
void Test_Sprite_UpdateWithBitmap_GreyScaleSprite3x3_GreyScaleBitmap2x2()
{
    // Create 3 x 3 greyscale Sprite from 
    Sprite sprite = new Sprite(3, 
    3, 
    new Byte { 
    1, 2, 3,
    4, 5, 6,
    7, 8, 9});

    // Create 3 x 2 bitmap to update with
                Bitmap bitmap = new Bitmap(2, 
    2, 
    new Byte { 
    101, 102
    103, 104});

    // Coordinates of update point
    Int32 x = 1;
    Int32 y = 1;

    // Expected sprite
    Sprite expectedSprite =  new Sprite(3, 
    3, 
    new Byte { 
    1, 2, 3,
    4, 101, 102,
    7, 103, 104});

    // Update  sprite
    sprite.updateWithBitmap(child, 3,3);

    // Assert
    CollectionAssert.AreEqual(expectedSprite, sprite);
}

Bene il tuo sprite e bitmap dovrebbero avere costruttori come Sprite(Int32,Int32, IEnumerable<Byte>); e il tuo Sprite dovrebbe essere IEnumerable (dovrai solo fare sprite.ToList() nell'asserzione) o ICollection

2) Se il tuo sprite non può essere calcolato (dipinto) se non nell'ambiente di interfaccia utente reale o se non vuoi aggiungere membri non necessari, dovresti prendere in considerazione un modo per ottenere i suoi pixel attraverso altri canali. Non so quale interfaccia utente usi, ma la maggior parte fornisce una sorta di PaintingContext per i tuoi oggetti di disegno personalizzati. Tale oggetto può essere un'interfaccia come:

public interface IPaintingContext : IDisposable
{
    void PutPixel(Int32 x, Int32 y);

    void PutImage(IImage image);

    //... And so on
}

che ti permetterà di prenderlo in giro e usarlo nel tuo metodo di test come:

...
IPaintingContext expectedPaintingContext = new MockPaintingContext(3, 3, new Byte[]{...});
...
IPaintingContext paintingContext = new MockPaintingContext();
...
sprite.PaintOn(paintingContext);
...
CollectionAssert.Assert(expectedPaintingContext, paintingContex);

Se il tuo ambiente fornisce tale funzionalità in modo non un'interfaccia, puoi creare la tua infrastruttura personalizzata di questo tipo: IPaintingContext context = new MyUiPaintingContextWrapper(UI.GetPaintingPlane())

    
risposta data 20.06.2014 - 07:46
fonte
0
  > Is it appropriate to store these bitmaps as resources, 
  > and then check the results are equal?

A mio parere direi di si, ma invece di codificare questi confronti personalmente userò approvaltests per dotnet o java per questo.

Quindi, invece di nascondere il confronto bitmap dietro un metodo junit-test, il test di approvazione mostra ogni risultato del test in cui le bitmap non sono più uguali al tester, chi può decidere che questo risultato sia ok o non sia ok. se è ok il risultato atteso viene sovrascritto.

così alla prossima esecuzione l'approvaltest non si lamenterà più.

    
risposta data 20.06.2014 - 16:54
fonte

Leggi altre domande sui tag