"""EL01 lab tests for YOUR design/requirements.toml (step 7).These check that your requirements are verifiable, not whether the design meetsthem: a requirement the design fails is still a good requirement (the reportshows it as "fail", which is information, not a bug)."""importunittestfrom_implimportREPO,artifactfromhweimportrequirementsasreqsfromhwe.unitsimportQ_# The results the EL01 pipeline computes, with their units (what `result = ...` may name).KNOWN={"mass.basic":Q_(1,"g"),"mass.predicted":Q_(1,"g"),"mass.allowable":Q_(1,"g"),"mass.margin":Q_(1,""),"hover.max_thrust_per_motor":Q_(1,"gf"),"hover.weight":Q_(1,"N"),"hover.thrust_per_motor":Q_(1,"gf"),"hover.thrust_to_weight":Q_(1,""),"hover.hover_fraction":Q_(1,""),"hover.max_climb_accel":Q_(1,"m/s^2"),"energy.battery_energy":Q_(1,"W*h"),"energy.hover_efficiency":Q_(1,"gf/W"),"energy.hover_power":Q_(1,"W"),"energy.flight_time":Q_(1,"min"),"energy.hover_current":Q_(1,"A"),"arm.volume":Q_(1,"mm^3"),"arm.volume_by_hand":Q_(1,"mm^3"),"arm.mass":Q_(1,"g"),}PATH=artifact("requirements.toml",REPO/"design"/"requirements.toml")classStep7Requirements(unittest.TestCase):@classmethoddefsetUpClass(cls):cls.records=reqs.load(PATH)deftest_at_least_five_requirements(self):self.assertGreaterEqual(len(self.records),5,f"write at least five requirements in {PATH}")deftest_no_problems_in_the_file(self):problems=reqs.validate(self.records,KNOWN)self.assertEqual(problems,[],"\n".join(problems))deftest_uses_analysis_test_and_inspection(self):methods={r.verificationforrinself.records}formin("Analysis","Test","Inspection"):self.assertIn(m,methods,f"no requirement is verified by {m}")deftest_at_least_one_derived_requirement(self):ids={r.idforrinself.records}derived=[rforrinself.recordsifr.parent]self.assertTrue(derived,"no requirement names a parent: derive at least one (section 2.11)")forrinderived:self.assertIn(r.parent,ids,f"{r.id}: parent {r.parent} is not in the file")deftest_every_requirement_has_a_rationale(self):forrinself.records:self.assertTrue(r.rationale.strip(),f"{r.id}: write a rationale (why this number?)")deftest_op_agrees_with_the_words(self):# "at least" is a floor (>=); "at most", "no more than", "not exceed" are ceilings (<=).forrinself.records:text=r.text.lower()if"at least"intext:self.assertEqual(r.op,">=",f"{r.id}: 'at least' needs op '>='")ifany(wintextforwin("at most","no more than","not exceed")):self.assertEqual(r.op,"<=",f"{r.id}: a ceiling needs op '<='")deftest_physical_thresholds_carry_units(self):forrinself.records:value=KNOWN.get(r.result)ifvalueisnotNoneandnotvalue.dimensionless:self.assertFalse(r.threshold.dimensionless,f"{r.id}: threshold needs a unit")if__name__=="__main__":unittest.main()