Best Python code snippet using SeleniumBase
test_order.py
Source:test_order.py
...125 with snapcraft_legacy.config.CLIConfig() as cli_config:126 cli_config.set_outdated_step_action(127 snapcraft_legacy.config.OutdatedStepAction.CLEAN128 )129 def set_attributes(self, kwargs):130 self.__dict__.update(kwargs)131 def get_run_order(self):132 # Let's determine run order by using the timestamp of state files133 actual_order = []134 for part_name in ("main", "dependent", "nested-dependent"):135 state_dir = os.path.join(self.parts_dir, part_name, "state")136 with contextlib.suppress(FileNotFoundError):137 for step_name in os.listdir(state_dir):138 path = os.path.join(state_dir, step_name)139 actual_order.append(140 {141 "part": part_name,142 "step": steps.get_step_by_name(step_name),143 "timestamp": os.stat(path).st_mtime,144 }145 )146 # Now sort by timestamp to get real order147 return sorted(actual_order, key=lambda k: k["timestamp"])148 def assert_parts_dirty(self, expected_parts, hint):149 cache = StatusCache(self.project_config)150 dirty_parts = []151 for part in self.project_config.parts.all_parts:152 for step in steps.STEPS:153 if cache.get_dirty_report(part, step):154 dirty_parts.append(dict(part=part.name, step=step))155 self.assertThat(dirty_parts, HasLength(len(expected_parts)), hint)156 for expected in expected_parts:157 self.assertThat(dirty_parts, Contains(expected), hint)158 def assert_parts_cleaned(self, earlier_parts, current_parts, expected_parts, hint):159 cleaned_parts = []160 for earlier in earlier_parts:161 earlier_part = earlier["part"]162 earlier_step = earlier["step"]163 found = False164 for current in current_parts:165 if earlier_part == current["part"] and earlier_step == current["step"]:166 found = True167 break168 if not found:169 cleaned_parts.append(dict(part=earlier_part, step=earlier_step))170 self.assertThat(cleaned_parts, HasLength(len(expected_parts)), hint)171 for expected in expected_parts:172 self.assertThat(cleaned_parts, Contains(expected), hint)173 def assert_run_order_equal(self, actual_order, expected_order, hint):174 self.assertThat(actual_order, HasLength(len(expected_order)), hint)175 for actual, expected in zip(actual_order, expected_order):176 actual_tuple = (actual["part"], actual["step"])177 expected_tuple = (expected["part"], expected["step"])178 self.assertThat(179 actual_tuple,180 Equals(expected_tuple),181 "expected {} {}".format(expected_tuple, hint),182 )183class ReStepOrderTestBase(OrderTestBase):184 def run_test(self):185 lifecycle.execute(186 self.initial_step, self.project_config, part_names=self.initial_parts187 )188 initial_order = self.get_run_order()189 self.assert_run_order_equal(initial_order, self.expected_initial, "(initial)")190 lifecycle.execute(191 self.test_step, self.project_config, part_names=self.test_parts192 )193 current_order = self.get_run_order()194 test_order = [o for o in current_order if o not in initial_order]195 self.assert_run_order_equal(test_order, self.expected_test, "(test)")196 self.assert_parts_cleaned(197 initial_order, current_order, self.expected_test_cleaned, "(cleaned)"198 )199 self.assert_run_order_equal(200 self.get_run_order(), self.expected_final, "(final)"201 )202 self.assert_parts_dirty(self.expected_dirty, "(dirty)")203class MainTest(ReStepOrderTestBase):204 def test_pull_repull(self):205 self.set_attributes(206 {207 "initial_step": steps.PULL,208 "initial_parts": ["main"],209 "test_parts": ["main"],210 "test_step": steps.PULL,211 "expected_initial": pull_order("main"),212 "expected_test": pull_order("main"),213 "expected_test_cleaned": [],214 "expected_final": pull_order("main"),215 "expected_dirty": [],216 }217 )218 self.run_test()219 def test_build_repull(self):220 self.set_attributes(221 {222 "initial_step": steps.BUILD,223 "initial_parts": ["main"],224 "test_parts": ["main"],225 "test_step": steps.PULL,226 "expected_initial": build_order("main"),227 "expected_test": pull_order("main"),228 "expected_test_cleaned": [dict(part="main", step=steps.BUILD)],229 "expected_final": pull_order("main"),230 "expected_dirty": [],231 }232 )233 self.run_test()234 def test_stage_repull(self):235 self.set_attributes(236 {237 "initial_step": steps.STAGE,238 "initial_parts": ["main"],239 "test_parts": ["main"],240 "test_step": steps.PULL,241 "expected_initial": stage_order("main"),242 "expected_test": pull_order("main"),243 "expected_test_cleaned": [244 dict(part="main", step=steps.BUILD),245 dict(part="main", step=steps.STAGE),246 ],247 "expected_final": pull_order("main"),248 "expected_dirty": [],249 }250 )251 self.run_test()252 def test_prime_repull(self):253 self.set_attributes(254 {255 "initial_step": steps.PRIME,256 "initial_parts": ["main"],257 "test_parts": ["main"],258 "test_step": steps.PULL,259 "expected_initial": prime_order("main"),260 "expected_test": pull_order("main"),261 "expected_test_cleaned": [262 dict(part="main", step=steps.BUILD),263 dict(part="main", step=steps.STAGE),264 dict(part="main", step=steps.PRIME),265 ],266 "expected_final": pull_order("main"),267 "expected_dirty": [],268 }269 )270 self.run_test()271 def test_all_pull_repull(self):272 self.set_attributes(273 {274 "initial_step": steps.PULL,275 "initial_parts": [],276 "test_parts": ["main"],277 "test_step": steps.PULL,278 "expected_initial": pull_order(),279 "expected_test": pull_order("main"),280 "expected_test_cleaned": [281 dict(part="main", step=steps.BUILD),282 dict(part="main", step=steps.STAGE),283 ],284 "expected_final": [285 dict(part="dependent", step=steps.PULL),286 dict(part="dependent", step=steps.BUILD),287 dict(part="dependent", step=steps.STAGE),288 dict(part="nested-dependent", step=steps.PULL),289 ]290 + pull_order("main"),291 "expected_dirty": [292 dict(part="dependent", step=steps.PULL),293 dict(part="dependent", step=steps.BUILD),294 dict(part="dependent", step=steps.STAGE),295 dict(part="nested-dependent", step=steps.PULL),296 ],297 }298 )299 self.run_test()300 def test_all_build_repull(self):301 self.set_attributes(302 {303 "initial_step": steps.BUILD,304 "initial_parts": [],305 "test_parts": ["main"],306 "test_step": steps.PULL,307 "expected_initial": build_order(),308 "expected_test": pull_order("main"),309 "expected_test_cleaned": [310 dict(part="main", step=steps.BUILD),311 dict(part="main", step=steps.STAGE),312 ],313 "expected_final": [314 dict(part="dependent", step=steps.PULL),315 dict(part="dependent", step=steps.BUILD),316 dict(part="dependent", step=steps.STAGE),317 dict(part="nested-dependent", step=steps.PULL),318 dict(part="nested-dependent", step=steps.BUILD),319 ]320 + pull_order("main"),321 "expected_dirty": [322 dict(part="dependent", step=steps.PULL),323 dict(part="dependent", step=steps.BUILD),324 dict(part="dependent", step=steps.STAGE),325 dict(part="nested-dependent", step=steps.PULL),326 dict(part="nested-dependent", step=steps.BUILD),327 ],328 }329 )330 self.run_test()331 def test_all_stage_repull(self):332 self.set_attributes(333 {334 "initial_step": steps.STAGE,335 "initial_parts": [],336 "test_parts": ["main"],337 "test_step": steps.PULL,338 "expected_initial": stage_order(),339 "expected_test": pull_order("main"),340 "expected_test_cleaned": [341 dict(part="main", step=steps.BUILD),342 dict(part="main", step=steps.STAGE),343 ],344 "expected_final": [345 dict(part="dependent", step=steps.PULL),346 dict(part="dependent", step=steps.BUILD),347 dict(part="dependent", step=steps.STAGE),348 dict(part="nested-dependent", step=steps.PULL),349 dict(part="nested-dependent", step=steps.BUILD),350 dict(part="nested-dependent", step=steps.STAGE),351 ]352 + pull_order("main"),353 "expected_dirty": [354 dict(part="dependent", step=steps.PULL),355 dict(part="dependent", step=steps.BUILD),356 dict(part="dependent", step=steps.STAGE),357 dict(part="nested-dependent", step=steps.PULL),358 dict(part="nested-dependent", step=steps.BUILD),359 dict(part="nested-dependent", step=steps.STAGE),360 ],361 }362 )363 self.run_test()364 def test_all_prime_repull(self):365 self.set_attributes(366 {367 "initial_step": steps.PRIME,368 "initial_parts": [],369 "test_parts": ["main"],370 "test_step": steps.PULL,371 "expected_initial": prime_order(),372 "expected_test": pull_order("main"),373 "expected_test_cleaned": [374 dict(part="main", step=steps.BUILD),375 dict(part="main", step=steps.STAGE),376 dict(part="main", step=steps.PRIME),377 ],378 "expected_final": [379 dict(part="dependent", step=steps.PULL),380 dict(part="dependent", step=steps.BUILD),381 dict(part="dependent", step=steps.STAGE),382 dict(part="nested-dependent", step=steps.PULL),383 dict(part="nested-dependent", step=steps.BUILD),384 dict(part="nested-dependent", step=steps.STAGE),385 dict(part="dependent", step=steps.PRIME),386 dict(part="nested-dependent", step=steps.PRIME),387 ]388 + pull_order("main"),389 "expected_dirty": [390 dict(part="dependent", step=steps.PULL),391 dict(part="dependent", step=steps.BUILD),392 dict(part="dependent", step=steps.STAGE),393 dict(part="dependent", step=steps.PRIME),394 dict(part="nested-dependent", step=steps.PULL),395 dict(part="nested-dependent", step=steps.BUILD),396 dict(part="nested-dependent", step=steps.STAGE),397 dict(part="nested-dependent", step=steps.PRIME),398 ],399 }400 )401 self.run_test()402 def test_build_rebuild(self):403 self.set_attributes(404 {405 "initial_step": steps.BUILD,406 "initial_parts": ["main"],407 "test_parts": ["main"],408 "test_step": steps.BUILD,409 "expected_initial": build_order("main"),410 "expected_test": [dict(part="main", step=steps.BUILD)],411 "expected_test_cleaned": [],412 "expected_final": build_order("main"),413 "expected_dirty": [],414 }415 )416 self.run_test()417 def test_stage_rebuild(self):418 self.set_attributes(419 {420 "initial_step": steps.STAGE,421 "initial_parts": ["main"],422 "test_parts": ["main"],423 "test_step": steps.BUILD,424 "expected_initial": stage_order("main"),425 "expected_test": [dict(part="main", step=steps.BUILD)],426 "expected_test_cleaned": [dict(part="main", step=steps.STAGE)],427 "expected_final": build_order("main"),428 "expected_dirty": [],429 }430 )431 self.run_test()432 def test_prime_rebuild(self):433 self.set_attributes(434 {435 "initial_step": steps.PRIME,436 "initial_parts": ["main"],437 "test_parts": ["main"],438 "test_step": steps.BUILD,439 "expected_initial": prime_order("main"),440 "expected_test": [dict(part="main", step=steps.BUILD)],441 "expected_test_cleaned": [442 dict(part="main", step=steps.STAGE),443 dict(part="main", step=steps.PRIME),444 ],445 "expected_final": build_order("main"),446 "expected_dirty": [],447 }448 )449 self.run_test()450 def test_all_build_rebuild(self):451 self.set_attributes(452 {453 "initial_step": steps.BUILD,454 "initial_parts": [],455 "test_parts": ["main"],456 "test_step": steps.BUILD,457 "expected_initial": build_order(),458 "expected_test": [dict(part="main", step=steps.BUILD)],459 "expected_test_cleaned": [dict(part="main", step=steps.STAGE)],460 "expected_final": [461 dict(part="main", step=steps.PULL),462 dict(part="dependent", step=steps.PULL),463 dict(part="dependent", step=steps.BUILD),464 dict(part="dependent", step=steps.STAGE),465 dict(part="nested-dependent", step=steps.PULL),466 dict(part="nested-dependent", step=steps.BUILD),467 dict(part="main", step=steps.BUILD),468 ],469 "expected_dirty": [470 dict(part="dependent", step=steps.PULL),471 dict(part="dependent", step=steps.BUILD),472 dict(part="dependent", step=steps.STAGE),473 dict(part="nested-dependent", step=steps.PULL),474 dict(part="nested-dependent", step=steps.BUILD),475 ],476 }477 )478 self.run_test()479 def test_all_stage_rebuild(self):480 self.set_attributes(481 {482 "initial_step": steps.STAGE,483 "initial_parts": [],484 "test_parts": ["main"],485 "test_step": steps.BUILD,486 "expected_initial": stage_order(),487 "expected_test": [dict(part="main", step=steps.BUILD)],488 "expected_test_cleaned": [dict(part="main", step=steps.STAGE)],489 "expected_final": [490 dict(part="main", step=steps.PULL),491 dict(part="dependent", step=steps.PULL),492 dict(part="dependent", step=steps.BUILD),493 dict(part="dependent", step=steps.STAGE),494 dict(part="nested-dependent", step=steps.PULL),495 dict(part="nested-dependent", step=steps.BUILD),496 dict(part="nested-dependent", step=steps.STAGE),497 dict(part="main", step=steps.BUILD),498 ],499 "expected_dirty": [500 dict(part="dependent", step=steps.PULL),501 dict(part="dependent", step=steps.BUILD),502 dict(part="dependent", step=steps.STAGE),503 dict(part="nested-dependent", step=steps.PULL),504 dict(part="nested-dependent", step=steps.BUILD),505 dict(part="nested-dependent", step=steps.STAGE),506 ],507 }508 )509 self.run_test()510 def test_all_prime_rebuild(self):511 self.set_attributes(512 {513 "initial_step": steps.PRIME,514 "initial_parts": [],515 "test_parts": ["main"],516 "test_step": steps.BUILD,517 "expected_initial": prime_order(),518 "expected_test": [dict(part="main", step=steps.BUILD)],519 "expected_test_cleaned": [520 dict(part="main", step=steps.STAGE),521 dict(part="main", step=steps.PRIME),522 ],523 "expected_final": [524 dict(part="main", step=steps.PULL),525 dict(part="dependent", step=steps.PULL),526 dict(part="dependent", step=steps.BUILD),527 dict(part="dependent", step=steps.STAGE),528 dict(part="nested-dependent", step=steps.PULL),529 dict(part="nested-dependent", step=steps.BUILD),530 dict(part="nested-dependent", step=steps.STAGE),531 dict(part="dependent", step=steps.PRIME),532 dict(part="nested-dependent", step=steps.PRIME),533 dict(part="main", step=steps.BUILD),534 ],535 "expected_dirty": [536 dict(part="dependent", step=steps.PULL),537 dict(part="dependent", step=steps.BUILD),538 dict(part="dependent", step=steps.STAGE),539 dict(part="dependent", step=steps.PRIME),540 dict(part="nested-dependent", step=steps.PULL),541 dict(part="nested-dependent", step=steps.BUILD),542 dict(part="nested-dependent", step=steps.STAGE),543 dict(part="nested-dependent", step=steps.PRIME),544 ],545 }546 )547 self.run_test()548 def test_stage_restage(self):549 self.set_attributes(550 {551 "initial_step": steps.STAGE,552 "initial_parts": ["main"],553 "test_parts": ["main"],554 "test_step": steps.STAGE,555 "expected_initial": stage_order("main"),556 "expected_test": [dict(part="main", step=steps.STAGE)],557 "expected_test_cleaned": [],558 "expected_final": stage_order("main"),559 "expected_dirty": [],560 }561 )562 self.run_test()563 def test_prime_restage(self):564 self.set_attributes(565 {566 "initial_step": steps.PRIME,567 "initial_parts": ["main"],568 "test_parts": ["main"],569 "test_step": steps.STAGE,570 "expected_initial": prime_order("main"),571 "expected_test": [dict(part="main", step=steps.STAGE)],572 "expected_test_cleaned": [dict(part="main", step=steps.PRIME)],573 "expected_final": stage_order("main"),574 "expected_dirty": [],575 }576 )577 self.run_test()578 def test_all_stage_restage(self):579 self.set_attributes(580 {581 "initial_step": steps.STAGE,582 "initial_parts": [],583 "test_parts": ["main"],584 "test_step": steps.STAGE,585 "expected_initial": stage_order(),586 "expected_test": [dict(part="main", step=steps.STAGE)],587 "expected_test_cleaned": [],588 "expected_final": build_order("main")589 + [590 dict(part="dependent", step=steps.PULL),591 dict(part="dependent", step=steps.BUILD),592 dict(part="dependent", step=steps.STAGE),593 dict(part="nested-dependent", step=steps.PULL),594 dict(part="nested-dependent", step=steps.BUILD),595 dict(part="nested-dependent", step=steps.STAGE),596 dict(part="main", step=steps.STAGE),597 ],598 "expected_dirty": [599 dict(part="dependent", step=steps.PULL),600 dict(part="dependent", step=steps.BUILD),601 dict(part="dependent", step=steps.STAGE),602 dict(part="nested-dependent", step=steps.PULL),603 dict(part="nested-dependent", step=steps.BUILD),604 dict(part="nested-dependent", step=steps.STAGE),605 ],606 }607 )608 self.run_test()609 def test_all_prime_restage(self):610 self.set_attributes(611 {612 "initial_step": steps.PRIME,613 "initial_parts": [],614 "test_parts": ["main"],615 "test_step": steps.STAGE,616 "expected_initial": prime_order(),617 "expected_test": [dict(part="main", step=steps.STAGE)],618 "expected_test_cleaned": [dict(part="main", step=steps.PRIME)],619 "expected_final": build_order("main")620 + [621 dict(part="dependent", step=steps.PULL),622 dict(part="dependent", step=steps.BUILD),623 dict(part="dependent", step=steps.STAGE),624 dict(part="nested-dependent", step=steps.PULL),625 dict(part="nested-dependent", step=steps.BUILD),626 dict(part="nested-dependent", step=steps.STAGE),627 dict(part="dependent", step=steps.PRIME),628 dict(part="nested-dependent", step=steps.PRIME),629 dict(part="main", step=steps.STAGE),630 ],631 "expected_dirty": [632 dict(part="dependent", step=steps.PULL),633 dict(part="dependent", step=steps.BUILD),634 dict(part="dependent", step=steps.STAGE),635 dict(part="dependent", step=steps.PRIME),636 dict(part="nested-dependent", step=steps.PULL),637 dict(part="nested-dependent", step=steps.BUILD),638 dict(part="nested-dependent", step=steps.STAGE),639 dict(part="nested-dependent", step=steps.PRIME),640 ],641 }642 )643 self.run_test()644 def test_prime_reprime(self):645 self.set_attributes(646 {647 "initial_step": steps.PRIME,648 "initial_parts": ["main"],649 "test_parts": ["main"],650 "test_step": steps.PRIME,651 "expected_initial": prime_order("main"),652 "expected_test": [dict(part="main", step=steps.PRIME)],653 "expected_test_cleaned": [],654 "expected_final": prime_order("main"),655 "expected_dirty": [],656 }657 )658 self.run_test()659 def test_all_prime_reprime(self):660 self.set_attributes(661 {662 "initial_step": steps.PRIME,663 "initial_parts": [],664 "test_parts": ["main"],665 "test_step": steps.PRIME,666 "expected_initial": prime_order(),667 "expected_test": [dict(part="main", step=steps.PRIME)],668 "expected_test_cleaned": [],669 "expected_final": stage_order()670 + [671 dict(part="dependent", step=steps.PRIME),672 dict(part="nested-dependent", step=steps.PRIME),673 dict(part="main", step=steps.PRIME),674 ],675 "expected_dirty": [676 dict(part="dependent", step=steps.PRIME),677 dict(part="nested-dependent", step=steps.PRIME),678 ],679 }680 )681 self.run_test()682class DependentTest(ReStepOrderTestBase):683 def test_pull_repull(self):684 self.set_attributes(685 {686 "initial_step": steps.PULL,687 "initial_parts": ["dependent"],688 "test_parts": ["dependent"],689 "test_step": steps.PULL,690 "expected_initial": pull_order("dependent"),691 "expected_test": [dict(part="dependent", step=steps.PULL)],692 "expected_test_cleaned": [],693 "expected_final": pull_order("dependent"),694 "expected_dirty": [],695 }696 )697 self.run_test()698 def test_build_repull(self):699 self.set_attributes(700 {701 "initial_step": steps.BUILD,702 "initial_parts": ["dependent"],703 "test_parts": ["dependent"],704 "test_step": steps.PULL,705 "expected_initial": build_order("dependent"),706 "expected_test": [dict(part="dependent", step=steps.PULL)],707 "expected_test_cleaned": [dict(part="dependent", step=steps.BUILD)],708 "expected_final": pull_order("dependent"),709 "expected_dirty": [],710 }711 )712 self.run_test()713 def test_stage_repull(self):714 self.set_attributes(715 {716 "initial_step": steps.STAGE,717 "initial_parts": ["dependent"],718 "test_parts": ["dependent"],719 "test_step": steps.PULL,720 "expected_initial": stage_order("dependent"),721 "expected_test": [dict(part="dependent", step=steps.PULL)],722 "expected_test_cleaned": [723 dict(part="dependent", step=steps.BUILD),724 dict(part="dependent", step=steps.STAGE),725 ],726 "expected_final": pull_order("dependent"),727 "expected_dirty": [],728 }729 )730 self.run_test()731 def test_prime_repull(self):732 self.set_attributes(733 {734 "initial_step": steps.PRIME,735 "initial_parts": ["dependent"],736 "test_parts": ["dependent"],737 "test_step": steps.PULL,738 "expected_initial": prime_order("dependent"),739 "expected_test": [dict(part="dependent", step=steps.PULL)],740 "expected_test_cleaned": [741 dict(part="dependent", step=steps.BUILD),742 dict(part="dependent", step=steps.STAGE),743 dict(part="dependent", step=steps.PRIME),744 ],745 "expected_final": prime_order("main")746 + [dict(part="dependent", step=steps.PULL)],747 "expected_dirty": [],748 }749 )750 self.run_test()751 def test_all_pull_repull(self):752 self.set_attributes(753 {754 "initial_step": steps.PULL,755 "initial_parts": [],756 "test_parts": ["dependent"],757 "test_step": steps.PULL,758 "expected_initial": pull_order(),759 "expected_test": [dict(part="dependent", step=steps.PULL)],760 "expected_test_cleaned": [761 dict(part="dependent", step=steps.BUILD),762 dict(part="dependent", step=steps.STAGE),763 ],764 "expected_final": stage_order("main")765 + [766 dict(part="nested-dependent", step=steps.PULL),767 dict(part="dependent", step=steps.PULL),768 ],769 "expected_dirty": [dict(part="nested-dependent", step=steps.PULL)],770 }771 )772 self.run_test()773 def test_all_build_repull(self):774 self.set_attributes(775 {776 "initial_step": steps.BUILD,777 "initial_parts": [],778 "test_parts": ["dependent"],779 "test_step": steps.PULL,780 "expected_initial": build_order(),781 "expected_test": [dict(part="dependent", step=steps.PULL)],782 "expected_test_cleaned": [783 dict(part="dependent", step=steps.BUILD),784 dict(part="dependent", step=steps.STAGE),785 ],786 "expected_final": stage_order("main")787 + [788 dict(part="nested-dependent", step=steps.PULL),789 dict(part="nested-dependent", step=steps.BUILD),790 dict(part="dependent", step=steps.PULL),791 ],792 "expected_dirty": [793 dict(part="nested-dependent", step=steps.PULL),794 dict(part="nested-dependent", step=steps.BUILD),795 ],796 }797 )798 self.run_test()799 def test_all_stage_repull(self):800 self.set_attributes(801 {802 "initial_step": steps.STAGE,803 "initial_parts": [],804 "test_parts": ["dependent"],805 "test_step": steps.PULL,806 "expected_initial": stage_order(),807 "expected_test": [dict(part="dependent", step=steps.PULL)],808 "expected_test_cleaned": [809 dict(part="dependent", step=steps.BUILD),810 dict(part="dependent", step=steps.STAGE),811 ],812 "expected_final": stage_order("main")813 + [814 dict(part="nested-dependent", step=steps.PULL),815 dict(part="nested-dependent", step=steps.BUILD),816 dict(part="nested-dependent", step=steps.STAGE),817 dict(part="dependent", step=steps.PULL),818 ],819 "expected_dirty": [820 dict(part="nested-dependent", step=steps.PULL),821 dict(part="nested-dependent", step=steps.BUILD),822 dict(part="nested-dependent", step=steps.STAGE),823 ],824 }825 )826 self.run_test()827 def test_all_prime_repull(self):828 self.set_attributes(829 {830 "initial_step": steps.PRIME,831 "initial_parts": [],832 "test_parts": ["dependent"],833 "test_step": steps.PULL,834 "expected_initial": prime_order(),835 "expected_test": [dict(part="dependent", step=steps.PULL)],836 "expected_test_cleaned": [837 dict(part="dependent", step=steps.BUILD),838 dict(part="dependent", step=steps.STAGE),839 dict(part="dependent", step=steps.PRIME),840 ],841 "expected_final": stage_order("main")842 + [843 dict(part="nested-dependent", step=steps.PULL),844 dict(part="nested-dependent", step=steps.BUILD),845 dict(part="nested-dependent", step=steps.STAGE),846 dict(part="main", step=steps.PRIME),847 dict(part="nested-dependent", step=steps.PRIME),848 dict(part="dependent", step=steps.PULL),849 ],850 "expected_dirty": [851 dict(part="nested-dependent", step=steps.PULL),852 dict(part="nested-dependent", step=steps.BUILD),853 dict(part="nested-dependent", step=steps.STAGE),854 dict(part="nested-dependent", step=steps.PRIME),855 ],856 }857 )858 self.run_test()859 def test_build_rebuild(self):860 self.set_attributes(861 {862 "initial_step": steps.BUILD,863 "initial_parts": ["dependent"],864 "test_parts": ["dependent"],865 "test_step": steps.BUILD,866 "expected_initial": build_order("dependent"),867 "expected_test": [dict(part="dependent", step=steps.BUILD)],868 "expected_test_cleaned": [],869 "expected_final": build_order("dependent"),870 "expected_dirty": [],871 }872 )873 self.run_test()874 def test_stage_rebuild(self):875 self.set_attributes(876 {877 "initial_step": steps.STAGE,878 "initial_parts": ["dependent"],879 "test_parts": ["dependent"],880 "test_step": steps.BUILD,881 "expected_initial": stage_order("dependent"),882 "expected_test": [dict(part="dependent", step=steps.BUILD)],883 "expected_test_cleaned": [dict(part="dependent", step=steps.STAGE)],884 "expected_final": build_order("dependent"),885 "expected_dirty": [],886 }887 )888 self.run_test()889 def test_prime_rebuild(self):890 self.set_attributes(891 {892 "initial_step": steps.PRIME,893 "initial_parts": ["dependent"],894 "test_parts": ["dependent"],895 "test_step": steps.BUILD,896 "expected_initial": prime_order("dependent"),897 "expected_test": [dict(part="dependent", step=steps.BUILD)],898 "expected_test_cleaned": [899 dict(part="dependent", step=steps.STAGE),900 dict(part="dependent", step=steps.PRIME),901 ],902 "expected_final": pull_order("dependent")903 + [904 dict(part="main", step=steps.PRIME),905 dict(part="dependent", step=steps.BUILD),906 ],907 "expected_dirty": [],908 }909 )910 self.run_test()911 def test_all_build_rebuild(self):912 self.set_attributes(913 {914 "initial_step": steps.BUILD,915 "initial_parts": [],916 "test_parts": ["dependent"],917 "test_step": steps.BUILD,918 "expected_initial": build_order(),919 "expected_test": [dict(part="dependent", step=steps.BUILD)],920 "expected_test_cleaned": [dict(part="dependent", step=steps.STAGE)],921 "expected_final": stage_order("main")922 + [923 dict(part="dependent", step=steps.PULL),924 dict(part="nested-dependent", step=steps.PULL),925 dict(part="nested-dependent", step=steps.BUILD),926 dict(part="dependent", step=steps.BUILD),927 ],928 "expected_dirty": [929 dict(part="nested-dependent", step=steps.PULL),930 dict(part="nested-dependent", step=steps.BUILD),931 ],932 }933 )934 self.run_test()935 def test_all_stage_rebuild(self):936 self.set_attributes(937 {938 "initial_step": steps.STAGE,939 "initial_parts": [],940 "test_parts": ["dependent"],941 "test_step": steps.BUILD,942 "expected_initial": stage_order(),943 "expected_test": [dict(part="dependent", step=steps.BUILD)],944 "expected_test_cleaned": [dict(part="dependent", step=steps.STAGE)],945 "expected_final": stage_order("main")946 + [947 dict(part="dependent", step=steps.PULL),948 dict(part="nested-dependent", step=steps.PULL),949 dict(part="nested-dependent", step=steps.BUILD),950 dict(part="nested-dependent", step=steps.STAGE),951 dict(part="dependent", step=steps.BUILD),952 ],953 "expected_dirty": [954 dict(part="nested-dependent", step=steps.PULL),955 dict(part="nested-dependent", step=steps.BUILD),956 dict(part="nested-dependent", step=steps.STAGE),957 ],958 }959 )960 self.run_test()961 def test_all_prime_rebuild(self):962 self.set_attributes(963 {964 "initial_step": steps.PRIME,965 "initial_parts": [],966 "test_parts": ["dependent"],967 "test_step": steps.BUILD,968 "expected_initial": prime_order(),969 "expected_test": [dict(part="dependent", step=steps.BUILD)],970 "expected_test_cleaned": [971 dict(part="dependent", step=steps.STAGE),972 dict(part="dependent", step=steps.PRIME),973 ],974 "expected_final": pull_order("dependent")975 + [976 dict(part="nested-dependent", step=steps.PULL),977 dict(part="nested-dependent", step=steps.BUILD),978 dict(part="nested-dependent", step=steps.STAGE),979 dict(part="main", step=steps.PRIME),980 dict(part="nested-dependent", step=steps.PRIME),981 dict(part="dependent", step=steps.BUILD),982 ],983 "expected_dirty": [984 dict(part="nested-dependent", step=steps.PULL),985 dict(part="nested-dependent", step=steps.BUILD),986 dict(part="nested-dependent", step=steps.STAGE),987 dict(part="nested-dependent", step=steps.PRIME),988 ],989 }990 )991 self.run_test()992 def test_stage_restage(self):993 self.set_attributes(994 {995 "initial_step": steps.STAGE,996 "initial_parts": ["dependent"],997 "test_parts": ["dependent"],998 "test_step": steps.STAGE,999 "expected_initial": stage_order("dependent"),1000 "expected_test": [dict(part="dependent", step=steps.STAGE)],1001 "expected_test_cleaned": [],1002 "expected_final": stage_order("dependent"),1003 "expected_dirty": [],1004 }1005 )1006 self.run_test()1007 def test_prime_restage(self):1008 self.set_attributes(1009 {1010 "initial_step": steps.PRIME,1011 "initial_parts": ["dependent"],1012 "test_parts": ["dependent"],1013 "test_step": steps.STAGE,1014 "expected_initial": prime_order("dependent"),1015 "expected_test": [dict(part="dependent", step=steps.STAGE)],1016 "expected_test_cleaned": [dict(part="dependent", step=steps.PRIME)],1017 "expected_final": build_order("dependent")1018 + [1019 dict(part="main", step=steps.PRIME),1020 dict(part="dependent", step=steps.STAGE),1021 ],1022 "expected_dirty": [],1023 }1024 )1025 self.run_test()1026 def test_all_stage_restage(self):1027 self.set_attributes(1028 {1029 "initial_step": steps.STAGE,1030 "initial_parts": [],1031 "test_parts": ["dependent"],1032 "test_step": steps.STAGE,1033 "expected_initial": stage_order(),1034 "expected_test": [dict(part="dependent", step=steps.STAGE)],1035 "expected_test_cleaned": [],1036 "expected_final": build_order("dependent")1037 + [1038 dict(part="nested-dependent", step=steps.PULL),1039 dict(part="nested-dependent", step=steps.BUILD),1040 dict(part="nested-dependent", step=steps.STAGE),1041 dict(part="dependent", step=steps.STAGE),1042 ],1043 "expected_dirty": [1044 dict(part="nested-dependent", step=steps.PULL),1045 dict(part="nested-dependent", step=steps.BUILD),1046 dict(part="nested-dependent", step=steps.STAGE),1047 ],1048 }1049 )1050 self.run_test()1051 def test_all_prime_restage(self):1052 self.set_attributes(1053 {1054 "initial_step": steps.PRIME,1055 "initial_parts": [],1056 "test_parts": ["dependent"],1057 "test_step": steps.STAGE,1058 "expected_initial": prime_order(),1059 "expected_test": [dict(part="dependent", step=steps.STAGE)],1060 "expected_test_cleaned": [dict(part="dependent", step=steps.PRIME)],1061 "expected_final": build_order("dependent")1062 + [1063 dict(part="nested-dependent", step=steps.PULL),1064 dict(part="nested-dependent", step=steps.BUILD),1065 dict(part="nested-dependent", step=steps.STAGE),1066 dict(part="main", step=steps.PRIME),1067 dict(part="nested-dependent", step=steps.PRIME),1068 dict(part="dependent", step=steps.STAGE),1069 ],1070 "expected_dirty": [1071 dict(part="nested-dependent", step=steps.PULL),1072 dict(part="nested-dependent", step=steps.BUILD),1073 dict(part="nested-dependent", step=steps.STAGE),1074 dict(part="nested-dependent", step=steps.PRIME),1075 ],1076 }1077 )1078 self.run_test()1079 def test_prime_reprime(self):1080 self.set_attributes(1081 {1082 "initial_step": steps.PRIME,1083 "initial_parts": ["dependent"],1084 "test_parts": ["dependent"],1085 "test_step": steps.PRIME,1086 "expected_initial": prime_order("dependent"),1087 "expected_test": [dict(part="dependent", step=steps.PRIME)],1088 "expected_test_cleaned": [],1089 "expected_final": prime_order("dependent"),1090 "expected_dirty": [],1091 }1092 )1093 self.run_test()1094 def test_all_prime_reprime(self):1095 self.set_attributes(1096 {1097 "initial_step": steps.PRIME,1098 "initial_parts": [],1099 "test_parts": ["dependent"],1100 "test_step": steps.PRIME,1101 "expected_initial": prime_order(),1102 "expected_test": [dict(part="dependent", step=steps.PRIME)],1103 "expected_test_cleaned": [],1104 "expected_final": stage_order("nested-dependent")1105 + [1106 dict(part="main", step=steps.PRIME),1107 dict(part="nested-dependent", step=steps.PRIME),1108 dict(part="dependent", step=steps.PRIME),1109 ],1110 "expected_dirty": [dict(part="nested-dependent", step=steps.PRIME)],1111 }1112 ),1113 self.run_test()1114class NestedDependentTest(ReStepOrderTestBase):1115 def test_pull_repull(self):1116 self.set_attributes(1117 {1118 "initial_step": steps.PULL,1119 "initial_parts": ["nested-dependent"],1120 "test_parts": ["nested-dependent"],1121 "test_step": steps.PULL,1122 "expected_initial": pull_order("nested-dependent"),1123 "expected_test": [dict(part="nested-dependent", step=steps.PULL)],1124 "expected_test_cleaned": [],1125 "expected_final": pull_order("nested-dependent"),1126 "expected_dirty": [],1127 }1128 )1129 self.run_test()1130 def test_build_repull(self):1131 self.set_attributes(1132 {1133 "initial_step": steps.BUILD,1134 "initial_parts": ["nested-dependent"],1135 "test_parts": ["nested-dependent"],1136 "test_step": steps.PULL,1137 "expected_initial": build_order("nested-dependent"),1138 "expected_test": [dict(part="nested-dependent", step=steps.PULL)],1139 "expected_test_cleaned": [1140 dict(part="nested-dependent", step=steps.BUILD)1141 ],1142 "expected_final": pull_order("nested-dependent"),1143 "expected_dirty": [],1144 }1145 )1146 self.run_test()1147 def test_stage_repull(self):1148 self.set_attributes(1149 {1150 "initial_step": steps.STAGE,1151 "initial_parts": ["nested-dependent"],1152 "test_parts": ["nested-dependent"],1153 "test_step": steps.PULL,1154 "expected_initial": stage_order("nested-dependent"),1155 "expected_test": [dict(part="nested-dependent", step=steps.PULL)],1156 "expected_test_cleaned": [1157 dict(part="nested-dependent", step=steps.BUILD),1158 dict(part="nested-dependent", step=steps.STAGE),1159 ],1160 "expected_final": pull_order("nested-dependent"),1161 "expected_dirty": [],1162 }1163 )1164 self.run_test()1165 def test_prime_repull(self):1166 self.set_attributes(1167 {1168 "initial_step": steps.PRIME,1169 "initial_parts": ["nested-dependent"],1170 "test_parts": ["nested-dependent"],1171 "test_step": steps.PULL,1172 "expected_initial": prime_order("nested-dependent"),1173 "expected_test": [dict(part="nested-dependent", step=steps.PULL)],1174 "expected_test_cleaned": [1175 dict(part="nested-dependent", step=steps.BUILD),1176 dict(part="nested-dependent", step=steps.STAGE),1177 dict(part="nested-dependent", step=steps.PRIME),1178 ],1179 "expected_final": prime_order("dependent")1180 + [dict(part="nested-dependent", step=steps.PULL)],1181 "expected_dirty": [],1182 }1183 )1184 self.run_test()1185 def test_build_rebuild(self):1186 self.set_attributes(1187 {1188 "initial_step": steps.BUILD,1189 "initial_parts": ["nested-dependent"],1190 "test_parts": ["nested-dependent"],1191 "test_step": steps.BUILD,1192 "expected_initial": build_order("nested-dependent"),1193 "expected_test": [dict(part="nested-dependent", step=steps.BUILD)],1194 "expected_test_cleaned": [],1195 "expected_final": build_order("nested-dependent"),1196 "expected_dirty": [],1197 }1198 )1199 self.run_test()1200 def test_stage_rebuild(self):1201 self.set_attributes(1202 {1203 "initial_step": steps.STAGE,1204 "initial_parts": ["nested-dependent"],1205 "test_parts": ["nested-dependent"],1206 "test_step": steps.BUILD,1207 "expected_initial": stage_order("nested-dependent"),1208 "expected_test": [dict(part="nested-dependent", step=steps.BUILD)],1209 "expected_test_cleaned": [1210 dict(part="nested-dependent", step=steps.STAGE)1211 ],1212 "expected_final": build_order("nested-dependent"),1213 "expected_dirty": [],1214 }1215 )1216 self.run_test()1217 def test_prime_rebuild(self):1218 self.set_attributes(1219 {1220 "initial_step": steps.PRIME,1221 "initial_parts": ["nested-dependent"],1222 "test_parts": ["nested-dependent"],1223 "test_step": steps.BUILD,1224 "expected_initial": prime_order("nested-dependent"),1225 "expected_test": [dict(part="nested-dependent", step=steps.BUILD)],1226 "expected_test_cleaned": [1227 dict(part="nested-dependent", step=steps.STAGE),1228 dict(part="nested-dependent", step=steps.PRIME),1229 ],1230 "expected_final": pull_order("nested-dependent")1231 + [1232 dict(part="main", step=steps.PRIME),1233 dict(part="dependent", step=steps.PRIME),1234 dict(part="nested-dependent", step=steps.BUILD),1235 ],1236 "expected_dirty": [],1237 }1238 )1239 self.run_test()1240 def test_stage_restage(self):1241 self.set_attributes(1242 {1243 "initial_step": steps.STAGE,1244 "initial_parts": ["nested-dependent"],1245 "test_parts": ["nested-dependent"],1246 "test_step": steps.STAGE,1247 "expected_initial": stage_order("nested-dependent"),1248 "expected_test": [dict(part="nested-dependent", step=steps.STAGE)],1249 "expected_test_cleaned": [],1250 "expected_final": stage_order("nested-dependent"),1251 "expected_dirty": [],1252 }1253 )1254 self.run_test()1255 def test_prime_restage(self):1256 self.set_attributes(1257 {1258 "initial_step": steps.PRIME,1259 "initial_parts": ["nested-dependent"],1260 "test_parts": ["nested-dependent"],1261 "test_step": steps.STAGE,1262 "expected_initial": prime_order("nested-dependent"),1263 "expected_test": [dict(part="nested-dependent", step=steps.STAGE)],1264 "expected_test_cleaned": [1265 dict(part="nested-dependent", step=steps.PRIME)1266 ],1267 "expected_final": build_order("nested-dependent")1268 + [1269 dict(part="main", step=steps.PRIME),1270 dict(part="dependent", step=steps.PRIME),1271 dict(part="nested-dependent", step=steps.STAGE),1272 ],1273 "expected_dirty": [],1274 }1275 )1276 self.run_test()1277 def test_prime_reprime(self):1278 self.set_attributes(1279 {1280 "initial_step": steps.PRIME,1281 "initial_parts": ["nested-dependent"],1282 "test_parts": ["nested-dependent"],1283 "test_step": steps.PRIME,1284 "expected_initial": prime_order("nested-dependent"),1285 "expected_test": [dict(part="nested-dependent", step=steps.PRIME)],1286 "expected_test_cleaned": [],1287 "expected_final": prime_order("nested-dependent"),1288 "expected_dirty": [],1289 }1290 )1291 self.run_test()1292class DirtyOutdatedTestBase(OrderTestBase):1293 def setUp(self):1294 super().setUp()1295 for directory in ("main", "dependent", "nested-dependent"):1296 os.mkdir(directory)1297 self.project_config = self.make_snapcraft_project(1298 textwrap.dedent(1299 """\1300 parts:1301 main:1302 plugin: dump1303 source: main/1304 dependent:1305 plugin: dump1306 source: dependent/1307 after: [main]1308 nested-dependent:1309 plugin: dump1310 source: nested-dependent/1311 after: [dependent]1312 """1313 )1314 )1315 self.dirty_parts = []1316 dirty_parts = self.dirty_parts1317 original_dirty_report = pluginhandler.PluginHandler.get_dirty_report1318 def _fake_dirty_report(self, step):1319 nonlocal dirty_parts1320 if dict(part=self.name, step=step) in dirty_parts:1321 return pluginhandler.DirtyReport(dirty_properties={"forced"})1322 return original_dirty_report(self, step)1323 patcher = mock.patch.object(1324 pluginhandler.PluginHandler, "get_dirty_report", _fake_dirty_report1325 )1326 patcher.start()1327 self.addCleanup(patcher.stop)1328 original_clean = pluginhandler.PluginHandler.clean1329 def _fake_clean(self, staged_state, primed_state, step):1330 nonlocal dirty_parts1331 original_clean(self, staged_state, primed_state, step)1332 with contextlib.suppress(ValueError):1333 dirty_parts.remove(dict(part=self.name, step=step))1334 patcher = mock.patch.object(pluginhandler.PluginHandler, "clean", _fake_clean)1335 patcher.start()1336 self.addCleanup(patcher.stop)1337 def make_outdated(self, part_name, step):1338 if step == steps.PULL:1339 open(os.path.join(part_name, "file"), "w").close()1340 else:1341 part = self.project_config.parts.get_part(part_name)1342 state_file_path = states.get_step_state_file(part.plugin.statedir, step)1343 open(state_file_path, "w").close()1344 def run_test(self):1345 # Prime all parts1346 lifecycle.execute(steps.PRIME, self.project_config)1347 initial_order = self.get_run_order()1348 self.assert_run_order_equal(initial_order, self.expected_initial, "(initial)")1349 if self.test_type == "dirty":1350 # Make some parts dirty1351 self.dirty_parts.extend(self.test_parts)1352 else:1353 # Make some parts outdated1354 for part in self.test_parts:1355 self.make_outdated(part["part"], part["step"])1356 # Prime again1357 lifecycle.execute(steps.PRIME, self.project_config)1358 current_order = self.get_run_order()1359 test_order = [o for o in current_order if o not in initial_order]1360 self.assert_run_order_equal(test_order, self.expected_test, "(test)")1361 self.assert_parts_cleaned(initial_order, current_order, [], "(cleaned)")1362 self.assert_run_order_equal(1363 self.get_run_order(), self.expected_final, "(final)"1364 )1365 self.assert_parts_dirty([], "(dirty)")1366class DirtyTest(DirtyOutdatedTestBase):1367 test_type = "dirty"1368 def test_main_pull_dirty(self):1369 self.set_attributes(1370 {1371 "test_parts": [dict(part="main", step=steps.PULL)],1372 "expected_initial": prime_order(),1373 "expected_test": prime_order(),1374 "expected_final": prime_order(),1375 }1376 )1377 self.run_test()1378 def test_main_build_dirty(self):1379 self.set_attributes(1380 {1381 "test_parts": [dict(part="main", step=steps.BUILD)],1382 "expected_initial": prime_order(),1383 "expected_test": [1384 dict(part="main", step=steps.BUILD),1385 dict(part="main", step=steps.STAGE),1386 dict(part="dependent", step=steps.PULL),1387 dict(part="dependent", step=steps.BUILD),1388 dict(part="dependent", step=steps.STAGE),1389 dict(part="nested-dependent", step=steps.PULL),1390 dict(part="nested-dependent", step=steps.BUILD),1391 dict(part="nested-dependent", step=steps.STAGE),1392 dict(part="main", step=steps.PRIME),1393 dict(part="dependent", step=steps.PRIME),1394 dict(part="nested-dependent", step=steps.PRIME),1395 ],1396 "expected_final": prime_order(),1397 }1398 )1399 self.run_test()1400 def test_main_stage_dirty(self):1401 self.set_attributes(1402 {1403 "test_parts": [dict(part="main", step=steps.STAGE)],1404 "expected_initial": prime_order(),1405 "expected_test": [1406 dict(part="main", step=steps.STAGE),1407 dict(part="dependent", step=steps.PULL),1408 dict(part="dependent", step=steps.BUILD),1409 dict(part="dependent", step=steps.STAGE),1410 dict(part="nested-dependent", step=steps.PULL),1411 dict(part="nested-dependent", step=steps.BUILD),1412 dict(part="nested-dependent", step=steps.STAGE),1413 dict(part="main", step=steps.PRIME),1414 dict(part="dependent", step=steps.PRIME),1415 dict(part="nested-dependent", step=steps.PRIME),1416 ],1417 "expected_test_cleaned": [],1418 "expected_final": prime_order(),1419 }1420 )1421 self.run_test()1422 def test_main_prime_dirty(self):1423 self.set_attributes(1424 {1425 "test_parts": [dict(part="main", step=steps.PRIME)],1426 "expected_initial": prime_order(),1427 "expected_test": [1428 dict(part="main", step=steps.PRIME),1429 dict(part="dependent", step=steps.PRIME),1430 dict(part="nested-dependent", step=steps.PRIME),1431 ],1432 "expected_test_cleaned": [],1433 "expected_final": prime_order(),1434 }1435 )1436 self.run_test()1437 def dependent_pull_dirty(self):1438 self.set_attributes(1439 {1440 "test_parts": [dict(part="dependent", step=steps.PULL)],1441 "expected_initial": prime_order(),1442 "expected_test": [1443 dict(part="dependent", step=steps.PULL),1444 dict(part="dependent", step=steps.BUILD),1445 dict(part="dependent", step=steps.STAGE),1446 dict(part="nested-dependent", step=steps.PULL),1447 dict(part="nested-dependent", step=steps.BUILD),1448 dict(part="nested-dependent", step=steps.STAGE),1449 dict(part="dependent", step=steps.PRIME),1450 dict(part="nested-dependent", step=steps.PRIME),1451 ],1452 "expected_final": prime_order("main")1453 + [1454 dict(part="dependent", step=steps.PULL),1455 dict(part="dependent", step=steps.BUILD),1456 dict(part="dependent", step=steps.STAGE),1457 dict(part="nested-dependent", step=steps.PULL),1458 dict(part="nested-dependent", step=steps.BUILD),1459 dict(part="nested-dependent", step=steps.STAGE),1460 dict(part="dependent", step=steps.PRIME),1461 dict(part="nested-dependent", step=steps.PRIME),1462 ],1463 }1464 )1465 self.run_test()1466 def test_dependent_build_dirty(self):1467 self.set_attributes(1468 {1469 "test_parts": [dict(part="dependent", step=steps.BUILD)],1470 "expected_initial": prime_order(),1471 "expected_test": [1472 dict(part="dependent", step=steps.BUILD),1473 dict(part="dependent", step=steps.STAGE),1474 dict(part="nested-dependent", step=steps.PULL),1475 dict(part="nested-dependent", step=steps.BUILD),1476 dict(part="nested-dependent", step=steps.STAGE),1477 dict(part="dependent", step=steps.PRIME),1478 dict(part="nested-dependent", step=steps.PRIME),1479 ],1480 "expected_final": stage_order("main")1481 + [1482 dict(part="dependent", step=steps.PULL),1483 dict(part="main", step=steps.PRIME),1484 dict(part="dependent", step=steps.BUILD),1485 dict(part="dependent", step=steps.STAGE),1486 dict(part="nested-dependent", step=steps.PULL),1487 dict(part="nested-dependent", step=steps.BUILD),1488 dict(part="nested-dependent", step=steps.STAGE),1489 dict(part="dependent", step=steps.PRIME),1490 dict(part="nested-dependent", step=steps.PRIME),1491 ],1492 }1493 )1494 self.run_test()1495 def test_dependent_stage_dirty(self):1496 self.set_attributes(1497 {1498 "test_parts": [dict(part="dependent", step=steps.STAGE)],1499 "expected_initial": prime_order(),1500 "expected_test": [1501 dict(part="dependent", step=steps.STAGE),1502 dict(part="nested-dependent", step=steps.PULL),1503 dict(part="nested-dependent", step=steps.BUILD),1504 dict(part="nested-dependent", step=steps.STAGE),1505 dict(part="dependent", step=steps.PRIME),1506 dict(part="nested-dependent", step=steps.PRIME),1507 ],1508 "expected_final": stage_order("main")1509 + [1510 dict(part="dependent", step=steps.PULL),1511 dict(part="dependent", step=steps.BUILD),1512 dict(part="main", step=steps.PRIME),1513 dict(part="dependent", step=steps.STAGE),1514 dict(part="nested-dependent", step=steps.PULL),1515 dict(part="nested-dependent", step=steps.BUILD),1516 dict(part="nested-dependent", step=steps.STAGE),1517 dict(part="dependent", step=steps.PRIME),1518 dict(part="nested-dependent", step=steps.PRIME),1519 ],1520 }1521 )1522 self.run_test()1523 def test_dependent_prime_dirty(self):1524 self.set_attributes(1525 {1526 "test_parts": [dict(part="dependent", step=steps.PRIME)],1527 "expected_initial": prime_order(),1528 "expected_test": [1529 dict(part="dependent", step=steps.PRIME),1530 dict(part="nested-dependent", step=steps.PRIME),1531 ],1532 "expected_final": prime_order(),1533 }1534 )1535 self.run_test()1536 def test_nested_dependent_pull_dirty(self):1537 self.set_attributes(1538 {1539 "test_parts": [dict(part="nested-dependent", step=steps.PULL)],1540 "expected_initial": prime_order(),1541 "expected_test": [1542 dict(part="nested-dependent", step=steps.PULL),1543 dict(part="nested-dependent", step=steps.BUILD),1544 dict(part="nested-dependent", step=steps.STAGE),1545 dict(part="nested-dependent", step=steps.PRIME),1546 ],1547 "expected_final": prime_order("dependent")1548 + [1549 dict(part="nested-dependent", step=steps.PULL),1550 dict(part="nested-dependent", step=steps.BUILD),1551 dict(part="nested-dependent", step=steps.STAGE),1552 dict(part="nested-dependent", step=steps.PRIME),1553 ],1554 }1555 )1556 self.run_test()1557 def test_nested_dependendent_build_dirty(self):1558 self.set_attributes(1559 {1560 "test_parts": [dict(part="nested-dependent", step=steps.BUILD)],1561 "expected_initial": prime_order(),1562 "expected_test": [1563 dict(part="nested-dependent", step=steps.BUILD),1564 dict(part="nested-dependent", step=steps.STAGE),1565 dict(part="nested-dependent", step=steps.PRIME),1566 ],1567 "expected_final": pull_order("nested-dependent")1568 + [1569 dict(part="main", step=steps.PRIME),1570 dict(part="dependent", step=steps.PRIME),1571 dict(part="nested-dependent", step=steps.BUILD),1572 dict(part="nested-dependent", step=steps.STAGE),1573 dict(part="nested-dependent", step=steps.PRIME),1574 ],1575 }1576 )1577 self.run_test()1578 def test_nested_dependent_stage_dirty(self):1579 self.set_attributes(1580 {1581 "test_parts": [dict(part="nested-dependent", step=steps.STAGE)],1582 "expected_initial": prime_order(),1583 "expected_test": [1584 dict(part="nested-dependent", step=steps.STAGE),1585 dict(part="nested-dependent", step=steps.PRIME),1586 ],1587 "expected_final": build_order("nested-dependent")1588 + [1589 dict(part="main", step=steps.PRIME),1590 dict(part="dependent", step=steps.PRIME),1591 dict(part="nested-dependent", step=steps.STAGE),1592 dict(part="nested-dependent", step=steps.PRIME),1593 ],1594 }1595 )1596 self.run_test()1597 def test_nested_dependent_prime_dirty(self):1598 self.set_attributes(1599 {1600 "test_parts": [dict(part="nested-dependent", step=steps.PRIME)],1601 "expected_initial": prime_order(),1602 "expected_test": [dict(part="nested-dependent", step=steps.PRIME)],1603 "expected_final": prime_order("nested-dependent"),1604 }1605 )1606 self.run_test()1607class OutdatedTest(DirtyOutdatedTestBase):1608 test_type = "outdated"1609 def test_main_pull_outdated(self):1610 self.set_attributes(1611 {1612 "test_parts": [dict(part="main", step=steps.PULL)],1613 "expected_initial": prime_order(),1614 "expected_test": prime_order(),1615 "expected_final": prime_order(),1616 }1617 )1618 self.run_test()1619 def test_main_build_outdated(self):1620 self.set_attributes(1621 {1622 "test_parts": [dict(part="main", step=steps.BUILD)],1623 "expected_initial": prime_order(),1624 "expected_test": [1625 dict(part="main", step=steps.BUILD),1626 dict(part="main", step=steps.STAGE),1627 dict(part="dependent", step=steps.PULL),1628 dict(part="dependent", step=steps.BUILD),1629 dict(part="dependent", step=steps.STAGE),1630 dict(part="nested-dependent", step=steps.PULL),1631 dict(part="nested-dependent", step=steps.BUILD),1632 dict(part="nested-dependent", step=steps.STAGE),1633 dict(part="main", step=steps.PRIME),1634 dict(part="dependent", step=steps.PRIME),1635 dict(part="nested-dependent", step=steps.PRIME),1636 ],1637 "expected_final": prime_order(),1638 }1639 )1640 self.run_test()1641 def test_main_stage_outdated(self):1642 self.set_attributes(1643 {1644 "test_parts": [dict(part="main", step=steps.STAGE)],1645 "expected_initial": prime_order(),1646 "expected_test": [1647 dict(part="main", step=steps.STAGE),1648 dict(part="dependent", step=steps.PULL),1649 dict(part="dependent", step=steps.BUILD),1650 dict(part="dependent", step=steps.STAGE),1651 dict(part="nested-dependent", step=steps.PULL),1652 dict(part="nested-dependent", step=steps.BUILD),1653 dict(part="nested-dependent", step=steps.STAGE),1654 dict(part="main", step=steps.PRIME),1655 dict(part="dependent", step=steps.PRIME),1656 dict(part="nested-dependent", step=steps.PRIME),1657 ],1658 "expected_test_cleaned": [],1659 "expected_final": prime_order(),1660 }1661 )1662 self.run_test()1663 def test_main_prime_outdated(self):1664 self.set_attributes(1665 {1666 "test_parts": [dict(part="main", step=steps.PRIME)],1667 "expected_initial": prime_order(),1668 "expected_test": [1669 dict(part="main", step=steps.PRIME),1670 dict(part="dependent", step=steps.PRIME),1671 dict(part="nested-dependent", step=steps.PRIME),1672 ],1673 "expected_test_cleaned": [],1674 "expected_final": prime_order(),1675 }1676 )1677 self.run_test()1678 def dependent_pull_outdated(self):1679 self.set_attributes(1680 {1681 "test_parts": [dict(part="dependent", step=steps.PULL)],1682 "expected_initial": prime_order(),1683 "expected_test": [1684 dict(part="dependent", step=steps.PULL),1685 dict(part="dependent", step=steps.BUILD),1686 dict(part="dependent", step=steps.STAGE),1687 dict(part="nested-dependent", step=steps.PULL),1688 dict(part="nested-dependent", step=steps.BUILD),1689 dict(part="nested-dependent", step=steps.STAGE),1690 dict(part="dependent", step=steps.PRIME),1691 dict(part="nested-dependent", step=steps.PRIME),1692 ],1693 "expected_final": prime_order("main")1694 + [1695 dict(part="dependent", step=steps.PULL),1696 dict(part="dependent", step=steps.BUILD),1697 dict(part="dependent", step=steps.STAGE),1698 dict(part="nested-dependent", step=steps.PULL),1699 dict(part="nested-dependent", step=steps.BUILD),1700 dict(part="nested-dependent", step=steps.STAGE),1701 dict(part="dependent", step=steps.PRIME),1702 dict(part="nested-dependent", step=steps.PRIME),1703 ],1704 }1705 )1706 self.run_test()1707 def test_dependent_build_outdated(self):1708 self.set_attributes(1709 {1710 "test_parts": [dict(part="dependent", step=steps.BUILD)],1711 "expected_initial": prime_order(),1712 "expected_test": [1713 dict(part="dependent", step=steps.BUILD),1714 dict(part="dependent", step=steps.STAGE),1715 dict(part="nested-dependent", step=steps.PULL),1716 dict(part="nested-dependent", step=steps.BUILD),1717 dict(part="nested-dependent", step=steps.STAGE),1718 dict(part="dependent", step=steps.PRIME),1719 dict(part="nested-dependent", step=steps.PRIME),1720 ],1721 "expected_final": stage_order("main")1722 + [1723 dict(part="dependent", step=steps.PULL),1724 dict(part="main", step=steps.PRIME),1725 dict(part="dependent", step=steps.BUILD),1726 dict(part="dependent", step=steps.STAGE),1727 dict(part="nested-dependent", step=steps.PULL),1728 dict(part="nested-dependent", step=steps.BUILD),1729 dict(part="nested-dependent", step=steps.STAGE),1730 dict(part="dependent", step=steps.PRIME),1731 dict(part="nested-dependent", step=steps.PRIME),1732 ],1733 }1734 )1735 self.run_test()1736 def test_dependent_stage_outdated(self):1737 self.set_attributes(1738 {1739 "test_parts": [dict(part="dependent", step=steps.STAGE)],1740 "expected_initial": prime_order(),1741 "expected_test": [1742 dict(part="dependent", step=steps.STAGE),1743 dict(part="nested-dependent", step=steps.PULL),1744 dict(part="nested-dependent", step=steps.BUILD),1745 dict(part="nested-dependent", step=steps.STAGE),1746 dict(part="dependent", step=steps.PRIME),1747 dict(part="nested-dependent", step=steps.PRIME),1748 ],1749 "expected_final": stage_order("main")1750 + [1751 dict(part="dependent", step=steps.PULL),1752 dict(part="dependent", step=steps.BUILD),1753 dict(part="main", step=steps.PRIME),1754 dict(part="dependent", step=steps.STAGE),1755 dict(part="nested-dependent", step=steps.PULL),1756 dict(part="nested-dependent", step=steps.BUILD),1757 dict(part="nested-dependent", step=steps.STAGE),1758 dict(part="dependent", step=steps.PRIME),1759 dict(part="nested-dependent", step=steps.PRIME),1760 ],1761 }1762 )1763 self.run_test()1764 def test_dependent_prime_outdated(self):1765 self.set_attributes(1766 {1767 "test_parts": [dict(part="dependent", step=steps.PRIME)],1768 "expected_initial": prime_order(),1769 "expected_test": [1770 dict(part="dependent", step=steps.PRIME),1771 dict(part="nested-dependent", step=steps.PRIME),1772 ],1773 "expected_final": prime_order(),1774 }1775 )1776 self.run_test()1777 def test_nested_dependent_pull_outdated(self):1778 self.set_attributes(1779 {1780 "test_parts": [dict(part="nested-dependent", step=steps.PULL)],1781 "expected_initial": prime_order(),1782 "expected_test": [1783 dict(part="nested-dependent", step=steps.PULL),1784 dict(part="nested-dependent", step=steps.BUILD),1785 dict(part="nested-dependent", step=steps.STAGE),1786 dict(part="nested-dependent", step=steps.PRIME),1787 ],1788 "expected_final": prime_order("dependent")1789 + [1790 dict(part="nested-dependent", step=steps.PULL),1791 dict(part="nested-dependent", step=steps.BUILD),1792 dict(part="nested-dependent", step=steps.STAGE),1793 dict(part="nested-dependent", step=steps.PRIME),1794 ],1795 }1796 )1797 self.run_test()1798 def test_nested_dependendent_build_outdated(self):1799 self.set_attributes(1800 {1801 "test_parts": [dict(part="nested-dependent", step=steps.BUILD)],1802 "expected_initial": prime_order(),1803 "expected_test": [1804 dict(part="nested-dependent", step=steps.BUILD),1805 dict(part="nested-dependent", step=steps.STAGE),1806 dict(part="nested-dependent", step=steps.PRIME),1807 ],1808 "expected_final": pull_order("nested-dependent")1809 + [1810 dict(part="main", step=steps.PRIME),1811 dict(part="dependent", step=steps.PRIME),1812 dict(part="nested-dependent", step=steps.BUILD),1813 dict(part="nested-dependent", step=steps.STAGE),1814 dict(part="nested-dependent", step=steps.PRIME),1815 ],1816 }1817 )1818 self.run_test()1819 def test_nested_dependent_stage_outdated(self):1820 self.set_attributes(1821 {1822 "test_parts": [dict(part="nested-dependent", step=steps.STAGE)],1823 "expected_initial": prime_order(),1824 "expected_test": [1825 dict(part="nested-dependent", step=steps.STAGE),1826 dict(part="nested-dependent", step=steps.PRIME),1827 ],1828 "expected_final": build_order("nested-dependent")1829 + [1830 dict(part="main", step=steps.PRIME),1831 dict(part="dependent", step=steps.PRIME),1832 dict(part="nested-dependent", step=steps.STAGE),1833 dict(part="nested-dependent", step=steps.PRIME),1834 ],1835 }1836 )1837 self.run_test()1838 def test_nested_dependent_prime_outdated(self):1839 self.set_attributes(1840 {1841 "test_parts": [dict(part="nested-dependent", step=steps.PRIME)],1842 "expected_initial": prime_order(),1843 "expected_test": [dict(part="nested-dependent", step=steps.PRIME)],1844 "expected_final": prime_order("nested-dependent"),1845 }1846 )...
decoder_for_data_package.py
Source:decoder_for_data_package.py
...20 ('aggregation', False, 'unicode', 'child::cim:aggregation'),21 ('frequency', False, 'unicode', 'child::cim:frequency/@value'),22 ('topic', False, decode_data_topic, 'child::cim:topic'),23 ]24 return set_attributes(typeset.data.DataContent(), xml, nsmap, decodings)25def decode_data_distribution(xml, nsmap):26 """Decodes an instance of the following type: data distribution.27 :param lxml.etree xml: XML from which type is to be decoded.28 :param dict nsmap: XML namespace mappings.29 :returns: A decoded type instance.30 :rtype: cim.v1.typeset.data.DataDistribution31 """32 decodings = [33 ('access', False, 'unicode', '@distributionAccess'),34 ('format', False, 'unicode', 'child::cim:distributionFormat/@value'),35 ('responsible_party', False, decode_responsible_party, 'child::cim:responsibleParty'),36 ]37 return set_attributes(typeset.data.DataDistribution(), xml, nsmap, decodings)38def decode_data_extent(xml, nsmap):39 """Decodes an instance of the following type: data extent.40 :param lxml.etree xml: XML from which type is to be decoded.41 :param dict nsmap: XML namespace mappings.42 :returns: A decoded type instance.43 :rtype: cim.v1.typeset.data.DataExtent44 """45 decodings = [46 ('geographical', False, decode_data_extent_geographical, 'child::gmd:geographicElement'),47 ('temporal', False, decode_data_extent_temporal, 'child::gmd:temporalElement/gmd:EX_TemporalExtent/gmd:extent/gml:TimePeriod'),48 ]49 return set_attributes(typeset.data.DataExtent(), xml, nsmap, decodings)50def decode_data_extent_geographical(xml, nsmap):51 """Decodes an instance of the following type: data extent geographical.52 :param lxml.etree xml: XML from which type is to be decoded.53 :param dict nsmap: XML namespace mappings.54 :returns: A decoded type instance.55 :rtype: cim.v1.typeset.data.DataExtentGeographical56 """57 decodings = [58 ('east', False, 'float', 'child::gmd:EX_GeographicBoundingBox/gmd:eastBoundLongitude/gco:Decimal'),59 ('north', False, 'float', 'child::gmd:EX_GeographicBoundingBox/gmd:northBoundLatitude/gco:Decimal'),60 ('south', False, 'float', 'child::gmd:EX_GeographicBoundingBox/gmd:southBoundLatitude/gco:Decimal'),61 ('west', False, 'float', 'child::gmd:EX_GeographicBoundingBox/gmd:westBoundLongitude/gco:Decimal'),62 ]63 return set_attributes(typeset.data.DataExtentGeographical(), xml, nsmap, decodings)64def decode_data_extent_temporal(xml, nsmap):65 """Decodes an instance of the following type: data extent temporal.66 :param lxml.etree xml: XML from which type is to be decoded.67 :param dict nsmap: XML namespace mappings.68 :returns: A decoded type instance.69 :rtype: cim.v1.typeset.data.DataExtentTemporal70 """71 decodings = [72 ('begin', False, 'datetime.date', 'child::gml:beginPosition'),73 ('end', False, 'datetime.date', 'child::gml:endPosition'),74 ('time_interval', False, decode_data_extent_time_interval, 'child::gml:timeInterval'),75 ]76 return set_attributes(typeset.data.DataExtentTemporal(), xml, nsmap, decodings)77def decode_data_extent_time_interval(xml, nsmap):78 """Decodes an instance of the following type: data extent time interval.79 :param lxml.etree xml: XML from which type is to be decoded.80 :param dict nsmap: XML namespace mappings.81 :returns: A decoded type instance.82 :rtype: cim.v1.typeset.data.DataExtentTimeInterval83 """84 decodings = [85 ('factor', False, 'int', '@factor'),86 ('radix', False, 'int', '@radix'),87 ('unit', False, 'unicode', '@unit'),88 ]89 return set_attributes(typeset.data.DataExtentTimeInterval(), xml, nsmap, decodings)90def decode_data_hierarchy_level(xml, nsmap):91 """Decodes an instance of the following type: data hierarchy level.92 :param lxml.etree xml: XML from which type is to be decoded.93 :param dict nsmap: XML namespace mappings.94 :returns: A decoded type instance.95 :rtype: cim.v1.typeset.data.DataHierarchyLevel96 """97 decodings = [98 ('is_open', False, 'bool', 'child::cim:hierarchyLevelName/@open'),99 ('name', False, 'unicode', 'child::cim:hierarchyLevelName/@value'),100 ('value', False, 'unicode', 'child::cim:hierarchyLevelValue'),101 ]102 return set_attributes(typeset.data.DataHierarchyLevel(), xml, nsmap, decodings)103def decode_data_object(xml, nsmap):104 """Decodes an instance of the following type: data object.105 :param lxml.etree xml: XML from which type is to be decoded.106 :param dict nsmap: XML namespace mappings.107 :returns: A decoded type instance.108 :rtype: cim.v1.typeset.data.DataObject109 """110 decodings = [111 ('acronym', False, 'unicode', 'child::cim:acronym'),112 ('citations', True, decode_citation, '//cim:citation[not(cim:citation)]'),113 ('content', True, decode_data_content, 'child::cim:content'),114 ('data_status', False, 'unicode', 'self::cim:dataObject/@dataStatus'),115 ('description', False, 'unicode', 'child::cim:description'),116 ('distribution', False, decode_data_distribution, 'child::cim:distribution'),117 ('extent', False, decode_data_extent, 'child::cim:extent'),118 ('hierarchy_level', False, decode_data_hierarchy_level, 'self::cim:dataObject'),119 ('keyword', False, 'unicode', 'child::cim:keyword'),120 ('meta', False, decode_doc_meta_info, 'self::cim:dataObject'),121 ('properties', True, decode_data_property, 'child::cim:dataProperty/cim:dataProperty'),122 ('purpose', False, 'unicode', 'self::cim:dataObject/@purpose'),123 ('purpose', False, 'unicode', 'self::cim:dataObject/@purpose'),124 ('storage', True, decode_data_storage_ip, 'child::cim:storage/cim:ipStorage'),125 ]126 return set_attributes(typeset.data.DataObject(), xml, nsmap, decodings)127def decode_data_property(xml, nsmap):128 """Decodes an instance of the following type: data property.129 :param lxml.etree xml: XML from which type is to be decoded.130 :param dict nsmap: XML namespace mappings.131 :returns: A decoded type instance.132 :rtype: cim.v1.typeset.data.DataProperty133 """134 decodings = [135 ('description', False, 'unicode', 'child::cim:description'),136 ('name', False, 'unicode', 'child::cim:name'),137 ('value', False, 'unicode', 'child::cim:value'),138 ]139 return set_attributes(typeset.data.DataProperty(), xml, nsmap, decodings)140def decode_data_restriction(xml, nsmap):141 """Decodes an instance of the following type: data restriction.142 :param lxml.etree xml: XML from which type is to be decoded.143 :param dict nsmap: XML namespace mappings.144 :returns: A decoded type instance.145 :rtype: cim.v1.typeset.data.DataRestriction146 """147 decodings = [148 ]149 return set_attributes(typeset.data.DataRestriction(), xml, nsmap, decodings)150def decode_data_storage(xml, nsmap):151 """Decodes an instance of the following type: data storage.152 :param lxml.etree xml: XML from which type is to be decoded.153 :param dict nsmap: XML namespace mappings.154 :returns: A decoded type instance.155 :rtype: cim.v1.typeset.data.DataStorage156 """157 decodings = [158 ]159 return set_attributes(typeset.data.DataStorage(), xml, nsmap, decodings)160def decode_data_storage_db(xml, nsmap):161 """Decodes an instance of the following type: data storage db.162 :param lxml.etree xml: XML from which type is to be decoded.163 :param dict nsmap: XML namespace mappings.164 :returns: A decoded type instance.165 :rtype: cim.v1.typeset.data.DataStorageDb166 """167 decodings = [168 ]169 return set_attributes(typeset.data.DataStorageDb(), xml, nsmap, decodings)170def decode_data_storage_file(xml, nsmap):171 """Decodes an instance of the following type: data storage file.172 :param lxml.etree xml: XML from which type is to be decoded.173 :param dict nsmap: XML namespace mappings.174 :returns: A decoded type instance.175 :rtype: cim.v1.typeset.data.DataStorageFile176 """177 decodings = [178 ]179 return set_attributes(typeset.data.DataStorageFile(), xml, nsmap, decodings)180def decode_data_storage_ip(xml, nsmap):181 """Decodes an instance of the following type: data storage ip.182 :param lxml.etree xml: XML from which type is to be decoded.183 :param dict nsmap: XML namespace mappings.184 :returns: A decoded type instance.185 :rtype: cim.v1.typeset.data.DataStorageIp186 """187 decodings = [188 ('file_name', False, 'unicode', 'child::cim:fileName'),189 ('format', False, 'unicode', 'child::cim:dataFormat/@value'),190 ]191 return set_attributes(typeset.data.DataStorageIp(), xml, nsmap, decodings)192def decode_data_topic(xml, nsmap):193 """Decodes an instance of the following type: data topic.194 :param lxml.etree xml: XML from which type is to be decoded.195 :param dict nsmap: XML namespace mappings.196 :returns: A decoded type instance.197 :rtype: cim.v1.typeset.data.DataTopic198 """199 decodings = [200 ('description', False, 'unicode', 'child::cim:description'),201 ('name', False, 'unicode', 'child::cim:name'),202 ('unit', False, 'unicode', 'child::cim:unit/@value'),203 ]...
tu_vi.py
Source:tu_vi.py
1import requests2class TuVi():3 def __init__(self):4 pass5 def con_giap(self, Cgiap=''):6 url = 'https://api.kma-chatbot.com/tuvi.php?tuoi={}'.format(Cgiap.strip())7 loi_phan = '' # Lá»i phán8 try:9 r = requests.get(url)10 data_json = r.json()11 set_attributes = data_json.get('set_attributes')12 if set_attributes:13 loi_phan = '-----{}-----\n- {}\n- {}\n- {}\n- {}\n'.format(14 set_attributes.get('tvcongiap'),15 set_attributes.get('congviec'),16 set_attributes.get('tinhcam'),17 set_attributes.get('taivan'),18 set_attributes.get('cantrong')19 )20 except:21 loi_phan = 'Có thá» con giáp bạn nháºp bá» sai :('22 return loi_phan23 def cung_hoang_dao(self, cung_hd=''):24 # Cái nà y mình cho API rá»i các bạn tá»± viết nha =)) LÆ°á»i!...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!