Parameters of "When" action not updated if these parameters were modified in "Given" action

Mar 6, 2010 at 6:30 PM

Hello robfe,

I noticed this anomaly when doing a test. The code should tell the story better than I do.

using System;
using System.Reflection;
using NUnit.Framework;
using StoryQ;

namespace DLLTests
{
    [TestFixture]
    public class StoryQ_Test
    {
        private DateTime Date1;
        private DateTime DateAsParameter;

        [Test]
        public void Test_execution_order()
        {
            new Story("")
                .InOrderTo("")
                .AsA("")
                .IWant("")
                .WithScenario("parameter of \"When\" modified in previous executable")
                .Given(a_valid_Date1)
                .When(save_the_date_parameter, Date1)
                .Then(The_two_dates_should_match)
                .ExecuteWithReport(MethodBase.GetCurrentMethod());
        }

        private void The_two_dates_should_match()
        {
            Assert.AreEqual(Date1, DateAsParameter);
        }

        private void save_the_date_parameter(DateTime reqDate)
        {
            DateAsParameter = reqDate;
        }

        public void a_valid_Date1()
        {
            Date1 = DateTime.Parse("2/1/2009");
        }
    }
}

This is the result:
Story is 
  In order to 
  As a 
  I want 

      With scenario parameter of "When" modified in previous executable
        Given a valid Date1                                             => Passed
        When save the date parameter                                    => Passed
        Then The two dates should match                                 => Failed  ->   Expected: 2009-02-01 00:00:00.000
  But was:  0001-01-01 00:00:00.000

Might be a bug?

Coordinator
Mar 6, 2010 at 8:36 PM

Hmm. What you see is what i'd expect to happen, based on how StoryQ was written. But I can see how as a user, you wouldn't expect that!

Basically, the string description is recorded when the story is constructed, rather than executed.

My recommendation is to only really pass literals into each step method: otherwise it will be very hard for someone else to understand what the test is actually doing (as well as exposing this bug). Developers would struggle, but business stakeholders (whom we have, beleive it or not, had looking at our test code) would have no chance.

If you were using cucumber or specflow, you'd be building the story in plaintext, so you'd be forced to pass parameters in directly, not as variables.

One exception to this is if you are using data-driven or parameterised unit tests - you'd pass "testContext.DataRow.Field<DateTime>("TheDate")" in for example - which wouldn't exhibit this bug...

 

Maybe you could post your actual test here if you think it's still a valid use?

 

Coordinator
Mar 6, 2010 at 8:37 PM

I will add something to the documentation about this though: I'm sure you won't be the first person to come across this

Mar 7, 2010 at 7:18 AM
Hello robfe,
Here is the actual test. I have commented out the statements that call methods of the SUT classes.
using System;
using System.Reflection;
using NUnit.Framework;
using StoryQ;

namespace JG.Tests.API3rdParty
{
    [TestFixture]
    public class StoryQ_Test
    {
        private DateTime Date1;
        private DateTime DateAsParameter;

        [Test]
        public void Test_execution_order()
        {
            new Story("")
                .InOrderTo("")
                .AsA("")
                .IWant("")
                .WithScenario("request with a weekday")
                .Given(requested_date_being_a_weekday)
                .When(read_data_from_file_the_requested_date_is_Arg1, Date1)
                .Then(timestamp_of_the_first_record_should_be_the_requested_date)

                .WithScenario("request with a weekend day")
                .Given(requested_date_being_a_weekend_day)
                .When(read_data_from_file_the_requested_date_is_Arg1, Date1)
                .Then(timestamp_of_the_first_record_should_be_the_following_Monday)

                .ExecuteWithReport(MethodBase.GetCurrentMethod());
        }

        public void requested_date_being_a_weekday()
        {
            Date1 = DateTime.Parse("2/1/2009");
        }

        private void read_data_from_file_the_requested_date_is_Arg1(DateTime reqDate)
        {
            DateAsParameter = reqDate;
            // fullfil the request here, like:
            // SUT.loadfromFile(reqDate);
        }

        private void timestamp_of_the_first_record_should_be_the_requested_date()
        {
            Assert.AreEqual(Date1, DateAsParameter);
        }

        private void timestamp_of_the_first_record_should_be_the_following_Monday()
        {
            DateTime firstRecordTime = DateTime.MinValue;
            // firstRecordTime = SUT.FirstDateTime;
            Assert.AreEqual(DateTime.Parse("3/7/2010"), firstRecordTime);
        }

        private void requested_date_being_a_weekend_day()
        {
            Date1 = DateTime.Parse("3/5/2010");
        }
    }
}
I agree that there are workarounds when I am aware of that I need to pass values to StoryQ actions. In this case, Date1 does not have to be there as a parameter--I just need it to show the date in the report.
Coordinator
Mar 7, 2010 at 8:15 AM

what do you think about (pseudocode):

public void Arg1_being_a_weekday(DateTime date)
{
     Assert.IsTrue(date.DayOfWeek >= DayOfWeek.Monday && date.DayOfWeek <= DayOfWeek.Friday)
}

by the way, "DateTime.Parse("3/5/2010")" will swap the month and day depending on whether you are in a US or UK locale - it's safer to use "DateTime.Parse("2010-5-3")" or even "new DateTime(2010,5,3)"

Mar 7, 2010 at 10:08 AM

Hello robfe,

Yes, that will test if the date is a weekday. I actually also have to test if the timestamp of the first record is the same weekday as the requested date (if the requested date is a weekday itself). The code is not production code, I merely constructed it to show how I came across the bug.

The suggestion to initialize a DateTime in different way is valid. Thank you for pointing out.