def test_add_range_check(self): rc = ODM.RangeCheck(Comparator="EQ", SoftHard="Soft") tt1 = ODM.TranslatedText(_content="invalid test code", lang="en") tt2 = ODM.TranslatedText(_content="code de test invalide", lang="fr") rc.CheckValue = [ODM.CheckValue(_content="DIABP")] rc.FormalExpression = [ ODM.FormalExpression(Context="Python 3.7", _content="print('hello world')") ] rc.MeasurementUnitRef = ODM.MeasurementUnitRef( MeasurementUnitOID="ODM.MU.UNITS") attrs = {"Comparator": "GT", "SoftHard": "Soft"} rc1 = ODM.RangeCheck(**attrs) tt1 = ODM.TranslatedText(_content="invalid test code", lang="en") rc1.ErrorMessage.TranslatedText = [tt1] rc1.CheckValue = [ODM.CheckValue(_content="SYSBP")] rc1.FormalExpression = [ ODM.FormalExpression(Context="Python 3.7", _content="print('hello world')") ] rc1.MeasurementUnitRef = ODM.MeasurementUnitRef( MeasurementUnitOID="ODM.MU.UNITS") self.item.RangeCheck = [rc, rc1] self.assertEqual(self.item.RangeCheck[0].Comparator, "EQ") self.assertEqual(self.item.RangeCheck[1].Comparator, "GT")
def test_add_description(self): tt1 = ODM.TranslatedText(_content="this is the first test description", lang="en") tt2 = ODM.TranslatedText(_content="this is the second test description", lang="en") self.formdef.Description = ODM.Description() self.formdef.Description.TranslatedText = [tt1, tt2] self.assertEqual(len(self.formdef.Description.TranslatedText), 2) self.assertEqual(self.formdef.Description.TranslatedText[1]._content, 'this is the second test description')
def test_ItemDef(self): attrs = { "OID": "ODM.IT.AE.AEYN", "Name": "Any AEs?", "DataType": "text", "Length": "1", "SASFieldName": "AEYN", "SDSVarName": "AEYN", "Origin": "CRF", "Comment": "Data management field" } item = ODM.ItemDef(**attrs) item.Description.TranslatedText = [ ODM.TranslatedText(_content="this is the first test description", lang="en") ] item.Question.TranslatedText = [ ODM.TranslatedText(_content="Any AEs?", lang="en") ] item.CodeListRef = ODM.CodeListRef( CodeListOID="CL.NY_SUB_Y_N_2011-10-24") item_dict = item.to_dict() print(item_dict) is_valid = self.validator.verify_conformance(item_dict, "ItemDef") self.assertTrue(is_valid)
def test_to_xml(self): attrs = self.set_item_attributes() item = ODM.ItemDef(**attrs) item.Description.TranslatedText = [ ODM.TranslatedText(_content="this is the first test description", lang="en") ] item.Question.TranslatedText = [ ODM.TranslatedText(_content="Any AEs?", lang="en") ] item.ExternalQuestion = ODM.ExternalQuestion(Dictionary="SF36", Version="12", Code="Walks 1-mile") item.CodeListRef = ODM.CodeListRef( CodeListOID="CL.NY_SUB_Y_N_2011-10-24") item.RangeCheck = [ODM.RangeCheck(Comparator="EQ", SoftHard="Soft")] item.RangeCheck[0].CheckValue = [ODM.CheckValue(_content="DIABP")] item.RangeCheck[0].FormalExpression = [ ODM.FormalExpression(Context="Python 3.7", _content="print('hello world')") ] item.RangeCheck[0].MeasurementUnitRef = ODM.MeasurementUnitRef( MeasurementUnitOID="ODM.MU.UNITS") item.RangeCheck[0].ErrorMessage.TranslatedText = [ ODM.TranslatedText(_content="invalid test code", lang="en") ] item_xml = item.to_xml() self.assertEqual(item_xml.attrib["OID"], "ODM.IT.AE.AEYN") cv = item_xml.find("*/CheckValue") self.assertEqual(cv.text, "DIABP") dt = item_xml.findall("Description/TranslatedText") self.assertEqual(len(dt), 1)
def add_ITD(self): # ItemDef 1 ttd1 = ODM.TranslatedText(_content="Date of measurements", lang="en") ttq1 = ODM.TranslatedText(_content="Date", lang="en") desc1 = ODM.Description() desc1.TranslatedText = [ttd1] q1 = ODM.Question() q1.TranslatedText = [ttq1] a1 = ODM.Alias(Context="CDASH", Name="VSDAT") itd1 = ODM.ItemDef(OID="ODM.IT.VS.VSDAT", Name="Date", DataType="partialDate") itd1.Description = desc1 itd1.Question = q1 itd1.Alias = [a1] # ItemDef 2 ttd2 = ODM.TranslatedText( _content= "Result of the vital signs measurement as originally received or collected.", lang="en") ttq2 = ODM.TranslatedText(_content="Diastolic", lang="en") desc2 = ODM.Description() desc2.TranslatedText = [ttd2] q2 = ODM.Question() q2.TranslatedText = [ttq2] a2a = ODM.Alias(Context="CDASH", Name="BP.DIABP.VSORRES") a2b = ODM.Alias(Context="CDASH/SDTM", Name="VSORRES+VSORRESU") itd2 = ODM.ItemDef(OID="ODM.IT.VS.BP.VSORRESU", Name="BP Units", DataType="text") itd2.Description = desc2 itd2.Question = q2 itd2.Alias = [a2a, a2b] return [itd1, itd2]
def test_add_description(self): tt1 = ODM.TranslatedText(_content="Age at Screening Date (Screening Date - Birth date)", lang="en") tt2 = ODM.TranslatedText(_content="For the complete algorithm see the referenced external document.", lang="fr") self.methoddef.Description = ODM.Description() self.methoddef.Description.TranslatedText = [tt1, tt2] self.assertEqual(len(self.methoddef.Description.TranslatedText), 2) self.assertEqual(self.methoddef.Description.TranslatedText[1]._content, 'For the complete algorithm see the referenced external document.')
def setUp(self) -> None: current_datetime = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).isoformat() root = ODM.ODM(FileOID="ODM.DEMO.001", Granularity="Metadata", AsOfDateTime=current_datetime, CreationDateTime=current_datetime, ODMVersion="1.3.2", FileType="Snapshot", Originator="swhume", SourceSystem="odmlib", SourceSystemVersion="0.1") # create Study and add to ODM root.Study.append(ODM.Study(OID="ODM.GET.STARTED")) # create the global variables root.Study[0].GlobalVariables = ODM.GlobalVariables() root.Study[0].GlobalVariables.StudyName = ODM.StudyName(_content="Get Started with ODM XML") root.Study[0].GlobalVariables.StudyDescription = ODM.StudyDescription( _content="Demo to get started with odmlib") root.Study[0].GlobalVariables.ProtocolName = ODM.ProtocolName(_content="ODM XML Get Started") # create the MetaDataVersion root.Study[0].MetaDataVersion.append(ODM.MetaDataVersion(OID="MDV.DEMO-ODM-01", Name="Get Started MDV", Description="Get Started Demo")) # create Protocol p = ODM.Protocol() p.Description = ODM.Description() p.Description.TranslatedText.append(ODM.TranslatedText(_content="Get Started Protocol", lang="en")) p.StudyEventRef.append(ODM.StudyEventRef(StudyEventOID="BASELINE", OrderNumber=1, Mandatory="Yes")) root.Study[0].MetaDataVersion[0].Protocol = p # create a StudyEventDef sed = ODM.StudyEventDef(OID="BASELINE", Name="Baseline Visit", Repeating="No", Type="Scheduled") sed.FormRef.append(ODM.FormRef(FormOID="ODM.F.DM", Mandatory="Yes", OrderNumber=1)) root.Study[0].MetaDataVersion[0].StudyEventDef.append(sed) # create a FormDef fd = ODM.FormDef(OID="ODM.F.DM", Name="Demographics", Repeating="No") fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.DM", Mandatory="Yes", OrderNumber=2)) root.Study[0].MetaDataVersion[0].FormDef.append(fd) # create an ItemGroupDef igd = ODM.ItemGroupDef(OID="ODM.IG.DM", Name="Demographics", Repeating="No") igd.ItemRef.append(ODM.ItemRef(ItemOID="ODM.IT.DM.BRTHYR", Mandatory="Yes")) root.Study[0].MetaDataVersion[0].ItemGroupDef.append(igd) # create an ItemDef itd = ODM.ItemDef(OID="ODM.IT.DM.BRTHYR", Name="Birth Year", DataType="integer") itd.Description = ODM.Description() itd.Description.TranslatedText.append(ODM.TranslatedText(_content="Year of the subject's birth", lang="en")) itd.Question = ODM.Question() itd.Question.TranslatedText.append(ODM.TranslatedText(_content="Birth Year", lang="en")) itd.Alias.append(ODM.Alias(Context="CDASH", Name="BRTHYR")) itd.Alias.append(ODM.Alias(Context="SDTM", Name="BRTHDTC")) root.Study[0].MetaDataVersion[0].ItemDef.append(itd) # save the new ODM document to an ODM XML file root.write_xml(ODM_XML_FILE) # save the same ODM document to a JSON file root.write_json(ODM_JSON_FILE)
def test_to_xml_description(self): tt1 = ODM.TranslatedText(_content="this is the first test description", lang="en") tt2 = ODM.TranslatedText( _content="this is the second test description", lang="en") desc = ODM.Description() desc.TranslatedText = [tt1, tt2] desc_xml = desc.to_xml() tts = desc_xml.findall("TranslatedText") self.assertEqual(tts[0].text, "this is the first test description")
def test_to_dict_description(self): tt1 = ODM.TranslatedText(_content="this is the first test description", lang="en") tt2 = ODM.TranslatedText( _content="this is the second test description", lang="en") desc = ODM.Description() desc.TranslatedText = [tt1, tt2] desc_dict = desc.to_dict() print(desc_dict) self.assertDictEqual(desc_dict["TranslatedText"][1], { '_content': 'this is the second test description', 'lang': 'en' })
def test_to_json(self): attrs = self.set_item_attributes() item = ODM.ItemDef(**attrs) item.Description.TranslatedText.append( ODM.TranslatedText(_content="this is the first test description", lang="en")) item.Question.TranslatedText = [ ODM.TranslatedText(_content="Any AEs?", lang="en") ] item.CodeListRef = ODM.CodeListRef( CodeListOID="CL.NY_SUB_Y_N_2011-10-24") item_json = item.to_json() item_dict = json.loads(item_json) self.assertEqual(item_dict["OID"], "ODM.IT.AE.AEYN")
def test_add_description(self): attrs = { "_content": "this is the first test description", "lang": "en" } tt1 = ODM.TranslatedText(**attrs) attrs = { "_content": "this is the second test description", "lang": "en" } tt2 = ODM.TranslatedText(**attrs) self.item.Description.TranslatedText.append(tt1) self.item.Description.TranslatedText.append(tt2) self.assertEqual(self.item.Description.TranslatedText[1]._content, "this is the second test description")
def add_CL(self): tt1 = ODM.TranslatedText(_content="No", lang="en") dc1 = ODM.Decode() dc1.TranslatedText = [tt1] cli1 = ODM.CodeListItem(CodedValue="N") cli1.Decode = dc1 tt2 = ODM.TranslatedText(_content="Yes", lang="en") dc2 = ODM.Decode() dc2.TranslatedText = [tt2] cli2 = ODM.CodeListItem(CodedValue="Y") cli2.Decode = dc2 cl = ODM.CodeList(OID="ODM.CL.NY_SUB_Y_N", Name="No Yes Response", DataType="text") cl.CodeListItem = [cli1, cli2] return [cl]
def test_ItemGroupDef(self): attrs = { "OID": "IG.VS", "Name": "VS", "Repeating": "Yes", "Domain": "VS", "Name": "VS", "SASDatasetName": "VS", "IsReferenceData": "No", "Purpose": "Tabulation" } igd = ODM.ItemGroupDef(**attrs) tt = ODM.TranslatedText(_content="this is the first test description", lang="en") igd.Description = ODM.Description() igd.Description.TranslatedText = [tt] ir1 = ODM.ItemRef(ItemOID="IT.STUDYID", Mandatory="Yes", OrderNumber="1") ir2 = ODM.ItemRef(ItemOID="IT.VS.VSTEST", Mandatory="No", OrderNumber="2") igd.ItemRef = [ir1, ir2] igd_dict = igd.to_dict() print(igd_dict) is_valid = self.validator.verify_conformance(igd_dict, "ItemGroupDef") self.assertTrue(is_valid)
def test_FormDef(self): formdef = ODM.FormDef(OID="ODM.F.VS", Name="Vital Signs Form", Repeating="Yes") tt1 = ODM.TranslatedText(_content="this is the first test description", lang="en") formdef.Description = ODM.Description() formdef.Description.TranslatedText = [tt1] igr = ODM.ItemGroupRef(ItemGroupOID="ODM.IG.COMMON", Mandatory="Yes", OrderNumber="1") formdef.ItemGroupRef.append(igr) igr = ODM.ItemGroupRef(ItemGroupOID="ODM.IG.VS_GENERAL", Mandatory="Yes", OrderNumber="2") formdef.ItemGroupRef.append(igr) igr = ODM.ItemGroupRef(ItemGroupOID="ODM.IG.VS", Mandatory="Yes", OrderNumber="3") formdef.ItemGroupRef.append(igr) formdef.Alias.append(ODM.Alias(Context="SDTMIG", Name="VS")) fd_dict = formdef.to_dict() print(fd_dict) is_valid = self.validator.verify_conformance(fd_dict, "FormDef") self.assertTrue(is_valid)
def test_RangeCheck(self): rc = ODM.RangeCheck(Comparator="EQ", SoftHard="Soft") tt1 = ODM.TranslatedText(_content="invalid test code", lang="en") tt2 = ODM.TranslatedText(_content="code de test invalide", lang="fr") rc.ErrorMessage.TranslatedText = [tt1, tt2] rc.CheckValue = [ODM.CheckValue(_content="DIABP")] rc.FormalExpression = [ ODM.FormalExpression(Context="Python 3.7", _content="print('hello world')") ] rc.MeasurementUnitRef = ODM.MeasurementUnitRef( MeasurementUnitOID="ODM.MU.UNITS") rc_dict = rc.to_dict() print(rc_dict) is_valid = self.validator.verify_conformance(rc_dict, "RangeCheck") self.assertTrue(is_valid)
def test_Protocol(self): p = ODM.Protocol() tt = ODM.TranslatedText(_content="Trace-XML Test CDASH File", lang="en") p.Description = ODM.Description() p.Description.TranslatedText = [tt] ser1 = ODM.StudyEventRef(StudyEventOID="BASELINE", OrderNumber="1", Mandatory="Yes") ser2 = ODM.StudyEventRef(StudyEventOID="FOLLOW-UP", OrderNumber="2", Mandatory="Yes") p.StudyEventRef = [ser1, ser2] p.Alias = [ ODM.Alias(Context="ClinicalTrials.gov", Name="trace-protocol") ] description_dict = p.Description.to_dict() print(description_dict) is_valid = self.validator.verify_conformance(description_dict, "Description") self.assertTrue(is_valid) protocol_dict = p.to_dict() print(protocol_dict) is_valid = self.validator.verify_conformance(protocol_dict, "Protocol") self.assertTrue(is_valid)
def test_set_invalid_description(self): rc = ODM.RangeCheck(Comparator="EQ", SoftHard="Soft") tt1 = ODM.TranslatedText(_content="invalid test code", lang="en") tt2 = ODM.TranslatedText(_content="code de test invalide", lang="fr") rc.ErrorMessage.TranslatedText.append(tt1) rc.ErrorMessage.TranslatedText.append(tt2) rc.CheckValue = [ODM.CheckValue(_content="DIABP")] rc.FormalExpression = [ ODM.FormalExpression(Context="Python 3.7", _content="print('hello world')") ] rc.MeasurementUnitRef = [ ODM.MeasurementUnitRef(MeasurementUnitOID="ODM.MU.UNITS") ] self.item.RangeCheck = [rc] # Description requires a Description object, not a RangeCheck object with self.assertRaises(TypeError): self.item.Description = rc
def test_add_description(self): tt1 = ODM.TranslatedText( _content="Skip the BRTHMO field when BRTHYR length NE 4", lang="en") self.cond_def.Description = ODM.Description() self.cond_def.Description.TranslatedText = [tt1] self.assertEqual(len(self.cond_def.Description.TranslatedText), 1) self.assertEqual(self.cond_def.Description.TranslatedText[0]._content, 'Skip the BRTHMO field when BRTHYR length NE 4')
def test_no_description(self): tt = ODM.TranslatedText(lang="en", _content="hello, world") validator = METADATA.MetadataSchema() results = tt.verify_conformance(validator) self.methoddef.FormalExpression = [ODM.FormalExpression(Context="Python 3.7", _content="print('hello world')")] self.assertEqual(self.methoddef.FormalExpression[0]._content, "print('hello world')") with self.assertRaises(ValueError): results = self.methoddef.verify_conformance(validator)
def add_CD(self): tt1 = ODM.TranslatedText( _content="Skip the BRTHMO field when BRTHYR length NE 4", lang="en") desc = ODM.Description() desc.TranslatedText = [tt1] cd = ODM.ConditionDef(OID="ODM.CD.BRTHMO", Name="Skip BRTHMO when no BRTHYR") cd.Description = desc return [cd]
def test_append_item_group_ref(self): fd = ODM.FormDef(OID="ODM.F.VS", Name="Vital Signs Form", Repeating="Yes") fd.Description = ODM.Description() fd.Description.TranslatedText.append(ODM.TranslatedText(_content="this is the first test description", lang="en")) fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.COMMON", Mandatory="Yes", OrderNumber=1)) fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.VS_GENERAL", Mandatory="Yes", OrderNumber=2)) fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.VS", Mandatory="Yes", OrderNumber=3)) self.assertEqual(fd.ItemGroupRef[0].ItemGroupOID, "ODM.IG.COMMON") self.assertEqual(fd.ItemGroupRef[2].OrderNumber, 3) self.assertEqual(fd.Description.TranslatedText[0]._content, "this is the first test description")
def test_CodeListItem(self): cli = ODM.CodeListItem(CodedValue="HGB", OrderNumber="1") tt1 = ODM.TranslatedText(_content="Hemoglobin", lang="en") decode = ODM.Decode() decode.TranslatedText.append(tt1) cli.Decode = decode cli.Alias.append(ODM.Alias(Context="nci:ExtCodeID", Name="C64848")) cli_dict = cli.to_dict() print(cli_dict) is_valid = self.validator.verify_conformance(cli_dict, "CodeListItem") self.assertTrue(is_valid)
def test_to_dict(self): attrs = self.set_formdef_attributes() fd = ODM.FormDef(**attrs) fd.Description = ODM.Description() fd.Description.TranslatedText.append(ODM.TranslatedText(_content="this is the first test description", lang="en")) fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.COMMON", Mandatory="Yes", OrderNumber=1)) fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.VS_GENERAL", Mandatory="Yes", OrderNumber=2)) fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.VS", Mandatory="Yes", OrderNumber=3)) fd.Alias.append(ODM.Alias(Context="SDTMIG", Name="VS")) fd_dict = fd.to_dict() self.assertEqual(fd_dict["OID"], "ODM.F.VS") self.assertDictEqual(fd_dict, self.expected_dict())
def test_to_dict(self): attrs = self.set_attributes() method = ODM.MethodDef(**attrs) desc = ODM.Description() tt1 = ODM.TranslatedText(_content="Age at Screening Date (Screening Date - Birth date)", lang="en") desc.TranslatedText = [tt1] method.Description = desc fex = ODM.FormalExpression(Context="Python 3.7", _content="print('hello world')") method.FormalExpression = [fex] method_dict = method.to_dict() self.assertEqual(method_dict["OID"], "ODM.MT.AGE") self.assertDictEqual(method_dict, self.expected_dict())
def add_MD(self): tt1 = ODM.TranslatedText( _content= "Concatenation of BRTHYR, BRTHMO, and BRTHDY in ISO 8601 format", lang="en") desc = ODM.Description() desc.TranslatedText = [tt1] md = ODM.MethodDef(OID="ODM.MT.DOB", Name="Create BRTHDTC from date ELEMENTS", Type="Computation") md.Description = desc return [md]
def test_to_dict(self): attrs = self.set_item_attributes() item = ODM.ItemDef(**attrs) item.Description.TranslatedText = [ ODM.TranslatedText(_content="this is the first test description", lang="en") ] item.Question.TranslatedText = [ ODM.TranslatedText(_content="Any AEs?", lang="en") ] item.CodeListRef = ODM.CodeListRef( CodeListOID="CL.NY_SUB_Y_N_2011-10-24") item_dict = item.to_dict() expected_dict = { 'OID': 'ODM.IT.AE.AEYN', 'Name': 'Any AEs?', 'DataType': 'text', 'Length': 1, 'SASFieldName': 'AEYN', 'SDSVarName': 'AEYN', 'Origin': 'CRF', 'Comment': 'Data management field', 'Description': { 'TranslatedText': [{ '_content': 'this is the first test description', 'lang': 'en' }] }, 'Question': { 'TranslatedText': [{ '_content': 'Any AEs?', 'lang': 'en' }] }, 'CodeListRef': { 'CodeListOID': 'CL.NY_SUB_Y_N_2011-10-24' } } self.assertDictEqual(item_dict, expected_dict)
def test_to_xml(self): attrs = self.set_formdef_attributes() fd = ODM.FormDef(**attrs) fd.Description = ODM.Description() fd.Description.TranslatedText.append(ODM.TranslatedText(_content="this is the first test description", lang="en")) fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.COMMON", Mandatory="Yes", OrderNumber=1)) fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.VS_GENERAL", Mandatory="Yes", OrderNumber=2)) fd.ItemGroupRef.append(ODM.ItemGroupRef(ItemGroupOID="ODM.IG.VS", Mandatory="Yes", OrderNumber=3)) fd.Alias.append(ODM.Alias(Context="SDTMIG", Name="VS")) fd_xml = fd.to_xml() self.assertEqual(fd_xml.attrib["OID"], "ODM.F.VS") igr = fd_xml.findall("ItemGroupRef") self.assertEqual(len(igr), 3) self.assertEqual(igr[0].attrib, {"ItemGroupOID": "ODM.IG.COMMON", "Mandatory": "Yes", "OrderNumber": "1"})
def test_itemgroupdef_iterator(self): """ test the ability to reference a specific or slice of ItemRefs """ attrs = self.set_itemgroupdef_attributes() igd = ODM.ItemGroupDef(**attrs) tt = ODM.TranslatedText(_content="Vital Signs", lang="en") igd.Description = ODM.Description() igd.Description.TranslatedText = [tt] item_refs = self.set_itemrefs() igd.ItemRef = item_refs parser = ODM_PARSER.ODMParser(self.odm_test_file) parser.parse() parser.MetaDataVersion() irs = [ir.ItemOID for ir in igd] self.assertEqual(len(irs), 13) self.assertEqual(len(igd), 13)
def test_itemgroupdef_slice(self): """ test the ability to reference a specific or slice of ItemRefs """ attrs = self.set_itemgroupdef_attributes() igd = ODM.ItemGroupDef(**attrs) tt = ODM.TranslatedText(_content="Vital Signs", lang="en") igd.Description = ODM.Description() igd.Description.TranslatedText = [tt] item_refs = self.set_itemrefs() igd.ItemRef = item_refs parser = ODM_PARSER.ODMParser(self.odm_test_file) parser.parse() parser.MetaDataVersion() self.assertEqual(len(igd), 13) self.assertEqual(igd.ItemRef[0].ItemOID, "IT.STUDYID") slice_itr = igd.ItemRef[1:5] self.assertEqual(slice_itr[1].ItemOID, "IT.VS.USUBJID")
def test_to_xml(self): attrs = self.set_attributes() cd = ODM.ConditionDef(**attrs) cd.Description = ODM.Description() cd.Description.TranslatedText = [ ODM.TranslatedText( _content="Skip the BRTHMO field when BRTHYR length NE 4", lang="en") ] cd.FormalExpression = [ ODM.FormalExpression(Context="Python 3.7", _content="BRTHYR != 4") ] cd_xml = cd.to_xml() self.assertEqual(cd_xml.attrib["OID"], "ODM.CD.BRTHMO") fex_xml = cd_xml.find("FormalExpression") self.assertEqual(fex_xml.attrib["Context"], "Python 3.7")