Domanda

Supponiamo che stiamo progettando una classe stack-first (TDD):

public class Stack<T> {
    private T[] elements = new T[16];
    private int size = 0;
    ...
}

Questo stack utilizza un array interno di dimensioni 16 per archiviare i suoi elementi. Funzionerà bene fino a quando non dovrai aggiungere un 17 ° elemento. Dato che potrei aver bisogno di un 17 ° elemento, ho deciso di aggiungere quella funzionalità al mio stack, quindi ho iniziato a pensare a quale nome potrei fare al test che avrei fatto per aggiungere quella funzionalità. Quello sarà il mio argomento prima domanda.

Ho scelto per la prima volta la forma di:

Should_Be_Able_To_Correctly_Increase_Its_Inner_Array_Size()

poi

Should_Handle_More_Items_Than_The_Default_Internal_Array_Size()

Ma dopo aver pensato per un po 'sono giunto alla conclusione che forse qualcosa di simile al seguente sarebbe più appropriato:

Should_Double_Its_Size_Every_Time_Its_Full()

Il mio ragionamento dovrebbe farlo nel primo caso, sto dicendo solo quello che fa, ma non quando. Nel secondo, sto dicendo quando aggiungere più oggetti, ma sto anche affermando come sto pensando di raggiungerlo (internamente), il che potrebbe non essere corretto. A mio avviso (non sono sicuro di avere ragione), i miei test dovrebbero le possibili interazioni del mio SUT con l'esterno e non su come è implementato internamente. Ho ragione?

Mi sembra che le opzioni di terza sono le migliori, in quanto afferma chiaramente ciò che fa (crescere di dimensioni - in effetti, raddoppiare le sue dimensioni), quando lo fa (quando è pieno) e non mi lega a nessun specifico Implementazione (potrei forse voler in seguito cambiarlo in un arraylist interno!).

Il che mi porta al mio Seconda domanda: Supponendo che io abbia fatto tutti i test unitari per la mia classe di stack che utilizza internamente un array e funziona bene e come previsto, se i miei test rimanessero intatti se in seguito voglio rifactare e cambiare l'array in un arraylist o qualsiasi altro tipo di dati -struttura? O i test dovrebbero in qualche modo rifletterlo? Immagino di no, ma non ne sono sicuro.

È stato utile?

Soluzione

In my view (I'm not sure I am correct), my tests should the possible interactions of my SUT with the exterior, and not on how it is implemented internally. Am I right?

You are correct. If you change the internal implementation of your class, the unit tests should remain the same. If you expose anything new externally, you should create new unit tests to account for these changes.

Remember that when you're designing your class you don't want to expose anything that indicates how it was implemented. The class' public members indicate how to interact with it, now how it works behind the scenes.

Altri suggerimenti

I am not sure how you can the test the internal list or array size through a unit test. You can't access it through the Stack interface. Unit testing is for testing external contracts. If you want to test implementation details then try something else.

The answer to your 2nd question is yes, the test should still pass, if it's a unit test.

Ask yourself to what you are willing to commit for this class.

Do you or the class' consumers really care whether the capacity doubles, increments by one, or increments by one thousand? If so, you should modify the interface so that they can specify the strategy used to increase capacity:

public Stack<T>(CapacityGrowthStyle capacityGrowthStyle) { ... }

If not, just write tests to document the capacity and leave it at that (where X below is your underlying data structure's limit):

[Test]
public void Can_Handle_X_Items() { ... }

[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void Cannot_Handle_More_Than_X_Items() { ... }

I'd answer your second question similarly: your tests should only reflect the underlying data structure if your class' users will care about it.

I'm not sure if you should test the internal list or array size through a unit test, since you cannot access it through the Stack interface. There are many ways to implement a stack, some good, and some bad, but as Bernard stated, those are internal implementations. Unit tests are designed to test outward facing functionality.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top