Exemple #1
0
        public void ProcProdSched_ReadDateTimeKinds()
        {
            // Testing time values with various time zones or kinds.
            // The core functionality is tested in HelperTest, but now testing
            // the integration of XML documents.

            var filepath = TestCommon.TestHelper.TestFileFolder + "\\ProcessProductionSchedule_DateTimeKinds.xml";
            var xmlBytes = System.IO.File.ReadAllBytes(filepath);

            var testObject        = new ProcessProductionSchedule(xmlBytes);
            var productionRequest = testObject.ProductionSchedules[0].ProductionRequests[0];

            var segmUnspec = productionRequest.SegmentRequirements[0];
            var segmUtc    = productionRequest.SegmentRequirements[1];
            var segmPlus2  = productionRequest.SegmentRequirements[2];
            var segmMinus5 = productionRequest.SegmentRequirements[3];

            // 2019-04-24T15:00:00 in file
            AssertHourAndKind(13, DateTimeKind.Unspecified, segmUnspec.EarliestStartTime.Value);
            AssertHourAndKind(14, DateTimeKind.Unspecified, segmUnspec.LatestEndTime.Value);

            // 2019-04-24T15:00:00Z in file
            AssertHourAndKind(14, DateTimeKind.Utc, segmUtc.EarliestStartTime.Value);
            AssertHourAndKind(15, DateTimeKind.Utc, segmUtc.LatestEndTime.Value);

            // 2019-04-24T17:00:00+02:00 in file
            AssertHourAndKind(15, DateTimeKind.Utc, segmPlus2.EarliestStartTime.Value);
            AssertHourAndKind(16, DateTimeKind.Utc, segmPlus2.LatestEndTime.Value);

            // 2019-04-24T10:00:00-01:00 in file
            AssertHourAndKind(22, DateTimeKind.Utc, segmMinus5.EarliestStartTime.Value);
            AssertHourAndKind(23, DateTimeKind.Utc, segmMinus5.LatestEndTime.Value);
        }
Exemple #2
0
        public void ProcProdSched_WriteSchedulingParameters()
        {
            // Testing the writing of scheduling parameters

            // Creating a schedule to be serialised
            var schedule    = new ProductionSchedule();
            var testObject1 = new ProcessProductionSchedule();

            testObject1.ProductionSchedules.Add(schedule);

            var schedulingParameters = new CMeas.Item_DataRecord()
            {
                { "myparam", new CMeas.Item_Count(3) }
            };

            // Creating a production request with scheduling parameters
            var productionRequest = new ProductionRequest
            {
                // Setting scheduling parameters. Not testing the parameters thorougly
                // because the data record is tested elsewhere.
                SchedulingParameters = schedulingParameters.ToDataRecordPropertyProxy()
            };

            schedule.ProductionRequests.Add(productionRequest);

            // Serialising validating and deserialising. The test will likely fails here if it fails.
            var xmlData   = testObject1.ToXmlBytes();
            var xmlString = System.Text.Encoding.UTF8.GetString(xmlData); // Just for debugging

            Validate(xmlData);

            // Asserting
            AssertSchedulingParameters(new ProcessProductionSchedule(xmlData));
        }
Exemple #3
0
        public void ProcProdSched_WriteEmptySchedule()
        {
            // Testing if write works when the schedule is empty.

            // Creating an object to be serialised
            var schedule                = new ProductionSchedule();
            var testObject1             = new ProcessProductionSchedule();
            var approximateCreationTime = DateTime.Now.ToUniversalTime();

            testObject1.ProductionSchedules.Add(schedule);

            // Serialising validating and deserialising. The test will likely fails here if it fails.
            var xmlData = testObject1.ToXmlBytes();

            Validate(xmlData);
            var testObjectIn = new ProcessProductionSchedule(xmlData);

            // Asserting
            AssertEmptyProcessMsg(testObjectIn);

            // Asserting creation time. Expecting it to be the creation time of the object.
            // !!! This assertion can fail if this test case is run first because there is
            // a long delay when the XML libraries are initialised. !!!
            long difference_ms = approximateCreationTime.Ticks - testObjectIn.CreationDateTime.Ticks;

            Assert.IsTrue(Math.Abs(difference_ms) < 500);
        }
Exemple #4
0
        public void ProcProdSched_ReadEmptySched()
        {
            // The schedule is empty in this test

            var filepath = TestCommon.TestHelper.TestFileFolder + "\\ProcessProductionSchedule_EmptySched.xml";
            var xmlBytes = System.IO.File.ReadAllBytes(filepath);

            var testObject = new ProcessProductionSchedule(xmlBytes);

            AssertEmptyProcessMsg(testObject);
        }
Exemple #5
0
        private void AssertSchedulingParameters(ProcessProductionSchedule testObjectIn)
        {
            // Use a separate function for assert to prevent asserting the wrong object.

            // Asserting parameters. Just a simple assert, because Item_DataRecord
            // is tested elsewhere.
            var paramNodes   = (SXml.XmlNode[])testObjectIn.ProductionSchedules[0].ProductionRequests[0].SchedulingParameters;
            var paramsRecord = new CMeas.Item_DataRecord(paramNodes);

            Assert.AreEqual(1, paramsRecord.ItemNames.Count);
            Assert.AreEqual(3, ((CMeas.Item_Count)paramsRecord["myparam"]).Value);
        }
Exemple #6
0
        public void ProcProdSched_ReadEmptyItems()
        {
            // There are empty items in the XML document in this test

            var filepath = TestCommon.TestHelper.TestFileFolder + "\\ProcessProductionSchedule_EmptyItems.xml";
            var xmlBytes = System.IO.File.ReadAllBytes(filepath);

            var testObject = new ProcessProductionSchedule(xmlBytes);

            // Asserting
            AssertEmptyItemsDoc(testObject);
        }
Exemple #7
0
        public void ProcProdSched_ReadInvalidQuantityValues()
        {
            // Testing reading an invalid quantity value

            var filepath = TestCommon.TestHelper.TestFileFolder + "\\Neg_ProcessProductionSchedule_InvalidQuantityValue.xml";
            var xmlBytes = System.IO.File.ReadAllBytes(filepath);

            var testObject = new ProcessProductionSchedule(xmlBytes);

            MaterialRequirement materialReq = testObject.ProductionSchedules[0].
                                              ProductionRequests[0].SegmentRequirements[0].MaterialRequirements[0];

            QuantityValue quantityDouble  = materialReq.Quantities[0];
            QuantityValue quantityBoolean = materialReq.Quantities[1];
            QuantityValue quantityInt     = materialReq.Quantities[2];

            // To make sure the raw values have been received as expected:
            Assert.AreEqual("41fs.9", quantityDouble.RawQuantityString);
            Assert.AreEqual("faflse", quantityBoolean.RawQuantityString);
            Assert.AreEqual("0r3", quantityInt.RawQuantityString);

            // Double
            TestCommon.TestHelper.AssertInvalidOperationException(() =>
            {
                quantityDouble.TryParseValueAsXmlDouble();
            },
                                                                  "Failed to parse double");

            // Boolean
            TestCommon.TestHelper.AssertInvalidOperationException(() =>
            {
                quantityBoolean.TryParseValueAsXmlBoolean();
            },
                                                                  "Failed to parse boolean");

            // Int32 (int)
            TestCommon.TestHelper.AssertInvalidOperationException(() =>
            {
                quantityInt.TryParseValueAsXmlInt();
            },
                                                                  "Failed to parse int");

            // Int64 (long)
            TestCommon.TestHelper.AssertInvalidOperationException(() =>
            {
                // Parsing the same value as for Int32
                quantityInt.TryParseValueAsXmlLong();
            },
                                                                  "Failed to parse long");
        }
Exemple #8
0
        private void AssertEmptyItemsDoc(ProcessProductionSchedule testObjectIn)
        {
            // This function asserts the object in "ProcessProductionSchedule_EmptyItems.xml".
            // The same function is also used as writing is tested.

            // One schedule expected
            Assert.AreEqual(1, testObjectIn.ProductionSchedules.Count);
            var schedule1 = testObjectIn.ProductionSchedules[0];

            // Three production requests expected
            Assert.AreEqual(3, schedule1.ProductionRequests.Count);
            var request1 = schedule1.ProductionRequests[0];
            var request2 = schedule1.ProductionRequests[1];
            var request3 = schedule1.ProductionRequests[2];

            // 1) Assert empty production request (request 1)
            Assert.IsNull(request1.Identifier);
            Assert.IsNull(request1.HierarchyScopeObj);
            Assert.AreEqual(0, request1.SegmentRequirements.Count);

            // 2) Asserting segment requirement (request 2)
            Assert.AreEqual(1, request2.SegmentRequirements.Count);
            AssertEmptySegmentRequirement(request2.SegmentRequirements[0]);

            // 3) Asserting empty equipment requirement (request 3)
            var eqReq_3_1 = request3.SegmentRequirements[0].EquipmentRequirements[0];

            Assert.AreEqual(0, eqReq_3_1.Quantities.Count);

            // 4) Asserting minimal material requirement (request 3)
            var matReq_3_1 = request3.SegmentRequirements[0].MaterialRequirements[0];

            Assert.AreEqual(0, matReq_3_1.MaterialDefinitionIdentifiers.Count);
            Assert.AreEqual(0, matReq_3_1.MaterialLotIdentifiers.Count);
            Assert.IsNull(matReq_3_1.MaterialUse);
            Assert.AreEqual(0, matReq_3_1.Quantities.Count);
            Assert.AreEqual(0, matReq_3_1.AssemblyRequirements.Count);

            // 5) Asserting minimal quantity value (request 3)
            var matReq_3_2 = request3.SegmentRequirements[0].MaterialRequirements[1];
            var quantityX  = matReq_3_2.Quantities[0];

            Assert.IsNull(quantityX.DataType);
            Assert.IsTrue(string.IsNullOrEmpty(quantityX.UnitOfMeasure));
            Assert.IsNull(quantityX.Key);
        }
Exemple #9
0
        public void ProcProdSched_ReadSchedulingParameters()
        {
            // Testing the reading of scheduling parameters

            var filepath = TestCommon.TestHelper.TestFileFolder + "\\ProcessProductionSchedule_SchedulingParams.xml";
            var xmlBytes = System.IO.File.ReadAllBytes(filepath);

            var testObject = new ProcessProductionSchedule(xmlBytes);

            // Get the parameters data record
            var productionReq = testObject.ProductionSchedules[0].ProductionRequests[0];
            var parameters    = new CMeas.Item_DataRecord((SXml.XmlNode[])productionReq.SchedulingParameters);

            // Asserting just one parameter, because the Item_DataRecord class is
            // not a part of this application.
            var parameter = (CMeas.Item_Measurement)parameters["SomeParam1"];

            Assert.AreEqual(10.6, parameter.Value, 0.0001);
            Assert.AreEqual("t/h", parameter.UnitOfMeasure);
        }
Exemple #10
0
        public void ProcProdSched_WriteNonUtcTimes()
        {
            // Expecting an error when there is an attempt to assign a non-UTC timestamp

            var sched = new ProcessProductionSchedule();
            var segm  = new SegmentRequirement();

            AssertDateTimeException(() =>
            {
                sched.CreationDateTime = DateTime.Parse("2020-02-20T13:09:00"); // expecting local kind by default
            }, "DateTime kind must be UTC");

            AssertDateTimeException(() =>
            {
                segm.EarliestStartTime = DateTime.Parse("2020-02-20T13:09:00"); // expecting local kind by default
            }, "DateTime kind must be UTC");

            AssertDateTimeException(() =>
            {
                segm.LatestEndTime = DateTime.Parse("2020-02-20T13:09:00"); // expecting local kind by default
            }, "DateTime kind must be UTC");
        }
Exemple #11
0
        public void ProcProdSched_WriteSegmentStartAfterEnd()
        {
            // Segment start must not be after end

            var startTime     = ParseDateTimeInUtc("2020-02-20T14:37:00Z");
            var faultySegment = new SegmentRequirement()
            {
                EarliestStartTime = startTime,
                LatestEndTime     = startTime.AddSeconds(-1) // Before start
            };

            var processProdSched = new ProcessProductionSchedule()
            {
                ProductionSchedules = new List <ProductionSchedule>
                {
                    new ProductionSchedule()
                    {
                        ProductionRequests = new List <ProductionRequest>()
                        {
                            new ProductionRequest()
                            {
                                SegmentRequirements = new List <SegmentRequirement>
                                {
                                    faultySegment
                                }
                            }
                        }
                    }
                }
            };

            // Expecting an error as message serialisation is requested
            AssertDateTimeException(() =>
            {
                processProdSched.ToXmlBytes();
            }, "Start of segment must not be after end");
        }
Exemple #12
0
 private void AssertEmptyProcessMsg(ProcessProductionSchedule testObject)
 {
     Assert.AreEqual(1, testObject.ProductionSchedules.Count);
     Assert.AreEqual(0, testObject.ProductionSchedules[0].ProductionRequests.Count);
 }
Exemple #13
0
        public void ProcProdSched_WriteEmptyItems()
        {
            // Testing if write works when there are empty items in the schedule

            // Create this production request here, because otherwise
            // there would be too many nested blocks to be readable
            var productionRequest3 = new ProductionRequest()
            {
                SegmentRequirements = new List <SegmentRequirement>()
                {
                    new SegmentRequirement()
                    {
                        EquipmentRequirements = new List <EquipmentRequirement>()
                        {
                            new EquipmentRequirement()
                            {
                                // 3) Empty equipment requirement
                            }
                        },

                        MaterialRequirements = new List <MaterialRequirement>()
                        {
                            new MaterialRequirement()
                            {
                                // 4) Empty material requirement
                            },
                            new MaterialRequirement()
                            {
                                Quantities = new List <QuantityValue>()
                                {
                                    // 5) Empty quantity value
                                    new QuantityValue((string)null)
                                }
                            }
                        }
                    }
                }
            };

            var testObject1 = new ProcessProductionSchedule()
            {
                ProductionSchedules = new List <ProductionSchedule>()
                {
                    new ProductionSchedule()
                    {
                        ProductionRequests = new List <ProductionRequest>()
                        {
                            // 1) Empty production request
                            new ProductionRequest(),

                            new ProductionRequest()
                            {
                                HierarchyScopeObj = new HierarchyScope(
                                    new IdentifierType("psc2"),
                                    EquipmentElementLevelType.ProcessCell
                                    ),

                                SegmentRequirements = new List <SegmentRequirement>()
                                {
                                    // 2) Empty segment requirement
                                    new SegmentRequirement()
                                }
                            },

                            productionRequest3
                        }
                    }
                }
            };

            // Serialising, validating and deserialising. The test will likely fails here if it fails.
            var xmlData = testObject1.ToXmlBytes();

            Validate(xmlData);
            var testObjectIn = new ProcessProductionSchedule(xmlData);

            // Asserting
            AssertEmptyItemsDoc(testObjectIn);
        }
Exemple #14
0
        private ProcessProductionSchedule CreateObjectForTestWrite()
        {
            // Applying identifiers (such as "SEG1") to items to enable a
            // verification that this test implementation has same items
            // as those in other environments, particularly Java.

            // SEG1a Creating a segment requirement
            SegmentRequirement segReq1 = new SegmentRequirement
            {
                ProcessSegmentIdentifier = new IdentifierType("1"),
                EarliestStartTime        = ParseDateTimeInUtc("2019-05-09T13:36:02Z"),
                LatestEndTime            = ParseDateTimeInUtc("2019-05-09T13:37:02Z")
            };

            // EQ1 Add equipment requirement
            EquipmentRequirement eqReq = new EquipmentRequirement()
            {
                Quantities = new List <QuantityValue>()
                {
                    new QuantityValue(true)
                }
            };

            segReq1.EquipmentRequirements.Add(eqReq);

            // MAT1 Add material requirement
            MaterialRequirement matReq = new MaterialRequirement()
            {
                MaterialDefinitionIdentifiers = new List <IdentifierType>()
                {
                    new IdentifierType("slag")
                },

                MaterialLotIdentifiers = new List <IdentifierType>()
                {
                    new IdentifierType("my-lot-1")
                },

                MaterialUse = new MaterialUse(MaterialUseType.Produced),

                Quantities = new List <QuantityValue>()
                {
                    new QuantityValue(12.2)
                    {
                        UnitOfMeasure = "t",
                        Key           = new IdentifierType("my-mat-key")
                    }
                },

                AssemblyRequirements = new List <MaterialRequirement>()
                {
                    new MaterialRequirement()
                    {
                        MaterialDefinitionIdentifiers = new List <IdentifierType>()
                        {
                            new IdentifierType("Ni")
                        }
                    }
                }
            };

            segReq1.MaterialRequirements.Add(matReq);

            // SEG1-1 Add nested segment requirement
            segReq1.SegmentRequirements.Add(new SegmentRequirement()
            {
                EarliestStartTime = ParseDateTimeInUtc("2019-08-29T15:31:38Z")
            });

            // PROD1a Create one production request (for the unit "psc3")
            ProductionRequest request1 = new ProductionRequest
            {
                // PROD1-ID Set identifier
                Identifier = new IdentifierType("some-id"),

                // PROD1-HS Set hierarchy scope
                HierarchyScopeObj = new HierarchyScope(
                    new IdentifierType("psc3"),
                    EquipmentElementLevelType.ProcessCell
                    ),

                SegmentRequirements = new List <SegmentRequirement>()
                {
                    // SEG1b Add segment requirement to production request
                    segReq1,

                    // SEG2 Add another (empty) segment requirement
                    new SegmentRequirement()
                }
            };

            // SCH Create schedule object
            ProductionSchedule schedule = new ProductionSchedule()
            {
                ProductionRequests = new List <ProductionRequest>()
                {
                    // PROD1b Add the production request to schedule
                    request1,

                    // PROD2 Adding another (empty) production request
                    new ProductionRequest()
                }
            };

            // PROPS Creating object to be serialised
            ProcessProductionSchedule testObject1 = new ProcessProductionSchedule()
            {
                // PROPS-CR Set creation time
                CreationDateTime = ParseDateTimeInUtc("2019-05-09T12:20:19Z")
            };

            // Add schedule to the test object
            testObject1.ProductionSchedules.Add(schedule);
            return(testObject1);
        }
Exemple #15
0
        public void ProcProdSched_Write()
        {
            // Serialising, validating and deserialising
            byte[] xmlData = CreateObjectForTestWrite().ToXmlBytes();
            Validate(xmlData);
            ProcessProductionSchedule testObject2 = new ProcessProductionSchedule(xmlData);

            // Assert creation time
            TestCommon.TestHelper.AssertDateTime(ParseDateTimeInUtc("2019-05-09T12:20:19Z"), testObject2.CreationDateTime);

            ProductionSchedule schedule = testObject2.ProductionSchedules[0];

            // Assert request count
            Assert.AreEqual(2, schedule.ProductionRequests.Count);

            // Asserting a production request
            ProductionRequest request1 = schedule.ProductionRequests[0];

            Assert.AreEqual(2, request1.SegmentRequirements.Count);

            // Asserting identifier
            Assert.AreEqual("some-id", request1.Identifier.Value);

            // Asserting a hierarchy scope
            Assert.AreEqual("psc3", request1.HierarchyScopeObj.EquipmentIdentifier.Value);
            Assert.AreEqual(EquipmentElementLevelType.ProcessCell, request1.HierarchyScopeObj.EquipmentElementLevel);

            // Asserting a segment requirement
            SegmentRequirement segReq = request1.SegmentRequirements[0];

            Assert.AreEqual("1", segReq.ProcessSegmentIdentifier.Value);
            AssertDateTime(ParseDateTimeInUtc("2019-05-09T13:36:02Z"), segReq.EarliestStartTime.Value);
            AssertDateTime(ParseDateTimeInUtc("2019-05-09T13:37:02Z"), segReq.LatestEndTime.Value);
            Assert.AreEqual(1, segReq.MaterialRequirements.Count);
            Assert.AreEqual(1, segReq.EquipmentRequirements.Count);

            // Asserting nested segment requirement
            SegmentRequirement segReqNested = segReq.SegmentRequirements[0];

            AssertDateTime(ParseDateTimeInUtc("2019-08-29T15:31:38Z"), segReqNested.EarliestStartTime.Value);

            // Asserting equipment requirement
            EquipmentRequirement eqReq = segReq.EquipmentRequirements[0];

            Assert.AreEqual(1, eqReq.Quantities.Count);
            Assert.IsTrue(eqReq.Quantities[0].TryParseValueAsXmlBoolean());

            MaterialRequirement matReq = segReq.MaterialRequirements[0];

            // Asserting material definition ID
            Assert.AreEqual(1, matReq.MaterialDefinitionIdentifiers.Count);
            Assert.AreEqual("slag", matReq.MaterialDefinitionIdentifiers[0].Value);

            // Asserting a material lot ID
            Assert.AreEqual(1, matReq.MaterialLotIdentifiers.Count);
            Assert.AreEqual("my-lot-1", matReq.MaterialLotIdentifiers[0].Value);

            // Asserting material use
            Assert.AreEqual(MaterialUseType.Produced, matReq.MaterialUse.Value);

            // Asserting a material quantity
            Assert.AreEqual(1, matReq.Quantities.Count);
            QuantityValue quantity = matReq.Quantities[0];

            Assert.AreEqual("12.2", quantity.RawQuantityString);
            Assert.AreEqual(12.2, quantity.TryParseValueAsXmlDouble(), 0.001);
            Assert.AreEqual("t", quantity.UnitOfMeasure);
            Assert.AreEqual(DataType.TypeType.doubleXml, quantity.DataType.Type);
            Assert.AreEqual("my-mat-key", quantity.Key.Value);

            // Asserting an assembly requirement
            Assert.AreEqual(1, matReq.AssemblyRequirements.Count);
            Assert.AreEqual("Ni", matReq.AssemblyRequirements[0].MaterialDefinitionIdentifiers[0].Value);
        }
Exemple #16
0
        public void ProcProdSched_Read()
        {
            // Testing reading a regular XML file with all supported features included.

            var filepath = TestCommon.TestHelper.TestFileFolder + "\\ProcessProductionSchedule.xml";
            var xmlBytes = System.IO.File.ReadAllBytes(filepath);

            var testObject = new ProcessProductionSchedule(xmlBytes);

            // Assert creation time
            AssertDateTime(ParseDateTimeInUtc("2019-04-24T14:10:25Z"), testObject.CreationDateTime);

            // Assert schedule count
            Assert.AreEqual(1, testObject.ProductionSchedules.Count);

            // Assert request count
            var schedule1 = testObject.ProductionSchedules[0];

            Assert.AreEqual(2, schedule1.ProductionRequests.Count);


            // Assert request 1

            var request1 = schedule1.ProductionRequests[0];

            Assert.AreEqual(2, request1.SegmentRequirements.Count);

            // Asserting identifier
            Assert.AreEqual("my-identifier-1", request1.Identifier.Value);

            // Asserting hierarchy scope
            Assert.AreEqual("fsf", request1.HierarchyScopeObj.EquipmentIdentifier.Value);
            Assert.AreEqual(EquipmentElementLevelType.ProcessCell, request1.HierarchyScopeObj.EquipmentElementLevel);


            // Asserting one segment requirement

            var segReq1 = request1.SegmentRequirements[0];

            // Assert process segment identifier
            Assert.AreEqual("1", segReq1.ProcessSegmentIdentifier.Value);

            // Assert times
            AssertDateTime(ParseDateTimeInUtc("2019-04-24T15:00:00Z"), segReq1.EarliestStartTime.Value);
            AssertDateTime(ParseDateTimeInUtc("2019-04-24T15:30:00Z"), segReq1.LatestEndTime.Value);

            // Asserting equipment requirement
            Assert.AreEqual(1, segReq1.EquipmentRequirements.Count);
            EquipmentRequirement equipmentReq = segReq1.EquipmentRequirements[0];
            QuantityValue        quantityEquipmentAvailability1 = equipmentReq.Quantities[0];
            QuantityValue        quantityEquipmentAvailability2 = equipmentReq.Quantities[1];

            Assert.AreEqual("false", quantityEquipmentAvailability1.RawQuantityString);
            Assert.AreEqual("true", quantityEquipmentAvailability2.RawQuantityString);
            Assert.IsFalse(quantityEquipmentAvailability1.TryParseValueAsXmlBoolean());
            Assert.IsTrue(quantityEquipmentAvailability2.TryParseValueAsXmlBoolean());
            Assert.AreEqual(DataType.TypeType.booleanXml, quantityEquipmentAvailability1.DataType.Type);
            Assert.AreEqual(DataType.TypeType.booleanXml, quantityEquipmentAvailability2.DataType.Type);

            // Asserting material requirement
            Assert.AreEqual(2, segReq1.MaterialRequirements.Count);
            var matReq = segReq1.MaterialRequirements[0];

            // Asserting material definition ID
            Assert.AreEqual("matte", matReq.MaterialDefinitionIdentifiers[0].Value);
            // Asserting material lot ID
            Assert.AreEqual(1, matReq.MaterialLotIdentifiers.Count);
            Assert.AreEqual("psc2-15", matReq.MaterialLotIdentifiers[0].Value);
            // Assert material use
            Assert.AreEqual(MaterialUseType.Produced, matReq.MaterialUse.Value);
            // Assert quantity 1
            var matProdQuantity1 = matReq.Quantities[0];

            Assert.AreEqual("41.9", matProdQuantity1.RawQuantityString);
            Assert.AreEqual(41.9, matProdQuantity1.TryParseValueAsXmlDouble(), 0.001);
            Assert.AreEqual("t/h", matProdQuantity1.UnitOfMeasure);
            Assert.AreEqual(DataType.TypeType.doubleXml, matProdQuantity1.DataType.Type);
            Assert.AreEqual("ProdRate", matProdQuantity1.Key.Value);
            // Assert quantity 2
            var matProdQuantity2 = matReq.Quantities[1];

            Assert.AreEqual("11.9", matProdQuantity2.RawQuantityString);
            // Not asserting other fields, because this would be redundant to the previous quantity value.
            // -- Asserting assembly requirements. Only one field is included in the test,
            // because the assembly requirements have a structure similar to the enclosing requirements.
            Assert.AreEqual(2, matReq.AssemblyRequirements.Count);
            Assert.AreEqual("Cu", matReq.AssemblyRequirements[0].MaterialDefinitionIdentifiers[0].Value);
            Assert.AreEqual("S", matReq.AssemblyRequirements[1].MaterialDefinitionIdentifiers[0].Value);

            // Asserting another segment requirement (with nested segment requirement)

            var segReq2_1 = request1.SegmentRequirements[1].SegmentRequirements[0];

            AssertDateTime(ParseDateTimeInUtc("2019-04-24T15:31:00Z"), segReq2_1.EarliestStartTime.Value);


            // Assert request 2

            var request2 = schedule1.ProductionRequests[1];

            Assert.AreEqual("my-identifier-2", request2.Identifier.Value);
        }