Hvordan skal jeg enhet teste en kode-generator?

stemmer
23

Dette er en vanskelig og åpent spørsmål jeg vet, men jeg tenkte jeg skulle kaste den i gulvet og se om noen hadde noen interessante forslag.

Jeg har utviklet en kodegenerator som tar vår python-grensesnitt til vårt C ++ kode (generert via SWIG) og genererer kode for å avsløre dette som WebServices. Da jeg utviklet denne koden jeg gjorde det ved hjelp TDD, men jeg har funnet mine tester for å være sprø som faen. Fordi hver test egentlig ønsket å bekrefte at for en gitt litt innspill kode (som skjer for å være en C ++ header) jeg ville få en gitt bit av utsendt code Jeg skrev en liten motor som leser testen definisjoner fra XML input filer og genererer test saker fra disse forventningene.

Problemet er at jeg gruer går i å endre koden i det hele tatt. Det og det faktum at enheten tester selv er en: kompleks, og b: sprø.

Så jeg prøver å tenke på alternative tilnærminger til dette problemet, og det slår meg at jeg kanskje takle det på feil måte. Kanskje jeg må fokusere mer på utfallet, IE: ikke koden jeg generere faktisk kjøre og gjøre hva jeg vil ha det til, heller enn, ikke koden ser slik jeg vil ha det til.

Har noen fått noen erfaringer med noe som ligner på dette de ville vare å dele?

Publisert på 14/08/2008 klokken 13:59
kilden bruker
På andre språk...                            


8 svar

stemmer
12

Jeg begynte å skrive opp et sammendrag av min erfaring med min egen kode generator, deretter gikk tilbake og re-leser spørsmålet ditt, og fant du allerede hadde rørt på de samme problemene selv, fokusere på henrettelsen resultatene i stedet i koden layout / utseende.

Problemet er at dette er vanskelig å teste, den genererte koden kan ikke være egnet til å faktisk kjøre i miljøet av enheten testsystemet, og hvordan du koder de forventede resultater?

Jeg har funnet ut at du trenger å bryte ned koden generator i mindre biter og enheten test disse. Unit testing full kodegenerator er mer som integrasjonstesting enn enhetstesting spør du meg.

Svarte 14/08/2008 kl. 14:04
kilden bruker

stemmer
5

Husk at "enhetstesting" er bare en form for testing. Du bør være i stand til enheten test de interne delene av koden generator. Hva du virkelig ser på her er systemnivå testing (aka regresjonstesting). Det er ikke bare semantikk ... det er ulike tankesett, tilnærminger, forventninger, etc. Det er sikkert mer arbeid, men du trenger sannsynligvis å bite i kule og sette opp en ende-til-ende-regresjon test suite: faste C ++ filer -> SWIG grensesnitt -> python moduler -> kjent utgang. Du virkelig ønsker å sjekke den kjente inngang (fast C ++ kode) mot forventet produksjon (hva som kommer ut av den endelige Python program). Kontrollere code generator resultatene direkte ville være som diffing objektfiler ...

Svarte 14/08/2008 kl. 18:15
kilden bruker

stemmer
0

Jeg finner ut at du trenger å teste hva du genererer mer enn hvordan du genererer det.

I mitt tilfelle, genererer programmet mange typer kode (C #, HTML, SCSS, JS, etc.) som kompilere til en web-applikasjon. Den beste måten jeg har funnet å redusere regresjon bugs samlet er å teste web-applikasjon i seg selv, ikke ved å teste generator.

Ikke misforstå, det er fortsatt enhet tester sjekke ut noen av generatoren koden, men vår største igjen for pengene våre har vært UI tester på den genererte app selv.

Siden vi genererer det vi også generere en hyggelig abstraksjon i JS kan vi bruke til å auto teste app. Vi fulgte noen ideer skissert her: http://code.tutsplus.com/articles/maintainable-automated-ui-tests--net-35089

Den store delen er at det virkelig tester systemet ende-til-ende, fra kodegenerering ut til hva du faktisk genererer. Når en test mislykkes, er det enkelt å spore den tilbake til der generatoren brøt.

Det er ganske søt.

Lykke til!

Svarte 20/07/2015 kl. 04:10
kilden bruker

stemmer
0

Min anbefaling vil være å finne ut et sett av kjente u-resultater, for eksempel noen enklere saker som du allerede har på plass, og enheten test koden som blir produsert . Det er helt mulig at når du endrer generator som den nøyaktige strengen som produseres kan være litt annerledes ... men hva du virkelig bryr deg er om det tolkes på samme måte. Dermed, hvis du teste resultatene som du ville teste koden om det var din funksjonen, vil du finne ut om det lykkes på måter du ønsker.

Innerst inne, hva du virkelig ønsker å vite er om din generator vil produsere hva du forventer uten fysisk å teste alle mulige kombinasjoner (også: umulig). Ved å sørge for at generatoren er konsekvent i hvordan du forventer, kan du føle deg bedre at generatoren vil lykkes i stadig mer komplekse situasjoner.

På denne måten kan du også bygge opp en pakke med regresjon tester (enhet tester som må fortsette å jobbe på riktig måte). Dette vil hjelpe deg å sørge for at endringer i generatoren ikke bryter andre former for kode. Når du støter på en feil at enheten tester ikke ta, kan det være lurt å ta den for å hindre lignende brudd.

Svarte 25/07/2010 kl. 23:56
kilden bruker

stemmer
0

Enhetstesting er nettopp det å teste en bestemt enhet. Så hvis du skriver en spesifikasjon for klasse A, er det ideelt hvis klasse A ikke har reelle konkrete versjoner av klasse B og C.

Ok jeg merke etterpå koden for dette spørsmålet inkluderer C ++ / Python, men prinsippene er de samme:

    public class A : InterfaceA 
    {   
      InterfaceB b;

      InterfaceC c;

      public A(InterfaceB b, InterfaceC c)   {
          this._b = b;
          this._c = c;   }

      public string SomeOperation(string input)   
      {
          return this._b.SomeOtherOperation(input) 
               + this._c.EvenAnotherOperation(input); 
      } 
    }

På grunn av at ovennevnte System A injiserer grensesnitt til system B og C, kan enheten test bare system A, uten å ha reell funksjonalitet som utføres ved et hvilket som helst annet system. Dette er enhetstesting.

Her er en smart måte for nærmer seg et system fra skapelse til fullførelse, med en annen Når spesifikasjon for hver del av virkemåten:

public class When_system_A_has_some_operation_called_with_valid_input : SystemASpecification
{
    private string _actualString;

    private string _expectedString;

    private string _input;

    private string _returnB;

    private string _returnC;

    [It]
    public void Should_return_the_expected_string()
    {
        _actualString.Should().Be.EqualTo(this._expectedString);
    }

    public override void GivenThat()
    {
        var randomGenerator = new RandomGenerator();
        this._input = randomGenerator.Generate<string>();
        this._returnB = randomGenerator.Generate<string>();
        this._returnC = randomGenerator.Generate<string>();

        Dep<InterfaceB>().Stub(b => b.SomeOtherOperation(_input))
                         .Return(this._returnB);
        Dep<InterfaceC>().Stub(c => c.EvenAnotherOperation(_input))
                         .Return(this._returnC);

        this._expectedString = this._returnB + this._returnC;
    }

    public override void WhenIRun()
    {
        this._actualString = Sut.SomeOperation(this._input);
    }
}

Så i konklusjonen, kan en enkelt enhet / spesifikasjon har flere atferd, og spesifikasjonen vokser som du utvikle enheten / system; og hvis systemet under test avhenger av andre konkrete systemer i det, se opp.

Svarte 19/05/2010 kl. 23:17
kilden bruker

stemmer
0

Ville bare påpeke at du fortsatt kan oppnå finkornet testing mens verifisere resultatene: du kan teste individuelle biter av koden ved å hekke dem inne noen oppsett og bekreftelseskode:

int x = 0;
GENERATED_CODE
assert(x == 100);

Forutsatt at du har din generert kode sammen av mindre biter, og biter ikke endres ofte, kan du trene flere forhold og teste litt bedre, og forhåpentligvis unngå at alle testene i stykker når du endrer spesifikk av en blings.

Svarte 16/09/2008 kl. 09:41
kilden bruker

stemmer
0

Hvis du kjører på * nux kan du vurdere dumping unittest rammen i favør av et bash script eller Makefile. på vinduer kan du vurdere å bygge et skall app / funksjon som kjører generatoren og deretter bruker koden (som en annen prosess) og unittest det.

En tredje mulighet vil være å generere koden og deretter bygge en app fra det som inneholder noe annet enn en unittest. Igjen må du ha et shell script eller whatnot å kjøre dette for hver inngang. Om hvordan man skal kode forventet atferd, slår det meg at det kunne gjøres på samme måte som du ville gjort for C ++ kode bare å bruke den genererte grensesnitt i stedet for C ++ ett.

Svarte 14/08/2008 kl. 15:46
kilden bruker

stemmer
0

Ja, resultatene er det eneste som teller. Den virkelige chore er å skrive et rammeverk som gjør at generert kode kjøres uavhengig ... tilbringe tid der.

Svarte 14/08/2008 kl. 14:38
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more