[TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_LengthNotDivisibleByStep_IterationCountMatchesCalculated()
        {
            Period    length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start  = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end    = start + length;
            // note that the number of steps is limited to 1000 or fewer
            int    steps = Random.Next(4, 1000);
            Period step  = PeriodDivideApprox(length, steps);

            //ensure that step size is not a factor of the length of the range
            if (length.TicksFrom(start) % step.TicksFrom(start) == 0)
            {
                start += RandomPeriod(MinPeriod, step - MinPeriod, false);
            }

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            long ticksA = start.TicksTo(end);
            long ticksB = step.TicksFrom(start);

            Assert.AreEqual(
                (ticksA / ticksB) + 1,
                localRange.Count(),
                "Iteration count should be (start-end)/step +1");
        }
        [ExpectedException(typeof(ArgumentOutOfRangeException))] // ReSharper disable once InconsistentNaming
        public void Constructor_EndBeforeStart_ThrowsArgumentOutOfRangeException()
        {
            Period    length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start  = RandomLocalTime(MinLocalTime + length, MaxLocalTime);
            LocalTime end    = start - length;

            // ReSharper disable once UnusedVariable
            LocalTimeRange localRange = new LocalTimeRange(start, end);
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void Step_StepIsLargerThanRange_MatchesThatGivenWithTimeStripped()
        {
            LocalTime      start, end;
            Period         step;
            LocalTimeRange localRange = GenerateLocalTimeRangeWithStepLargerThanRange(
                out start,
                out end,
                out step);

            Assert.AreEqual(step, localRange.Step, "Step amount field must match the value supplied.");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void ToString_HasCorrectFormat()
        {
            Period    length = RandomPeriod(MinPeriod + MinPeriod, MaxPeriod, false);
            LocalTime start  = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end    = start + length;
            Period    step   = RandomPeriod(MinPeriod, length - MinPeriod, false);

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            Assert.AreEqual($"{start} - {end}", localRange.ToString());
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void End_StepSmallerThanRange_MatchesThatGivenWithTimeStripped()
        {
            LocalTime      start, end;
            Period         step;
            LocalTimeRange localRange = GenerateLocalTimeRangeWithStepSmallerThanRange(
                out start,
                out end,
                out step);

            Assert.AreEqual(end, localRange.End, "End point field must match the value supplied.");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void ToString_HasCorrectFormat()
        {
            Period length = RandomPeriod(MinPeriod + MinPeriod, MaxPeriod, false);
            LocalTime start = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end = start + length;
            Period step = RandomPeriod(MinPeriod, length - MinPeriod, false);

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            Assert.AreEqual($"{start} - {end}", localRange.ToString());
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_UsingLargestPossibleParameters_IteratesSuccessfully()
        {
            // Step chosen to avoid an unfeasible number of iterations
            LocalTimeRange localRange = new LocalTimeRange(
                MinLocalTime,
                MaxLocalTime,
                PeriodDivideApprox(MaxPeriod, 16));

            bool iterated = localRange.Any();

            Assert.AreEqual(true, iterated, "When iterating across full range, at least one value should be returned");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void ToString_IsNotBlank()
        {
            Period    length = RandomPeriod(MinPeriod + MinPeriod, MaxPeriod, false);
            LocalTime start  = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end    = start + length;
            Period    step   = RandomPeriod(MinPeriod, length - MinPeriod, false);

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            Assert.AreNotEqual(
                "",
                localRange.ToString(),
                "String representation of range must not be an empty string");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void Constructor_WithoutStepParam_DeltaLessThanDay_StepDefaultsToOneHour()
        {
            Period length = RandomPeriod(Period.FromHours(1), Period.FromDays(1), false);

            Trace.WriteLine(length);
            LocalTime start = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end   = start + length;

            LocalTimeRange localRange = new LocalTimeRange(start, end);

            Assert.AreEqual(start, localRange.Start, "Starting point field must match the value supplied");
            Assert.AreEqual(end, localRange.End, "End point field must match the value supplied");
            Assert.AreEqual(Period.FromHours(1), localRange.Step, "Step amount must default to one hour");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void ToString_IsNotBlank()
        {
            Period length = RandomPeriod(MinPeriod + MinPeriod, MaxPeriod, false);
            LocalTime start = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end = start + length;
            Period step = RandomPeriod(MinPeriod, length - MinPeriod, false);

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            Assert.AreNotEqual(
                "",
                localRange.ToString(),
                "String representation of range must not be an empty string");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_ValuesStayWithinRange()
        {
            Period    length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start  = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end    = start + length;
            // note that the number of steps is limited to 100 or fewer
            Period step = PeriodDivideApprox(length, Random.Next(4, 100));

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            foreach (LocalTime d in localRange)
            {
                Assert.IsTrue(d >= start, "Value from iterator must by equal or above start parameter");
                Assert.IsTrue(d <= end, "Value from iterator must be equal or below end parameter");
            }
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_LengthDivisibleByStep_IterationCountMatchesCalculated()
        {
            Period    length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start  = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end    = start + length;
            // note that the number of steps is limited to 1000 or fewer
            Period step = PeriodDivideApprox(length, Random.Next(4, 1000));

            //ensure that step size is a factor of the length of the range
            start += Period.FromTicks(length.TicksFrom(start) % step.TicksFrom(start));

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            long ticksA = start.TicksTo(end);
            long ticksB = step.TicksFrom(start);

            // Range endpoint is inclusive, so must take longo account this extra iteration
            Assert.AreEqual(
                (ticksA / ticksB) + 1,
                localRange.Count(),
                "Iteration count should be (end-start)/step + 1 where endpoint is included");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_Iterating_DifferenceBetweenIterationsMatchesStepSize()
        {
            Period    length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start  = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end    = start + length;
            // note that the number of steps is limited to 100 or fewer
            Period step = PeriodDivideApprox(length, Random.Next(4, 100));

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            LocalTime?previous = null;

            foreach (LocalTime d in localRange)
            {
                if (previous.HasValue)
                {
                    Assert.AreEqual(
                        Period.Between(previous.Value, d),
                        step,
                        "Difference between iteration values should match the step value supplied");
                }
                previous = d;
            }
        }
        [ExpectedException(typeof(ArgumentOutOfRangeException))] // ReSharper disable once InconsistentNaming
        public void Constructor_EndBeforeStart_ThrowsArgumentOutOfRangeException()
        {
            Period length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start = RandomLocalTime(MinLocalTime + length, MaxLocalTime);
            LocalTime end = start - length;

            // ReSharper disable once UnusedVariable
            LocalTimeRange localRange = new LocalTimeRange(start, end);
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_ValuesStayWithinRange()
        {
            Period length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end = start + length;
            // note that the number of steps is limited to 100 or fewer
            Period step = PeriodDivideApprox(length, Random.Next(4, 100));

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            foreach (LocalTime d in localRange)
            {
                Assert.IsTrue(d >= start, "Value from iterator must by equal or above start parameter");
                Assert.IsTrue(d <= end, "Value from iterator must be equal or below end parameter");
            }
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_LengthDivisibleByStep_IterationCountMatchesCalculated()
        {
            Period length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end = start + length;
            // note that the number of steps is limited to 1000 or fewer
            Period step = PeriodDivideApprox(length, Random.Next(4, 1000));

            //ensure that step size is a factor of the length of the range
            start += Period.FromTicks(length.TicksFrom(start) % step.TicksFrom(start));

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            long ticksA = start.TicksTo(end);
            long ticksB = step.TicksFrom(start);

            // Range endpoint is inclusive, so must take longo account this extra iteration
            Assert.AreEqual(
                (ticksA / ticksB) + 1,
                localRange.Count(),
                "Iteration count should be (end-start)/step + 1 where endpoint is included");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void Constructor_WithoutStepParam_DeltaLessThanDay_StepDefaultsToOneHour()
        {
            Period length = RandomPeriod(Period.FromHours(1), Period.FromDays(1), false);
            Trace.WriteLine(length);
            LocalTime start = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end = start + length;

            LocalTimeRange localRange = new LocalTimeRange(start, end);

            Assert.AreEqual(start, localRange.Start, "Starting point field must match the value supplied");
            Assert.AreEqual(end, localRange.End, "End point field must match the value supplied");
            Assert.AreEqual(Period.FromHours(1), localRange.Step, "Step amount must default to one hour");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_UsingLargestPossibleParameters_IteratesSuccessfully()
        {
            // Step chosen to avoid an unfeasible number of iterations
            LocalTimeRange localRange = new LocalTimeRange(
                MinLocalTime,
                MaxLocalTime,
                PeriodDivideApprox(MaxPeriod, 16));

            bool iterated = localRange.Any();

            Assert.AreEqual(true, iterated, "When iterating across full range, at least one value should be returned");
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_Iterating_DifferenceBetweenIterationsMatchesStepSize()
        {
            Period length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end = start + length;
            // note that the number of steps is limited to 100 or fewer
            Period step = PeriodDivideApprox(length, Random.Next(4, 100));

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            LocalTime? previous = null;
            foreach (LocalTime d in localRange)
            {
                if (previous.HasValue)
                {
                    Assert.AreEqual(
                        Period.Between(previous.Value, d),
                        step,
                        "Difference between iteration values should match the step value supplied");
                }
                previous = d;
            }
        }
        [TestMethod] // ReSharper disable once InconsistentNaming
        public void GetEnumerator_LengthNotDivisibleByStep_IterationCountMatchesCalculated()
        {
            Period length = RandomPeriod(MinPeriod, MaxPeriod, false);
            LocalTime start = RandomLocalTime(MinLocalTime, MaxLocalTime - length);
            LocalTime end = start + length;
            // note that the number of steps is limited to 1000 or fewer
            int steps = Random.Next(4, 1000);
            Period step = PeriodDivideApprox(length, steps);

            //ensure that step size is not a factor of the length of the range
            if (length.TicksFrom(start) % step.TicksFrom(start) == 0)
            {
                start += RandomPeriod(MinPeriod, step - MinPeriod, false);
            }

            LocalTimeRange localRange = new LocalTimeRange(start, end, step);

            long ticksA = start.TicksTo(end);
            long ticksB = step.TicksFrom(start);

            Assert.AreEqual(
                (ticksA / ticksB) + 1,
                localRange.Count(),
                "Iteration count should be (start-end)/step +1");
        }