D E V M A T E

Loading

Generate Test Code

You are here:
Estimated reading time: 4 min

You can use the “Generate Test Code” button to generate executable code from the test model.

Structure of Generated Code

In this section we describe the structure of the generated test code in detail. As an example we use the test code generated from the test model “avgspeed.tmdl”.

The test code is composed of the following elements, the generated test code also listed at the bottom of this chapter:

Test model id comment

This comment is used to refer back to the test model from which this test code was generated. To enable this back referencing, this comment must not be changed under any circumstances.

/*
* DO NOT MODIFY THIS COMMENT
* Generated by devmate
* Test model: a8d26c27-a654-4d6d-857e-3e53b2919d0b
*/

Test Class

This is the test class which contains the test cases. The name of this class consists of the name of the method to be tested and the suffix “TestCase”.

public class AverageSpeedTestCase
{
    ...
}

Custom Factory Method

If custom factory methods are defined for the creation of complex data types, such as for the creation of a sensor stub, these are specified first in the test class. A custom factory method gets the name defined in the Equivalence Class Editor including the prefix “Create”. In the body of the method, a comment is written to remind you to revise the method to return the desired object. Additionally a NotImplementedException gets thrown.

private static AvgSpeed.ISpeedSensor CreateSensorStub()
{
    // TODO implement factory
    throw new System.NotImplementedException();
}

In our example we have adapted the method and return a stub object.

private static AvgSpeed.ISpeedSensor CreateSensorStub()
{
    return new Mock<AvgSpeed.ISpeedSensor>().Object;
}

Test Case Sources

The tests created by devmate are also called parameterized test cases. The special thing about this type of test is that the values for these tests are given as a source. In our example the methods “AverageSpeedTest” and “AverageSpeedTestThrowingException” are the test methods and “PositiveTests” and “TestsThrowingException” contain the data for the tests. For each line starting with the contextual keyword “yield”, one record is returned that causes the test method to execute a test.

 In addition to the test values, meta information is set for each data set, such as the test case name, for example “p1”, and a description which can be set in the Equivalence Class Editor.

private static IEnumerable<TestCaseData> PositiveTests()
{
    yield return new TestCaseData(new AvgSpeed.Speedometer(CreateSensorStub(), CreatePreferences(UnitsNet.Units.SpeedUnit.KilometerPerHour)), new UnitsNet.Duration(2, UnitsNet.Units.DurationUnit.Hour), CreateTrackStub(60, UnitsNet.Units.LengthUnit.Kilometer), new UnitsNet.Speed(30, UnitsNet.Units.SpeedUnit.KilometerPerHour)).SetName("p1").SetDescription("");
}

Test Case Method

The test case method gets as input the test data from the test case sources and executes the test. The test case method is characterized by the annotation “[Test]” and by the reference to the test case source “[TestCaseSource(“…”)]”. For positive, negative and for tests that expect an exception, separate test case methods and test case sources are generated.

[Test]
[TestCaseSource("PositiveTests")]
public void AverageSpeedTest(AvgSpeed.Speedometer instance, UnitsNet.Duration duration, AvgSpeed.ITrack track, UnitsNet.Speed expected)
{
    UnitsNet.Speed actual = instance.AverageSpeed(duration, track);
    Assert.AreEqual(expected, actual);
}

Data comment

This comment is necessary to merge your manual changes to the test code with your changes deriving from the Equivalence Class Editor. It is important that you do not change this comment.

/*
WARNING: Modification of this comment will make it impossible to merge user-defined changes
 
BEGIN_CODEGEN_DATA
H4sIAAAAAAAAAN2WW2/aMBTHn4vEd7B4ChWEAoXe1koIaIs2LhLZwzTtISSn1GqwM9uhZdO++44NoSmh
Wdut2jqJi2P7+PzP75zYruzmc7ukMySDoUP6w07v/BNxLntj0h72+92Bo0cvgIFwFfhksiBO+0L3OSBV
T8HsmLiHfq3p1Q7KbrOxX973m375sHEA5To06pPaUfXI35ugRSWfy+ciSdmUjBcSLe02DwLwFOVM2sYF
9U7iKYOPjCr7XLgzuOXi5uSh6YleK4wmAfWIF7hSktYcFU5hHAL4WlrblZDPfc/ndkJB56idSOUqnN6a
T80ku2f+xsAkF6QtAOcsH8YqmlhFtNTWO5UKcYaIh87CAGbAFLlyPcXFQg+qa8FvCYPbOKQBV714Ivjd
Ow9CHZ9VRMU7P/CbIWgk4AoEMA/kSk+ix9I85ACUbRq2MdFNEppJAkMJTcdfUN5zhOvdrESbtmG4WrnH
VL1G5m4QQYlshPEB2FRdmzii19Oelt7rsmiGFTMJ4F1cLh1XuWdkxCVVdA66V96XwYJC4BMBKhLMuE5a
WbpjTcP88hkoEFa6rkrPyK39ngbLhUYgLnkkimiufa0NOhG+lzrUWgptPGQWMsalVIaaexkZufe+6dUI
tOpp4yzl9hjUAF9nqxBWC+apA9ITdJmqQiGj0B7PlsmSo+sBN4dE4t9K2n4rJ2oRAr+yWmIa6cpfh59k
zbax9lfuj8k3EHxJ/p9HVa5ml3ifskjB6wOtZQJlMHX19vFGoL5s28gE2kZy9FlE61uIKu3sTdXny1CW
q5kwzzlXT8W4/zjG/7IqWRQEKTQD7NyOp5GBB41GnOLlQSSPIfz5rMl8iRsa0Ride7jeg3tCoajnrC6k
c0791H3U2kaUUIYnHFIrpSGQeE8ppe5ZRnVp4zgmcBfiZRr89dm3MY73p8gNyOnaqZ3UaN27M8svC6Ul
JQhltwR0v6KxFfsorVZLntmPo9p+SP+aWfpc//MQHSyfNLpV3EaATERtFcnp2RMBxmzw8xMUKl7eZA0A
AA==
END_CODEGEN_DATA
*/

Here again the whole file:

/*
* DO NOT MODIFY THIS COMMENT
* Generated by devmate
* Test model: a8d26c27-a654-4d6d-857e-3e53b2919d0b
*/
 
using System.Collections.Generic;
using NUnit.Framework;
using System;
 
public class AverageSpeedTestCase
{
    private static AvgSpeed.ISpeedSensor CreateSensorStub()
    {
        // TODO implement factory
        throw new System.NotImplementedException();
    }
     
    private static AvgSpeed.Preferences CreatePreferences(UnitsNet.Units.SpeedUnit preferredSpdUnit)
    {
        // TODO implement factory
        throw new System.NotImplementedException();
    }
     
    private static AvgSpeed.ITrack CreateTrackStub(System.Int32 value, UnitsNet.Units.LengthUnit unit)
    {
        // TODO implement factory
        throw new System.NotImplementedException();
    }
 
    private static IEnumerable<TestCaseData> PositiveTests()
    {
        yield return new TestCaseData(new AvgSpeed.Speedometer(CreateSensorStub(), CreatePreferences(UnitsNet.Units.SpeedUnit.KilometerPerHour)), new UnitsNet.Duration(2, UnitsNet.Units.DurationUnit.Hour), CreateTrackStub(60, UnitsNet.Units.LengthUnit.Kilometer), new UnitsNet.Speed(30, UnitsNet.Units.SpeedUnit.KilometerPerHour)).SetName("p1").SetDescription("");
    }
     
    private static IEnumerable<TestCaseData> TestsThrowingException()
    {
        yield return new TestCaseData(new AvgSpeed.Speedometer(CreateSecondSensorStub(), CreatePreferences(UnitsNet.Units.SpeedUnit.KilometerPerHour)), new UnitsNet.Duration(), CreateTrackStub(60, UnitsNet.Units.LengthUnit.Kilometer), typeof(ArgumentException)).SetName("n1").SetDescription("duration: zero");
        yield return new TestCaseData(new AvgSpeed.Speedometer(CreateSecondSensorStub(), CreatePreferences(UnitsNet.Units.SpeedUnit.KilometerPerHour)), new UnitsNet.Duration(-1, UnitsNet.Units.DurationUnit.Minute), CreateTrackStub(60, UnitsNet.Units.LengthUnit.Kilometer), typeof(ArgumentException)).SetName("n2").SetDescription("duration: negative");
        yield return new TestCaseData(new AvgSpeed.Speedometer(CreateSecondSensorStub(), CreatePreferences(UnitsNet.Units.SpeedUnit.KilometerPerHour)), new UnitsNet.Duration(2, UnitsNet.Units.DurationUnit.Hour), CreateTrackStub(0, UnitsNet.Units.LengthUnit.Centimeter), typeof(ArgumentException)).SetName("n3").SetDescription("track: zero");
        yield return new TestCaseData(new AvgSpeed.Speedometer(CreateSecondSensorStub(), CreatePreferences(UnitsNet.Units.SpeedUnit.KilometerPerHour)), new UnitsNet.Duration(2, UnitsNet.Units.DurationUnit.Hour), CreateTrackStub(-10, UnitsNet.Units.LengthUnit.Foot), typeof(ArgumentException)).SetName("n4").SetDescription("track: negative");
        yield return new TestCaseData(new AvgSpeed.Speedometer(CreateSecondSensorStub(), CreatePreferences(UnitsNet.Units.SpeedUnit.KilometerPerHour)), new UnitsNet.Duration(2, UnitsNet.Units.DurationUnit.Hour), null, typeof(ArgumentNullException)).SetName("n5").SetDescription("track: nullPointer");
    }
     
 
    [Test]
    [TestCaseSource("PositiveTests")]
    public void AverageSpeedTest(AvgSpeed.Speedometer instance, UnitsNet.Duration duration, AvgSpeed.ITrack track, UnitsNet.Speed expected)
    {
        UnitsNet.Speed actual = instance.AverageSpeed(duration, track);
        Assert.AreEqual(expected, actual);
    }
     
    [Test]
    [TestCaseSource("TestsThrowingException")]
    public void AverageSpeedTestThrowingException(AvgSpeed.Speedometer instance, UnitsNet.Duration duration, AvgSpeed.ITrack track, Type expected)
    {
        Assert.Throws(expected, () => instance.AverageSpeed(duration, track));
    }
}
 
/*
WARNING: Modification of this comment will make it impossible to merge user-defined changes
 
BEGIN_CODEGEN_DATA
H4sIAAAAAAAAAN2WW2/aMBTHn4vEd7B4ChWEAoXe1kqIy4o2LlKyh2naQ0hOqdXEzmyHlk377rNNQlMC
WdutmpgEwdg+5/z9Oye2a4fFwiHqTdB4YqPRpDccfEb29dBC3clo1B/bavQ9EGCOAA/NlsiDRSDbqt8G
LlBAPfDPkXPqNdpu46TqtFvH1WOv7VVPWydQbUKrOWuc1c+8o5m0qRULxULEMZkja8kFBGaX+j64AlPC
TR0IuxfJlPEngoU5YE4A95TdXTw1vVC+wmjmYxe5vsM56iykzjlYIYCnxHUdLoX+KBYOQoYXUjXiwhFy
emcx15PMof6xgHDKUJeBnGOBS0ncZYloZpSlvfJxUKsheyJR4SD0IQAi0I3jCsqWalDcMnqPCNwnCxtT
MUwmgtd/cCFUqzTKUvfBT/nNkTVlcAMMiAs8VpXqMRQVPgZh6oapTVQThXoSkwsKdcc/UD60mePexaJ1
WzOMPQ+JaDbQwvEjqKCNZXwEMhe3eh3R22nPSh/2SRTIupn58C4pmp4jnCs0pRwLvADVyx/LYInB9xAD
ETGiQ6etDNWxpqGfNAABzNhVXZUXZNj8gP2VuymwaxqxsjRXEdcGvUi+qWrBjQzgZEg70saVTJ7aRzl5
eYy+GVULNJpZ4zzlpgViLF9toxTWS/pfD7jL8CphpVJOue3Omc6VrapCbhSp9O9X8v4oM2IZAr0xOmwe
qbdgDSFNnGwj7sXhz9F3YHTFf0+AVev55T7CJBLw9lgbuVgJzB21oewV2tdtJLlYu5IffhHX5hauQgXb
w1p9HdBqPRfpgFLxXJjHu2H+xxVKIt/PABrLzu2QWjmQpNGUYnnBYOlDSj6+KD5fk4YCZcngrvT35C5R
Kqs58dV1QbGXubka27giTOT5J6lVshBQsstUMncxrbqycVgjeAjltRu89cm4MS7vWJHjo8t1UDOt0XgM
p92vyqXDOTBhdhj0v0ljI4lRib2lT/TdqLYf4b9nlj31/z5EW5ZPFl28bi2Ap1ZtlNHl1TMBJmzk5xew
PozmlA0AAA==
END_CODEGEN_DATA
*/

Preconditions for Generating Test Code

To generate test code, the following preconditions must be met:

  • The test model must have at least one test case.
  • In each test case a representative must be selected for each input factor.

If these preconditions are not met and you still try to generate test code, an error message pops up providing information about the unfulfilled preconditions.

Otherwise, a window opens allowing you to save the file to the desired location. 

Adapt Test Code

Merge Test Code

You can modify the generated test code at any time. Your changes are not lost when you regenerate test code, because devmate takes care of merging your manual modifications to the test code and the changes derived from the Equivalence Class Editor. Let us look at a short example in this context.

First we generate test code from our AvgSpeed test model (avgspeed.tmdl) and store it with the name “Test.cs” in our test project.

Some factory methods are generated and one of them is:

private static AvgSpeed.Preferences CreatePreferences(UnitsNet.Units.SpeedUnit preferredSpdUnit)
{
    // TODO implement factory
    throw new System.NotImplementedException();
}

Now we want to make an adjustment like implementing the factory method “CreatePreferences”.

private static AvgSpeed.Preferences CreatePreferences(UnitsNet.Units.SpeedUnit preferredSpdUnit)
{
    return new AvgSpeed.Preferences
    {
        PreferredLengthUnit = UnitsNet.Units.LengthUnit.KilolightYear,
        PreferredSpeedUnit = UnitsNet.Units.SpeedUnit.KilometerPerHour
    };
}

Then we switch back to the Equvilance Class Editor, define a second positive test and generate the code again. When saving, we select the same file (named “Test.cs”). After confirming, we will be offered to merge the file, overwrite it with the new one or cancel the process. We select the “Merge” option.

We can now see that our manual change has been retained and that the second positive test has also been created.

private static AvgSpeed.Preferences CreatePreferences(UnitsNet.Units.SpeedUnit preferredSpdUnit)
{
    return new AvgSpeed.Preferences
    {
        PreferredLengthUnit = UnitsNet.Units.LengthUnit.KilolightYear,
        PreferredSpeedUnit = UnitsNet.Units.SpeedUnit.KilometerPerHour
    };
}
 
...
 
private static IEnumerable<TestCaseData> PositiveTests()
{
    yield return new TestCaseData(new AvgSpeed.Speedometer(CreateSensorStub(), CreatePreferences(UnitsNet.Units.SpeedUnit.KilometerPerHour)), new UnitsNet.Duration(2, UnitsNet.Units.DurationUnit.Hour), CreateTrackStub(60, UnitsNet.Units.LengthUnit.Kilometer), new UnitsNet.Speed(30, UnitsNet.Units.SpeedUnit.KilometerPerHour)).SetName("p1").SetDescription("");
    yield return new TestCaseData(new AvgSpeed.Speedometer(CreateSensorStub(), CreatePreferences(UnitsNet.Units.SpeedUnit.KilometerPerHour)), new UnitsNet.Duration(2, UnitsNet.Units.DurationUnit.Hour), CreateTrackStub(60, UnitsNet.Units.LengthUnit.Kilometer), new UnitsNet.Speed(0, null)).SetName("1").SetDescription("");
}

Merge Conflicts

Nevertheless you might run into a situation where changes cannot be merged automatically. This is the case when both changes take place at one and the same location. Let us look at this again with a short example.

The starting point is to manually implement the “CreatePreferences” except that we now also change the name of the parameter to “speedUnit”. Now we make a change in the Equivalence Class Editor at the same place, namely we change the name of the parameter from “Perferences” to “firstParameter”.

Then we generate the test code again, select the file “Test.cs” and choose the function “Merge”. You can now see that the merging has led to a conflict which we have to solve ourselves manually. Since the “three-way-diff” algorithm is used on merging, 3 different states are displayed.

  • “.base” represents the state before the change.
  • “.mine” is the change from the Equivalence Class Editor.
  • “.theirs” stands for the manual change.
<<<<<<< .mine
    private static AvgSpeed.Preferences CreatePreferences(UnitsNet.Units.SpeedUnit firstParameter)
||||||| .base
    private static AvgSpeed.Preferences CreatePreferences(UnitsNet.Units.SpeedUnit preferredSpdUnit)
=======
    private static AvgSpeed.Preferences CreatePreferences(UnitsNet.Units.SpeedUnit speedUnit)
>>>>>>> .theirs
    {
        return new AvgSpeed.Preferences
        {
            PreferredLengthUnit = UnitsNet.Units.LengthUnit.KilolightYear,
            PreferredSpeedUnit = UnitsNet.Units.SpeedUnit.KilometerPerHour
        };
    }

To resolve the conflict, we remove everything manually except the desired code.

Was this article helpful?
Dislike 0
Views: 36

Continue reading

Next: Define Test Cases

We use cookies to give you the best online experience. By agreeing you accept the use of cookies in accordance with our cookie policy.

Privacy Settings saved!
Privacy Settings

When you visit any web site, it may store or retrieve information on your browser, mostly in the form of cookies. Control your personal Cookie Services here.

GetResponse, Google Analytics

We use Google Analytics for marketing purposes. You can disable these cookies.
  • __utmz
  • __utma
  • _ga
  • _gat

We use GetResponse for marketing purposes. This service cannot be disabled, otherwise the website functions will be limited.

Decline all Services
Accept all Services
Get Free Access Now to
9 eBooks!
All about Automated Software Testing
Proven experts
Learn to save up to 75% of your test efforts
Get Free Access Now!
Get Access Now! & Save 50%
Personal Trainer FREE Nutrition Custom Workout App
Get Access Now!
eBook Download
Enter your details to get your free ebook!
All about Automated Software Testing
Download Free Ebook
SUBSCRIBE
MY WEB
NEWSLETTERS
Lorem ipsum dolor sit amet, consectetur adipiscing