Avatar billede macadisé Novice
23. juni 2015 - 22:13 Der er 10 kommentarer og
1 løsning

Endnu et test formulerings problem

For at teste at SugarContainer formindskes med én når SugarContainer bliver brugt, hvad skal der da skrives?

//The SugarContainer is withdrawed with one when the SugarContainer is used & an exception is casted when the SugarContainer is zero
[Test]
public void SugarContainerTest()
{
int SugarContainer = 10;

Console.Write("Test of sugar container countdown");
Assert.IsTrue(???);

throw new EmptyContainerException(SugarContainer = 0); 
}
Avatar billede softspot Forsker
23. juni 2015 - 23:10 #1
Du mangler at gøre noget ved SugarContainer for at en test skal give nogen mening (f.eks. via en metode på et objekt, hvor SugarContainer er en egenskab af type int).

Typisk vil målet for din test være denne funktion, hvor du efter kaldet til funktionen undersøger om SugarContainer-egenskaben på objektet har den forventede værdi.

Eksempelvis:

public class SugarContainer
{
    public SugarContainer(int initialLevel)
    {
        Level = initialLevel;
    }

    public int Level { get; protected set; }

    public void UseSugar(int units)
    {
        if(units > Level)
            throw new Exception("Not enough sugar");

        Level -= units;
    }
}

Din testcase kunne da se således ud:

[Test]
public void SugarContainerUsesSugarWhenOneUnitOfSugarIsUsed()
{
    var target = new SugarContainer(10);

    target.UseSugar(1);

    Assert.AreEqual(9, target.Level);
}

[Test]
public void SugarContainerThrowsExceptionWhenTooMuchSugarIsUsed()
{
    var target = new SugarContainer(10);

    try
    {
        target.UseSugar(11);
        Assert.Fail();
    }
    catch(Exception x)
    {
        Assert.AreEqual("Not enough sugar", x.Message);
    }
}

Jeg er klar over, at det sidste scenarium ikke er optimalt kodet. Der findes nok en smartere måde i dit testframework (givetvis noget med Assert.Throws). Jeg anvender normalt MSTest og kender derfor ikke metoden i dit testframework... beklager min uvidenhed.
Avatar billede macadisé Novice
24. juni 2015 - 11:35 #2
Det meste af det virker, men jeg kan dog ikke få parameterne til at virke, der fremkommer fejl når disse er implementeret.

Koden ser nu således ud:

        [Test]
        public void SugarCountDownTest()
        {
            var target = new SugarContainer(10);

            target.HasContent();

            Assert.AreEqual(9, target.Level);
        }
       
        //The RefillContainerTest shows if the suger container throws                          an exception when the container is empty!
        [Test]
        public void RefillContainerTest()
        {
            var target = new SugarContainer(10);

            try
            {
                target.HasContent();
                Assert.Fail();
            }
            catch (Exception x)
            {
                Assert.AreEqual("Not enough sugar", x.Message);
            }
        }

Jeg bruger Nunit test 2.6.4.

Og SugarContainer klassen ser således ud:

        public class SugarContainer : Container
    {
        /// <summary>
        /// Initiates container
        /// </summary>
        /// <param name="level">Init level</param>
        public SugarContainer(int level)
        {
            Level = level;
        }

        /// <summary>
        /// Get content from container
        /// </summary>
        public override void GetContent()
        {
            if (HasContent())
            {
                Level -= 1;
            }
            else
            {
                throw new EmptyContainerException("Not enough sugar.");
            }
        }

Og container klassen ser således ud:

public abstract class Container
    {
        // Minimum threshold value indicating when a container is empty
        protected const int MIN_CONTAINER_THRESHOLD = 1;

        // Current container level
        protected int containerLevel;       

        /// <summary>
        /// Container level (get/set)
        /// </summary>
        public int Level
        {
            get
            {
                return containerLevel;
            }
            set
            {
                containerLevel = value;
            }
        }

        /// <summary>
        /// Returns whether the chosen container has content
        /// </summary>
        /// <returns>True if there is content, otherwise false</returns>
        public bool HasContent()
        {
            return Level > MIN_CONTAINER_THRESHOLD;
        }

        /// <summary>
        /// Get content from container (no implementation)
        /// </summary>
        public abstract void GetContent();
    }


Håber du stadig har mod på det :-)
Avatar billede softspot Forsker
24. juni 2015 - 14:56 #3
Du ændrer jo ikke værdien af containerens level, så testene skal jo fejle...

Du spørger, i dine tests, blot på, om containeren indeholder noget.

Du bør, i dine tests, nok kalde GetContent i stedet for HasContent.

Desuden ville jeg gøre Level (set) protected i stedet for public, så det kun er klassen eller dens nedarvede klasser, der kan ændret denne egenskab (som jeg også indikerede i mit eksempel). Så har du i det mindste sikret dig, at Level ikke ændrer sig udenfor klassehierarkiet.

P.S. Dine kommentarer virker en smuler overflødige. Kommentarer er fine nok, hvis de tilfører koden nogen værdi ude over det koden tydeligt afspejler... :-)
Avatar billede softspot Forsker
24. juni 2015 - 15:07 #4
Du kan i øvrigt gøre din test af exception-tilfældet noget mere overskuelig ved at bruge ExpectedExceptionAttribute.

[Test]
[ExpectedException(typeof(Exception), ExpectedMessage="Not enough sugar")]
public void RefillContainerTest()
{
    var target = new SugarContainer(0);

    target.GetContent();
}

Bemærk, at jeg har initieret containeren med nul, så kaldet til GetContent bør rejse en kørselsfejl.

Læs mere om brugen af denne atribut på http://www.nunit.org/index.php?p=exception&r=2.4.8
Avatar billede macadisé Novice
25. juni 2015 - 14:49 #5
Det kunne jeg ikke lige umiddelbart få til at virke.
Avatar billede softspot Forsker
25. juni 2015 - 15:01 #6
Hvad har du gjort?

Læste du min kommentar i #3 (med kald af GetContent i stedet for HasContent)... eller læste du kun den sidste kommentar #4?
Avatar billede macadisé Novice
25. juni 2015 - 15:21 #7
Jeg læste dem begge. Jeg tror mit problem er noget med "reference" til de forskellige attributer, metoder og klasser...
Avatar billede softspot Forsker
25. juni 2015 - 15:51 #8
Kan du evt. vise den tilrettede kode og evt. forklare, hvad det er der ikke fungerer...?
Avatar billede macadisé Novice
25. juni 2015 - 19:30 #9
Snarest muligt :-)
Avatar billede macadisé Novice
15. juli 2015 - 10:23 #10
Lukker tråden.
Avatar billede softspot Forsker
15. juli 2015 - 15:05 #11
Jamen, velbekomme da!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester