Best Python code snippet using avocado_python
test_basic.py
Source:test_basic.py  
1import glob2import json3import os4import re5import tempfile6import time7import unittest8import xml.dom.minidom9import zipfile10from avocado.core import exit_codes11from avocado.utils import path as utils_path12from avocado.utils import process, script13from selftests.utils import (14    AVOCADO,15    BASEDIR,16    TestCaseTmpDir,17    python_module_available,18    skipOnLevelsInferiorThan,19    skipUnlessPathExists,20    temp_dir_prefix,21)22try:23    import xmlschema24    SCHEMA_CAPABLE = True25except ImportError:26    SCHEMA_CAPABLE = False27UNSUPPORTED_STATUS_TEST_CONTENTS = """28from avocado import Test29class FakeStatusTest(Test):30    def run_avocado(self):31        super(FakeStatusTest, self).run_avocado()32        # Please do NOT ever use this, it's for unittesting only.33        self._Test__status = 'not supported'34    def test(self):35        pass36"""37INVALID_PYTHON_TEST = """38from avocado import Test39class MyTest(Test):40    non_existing_variable_causing_crash41    def test_my_name(self):42        pass43"""44VALID_PYTHON_TEST_WITH_TAGS = '''45from avocado import Test46class MyTest(Test):47    def test(self):48         """49         :avocado: tags=BIG_TAG_NAME50         """51         pass52'''53DIE_WITHOUT_REPORTING_STATUS = """54from avocado import Test55import os56import signal57class MyTest(Test):58    def test(self):59         os.kill(os.getpid(), signal.SIGKILL)60"""61RAISE_CUSTOM_PATH_EXCEPTION_CONTENT = """import os62import sys63from avocado import Test64class SharedLibTest(Test):65    def test(self):66        sys.path.append(os.path.join(os.path.dirname(__file__), "shared_lib"))67        from mylib import CancelExc68        raise CancelExc("This should not crash on unpickling in runner")69"""70TEST_OTHER_LOGGERS_CONTENT = """71import logging72from avocado import Test73class My(Test):74    def test(self):75        logging.getLogger("some.other.logger").info("SHOULD NOT BE ON debug.log")76"""77def probe_binary(binary):78    try:79        return utils_path.find_command(binary)80    except utils_path.CmdNotFoundError:81        return None82TRUE_CMD = probe_binary("true")83CC_BINARY = probe_binary("cc")84# On macOS, the default GNU core-utils installation (brew)85# installs the gnu utility versions with a g prefix. It still has the86# BSD versions of the core utilities installed on their expected paths87# but their behavior and flags are in most cases different.88GNU_ECHO_BINARY = probe_binary("echo")89if GNU_ECHO_BINARY is not None:90    if probe_binary("man") is not None:91        echo_cmd = f"man {os.path.basename(GNU_ECHO_BINARY)}"92        echo_manpage = process.run(echo_cmd, env={"LANG": "C"}, encoding="ascii").stdout93        if b"-e" not in echo_manpage:94            GNU_ECHO_BINARY = probe_binary("gecho")95READ_BINARY = probe_binary("read")96SLEEP_BINARY = probe_binary("sleep")97class RunnerOperationTest(TestCaseTmpDir):98    def test_show_version(self):99        result = process.run(f"{AVOCADO} -v", ignore_status=True)100        self.assertEqual(result.exit_status, 0)101        self.assertTrue(102            re.match(r"^Avocado \d+\.\d+$", result.stdout_text),103            (104                f"Version string does not match "105                f"'Avocado \\d\\.\\d:'\n"106                f"{result.stdout_text}"107            ),108        )109    def test_alternate_config_datadir(self):110        """111        Uses the "--config" flag to check custom configuration is applied112        Even on the more complex data_dir module, which adds extra checks113        to what is set on the plain settings module.114        """115        base_dir = os.path.join(self.tmpdir.name, "datadir_base")116        os.mkdir(base_dir)117        mapping = {118            "base_dir": base_dir,119            "test_dir": os.path.join(base_dir, "test"),120            "data_dir": os.path.join(base_dir, "data"),121            "logs_dir": os.path.join(base_dir, "logs"),122        }123        config = "[datadir.paths]\n"124        for key, value in mapping.items():125            if not os.path.isdir(value):126                os.mkdir(value)127            config += f"{key} = {value}\n"128        fd, config_file = tempfile.mkstemp(dir=self.tmpdir.name)129        os.write(fd, config.encode())130        os.close(fd)131        cmd = f"{AVOCADO} --config {config_file} config --datadir"132        result = process.run(cmd)133        expected_rc = exit_codes.AVOCADO_ALL_OK134        self.assertEqual(135            result.exit_status,136            expected_rc,137            (f"Avocado did not return rc {expected_rc}:" f"\n{result}"),138        )139        self.assertIn("   base    " + mapping["base_dir"], result.stdout_text)140        self.assertIn("   data    " + mapping["data_dir"], result.stdout_text)141        self.assertIn("   logs    " + mapping["logs_dir"], result.stdout_text)142    def test_runner_phases(self):143        cmd_line = (144            f"{AVOCADO} run --disable-sysinfo "145            f"--job-results-dir {self.tmpdir.name} "146            f"examples/tests/phases.py"147        )148        result = process.run(cmd_line)149        expected_rc = exit_codes.AVOCADO_ALL_OK150        self.assertEqual(151            result.exit_status,152            expected_rc,153            (f"Avocado did not return rc {expected_rc}:" f"\n{result}"),154        )155    def test_runner_all_ok(self):156        cmd_line = (157            f"{AVOCADO} run --disable-sysinfo "158            f"--job-results-dir {self.tmpdir.name} "159            f"examples/tests/passtest.py examples/tests/passtest.py"160        )161        process.run(cmd_line)162        # Also check whether jobdata contains correct parameter paths163        variants = open(164            os.path.join(self.tmpdir.name, "latest", "jobdata", "variants-1.json"),165            encoding="utf-8",166        ).read()167        expected = '[{"paths": ["/run/*"], "variant_id": null, "variant": [["/", []]]}]'168        self.assertEqual(variants, expected)169    def test_runner_failfast_fail(self):170        cmd_line = (171            f"{AVOCADO} run --disable-sysinfo "172            f"--job-results-dir {self.tmpdir.name} "173            f"examples/tests/passtest.py examples/tests/failtest.py "174            f"examples/tests/passtest.py --failfast "175            f"--nrunner-max-parallel-tasks=1"176        )177        result = process.run(cmd_line, ignore_status=True)178        self.assertIn(b"Interrupting job (failfast).", result.stdout)179        self.assertIn(b"PASS 1 | ERROR 0 | FAIL 1 | SKIP 1", result.stdout)180        expected_rc = exit_codes.AVOCADO_TESTS_FAIL | exit_codes.AVOCADO_JOB_INTERRUPTED181        self.assertEqual(182            result.exit_status,183            expected_rc,184            f"Avocado did not return rc {expected_rc}:\n{result}",185        )186    def test_runner_failfast_error(self):187        cmd_line = (188            f"{AVOCADO} run --disable-sysinfo "189            f"--job-results-dir {self.tmpdir.name} "190            f"examples/tests/passtest.py examples/tests/errortest.py "191            f"examples/tests/passtest.py --failfast "192            f"--nrunner-max-parallel-tasks=1"193        )194        result = process.run(cmd_line, ignore_status=True)195        self.assertIn(b"Interrupting job (failfast).", result.stdout)196        self.assertIn(b"PASS 1 | ERROR 1 | FAIL 0 | SKIP 1", result.stdout)197        expected_rc = exit_codes.AVOCADO_TESTS_FAIL | exit_codes.AVOCADO_JOB_INTERRUPTED198        self.assertEqual(199            result.exit_status,200            expected_rc,201            f"Avocado did not return rc {expected_rc}:\n{result}",202        )203    def test_runner_ignore_missing_references_one_missing(self):204        cmd_line = (205            f"{AVOCADO} run --disable-sysinfo "206            f"--job-results-dir {self.tmpdir.name} "207            f"examples/tests/passtest.py badtest.py "208            f"--ignore-missing-references"209        )210        result = process.run(cmd_line, ignore_status=True)211        self.assertIn(b"PASS 1 | ERROR 0 | FAIL 0 | SKIP 0", result.stdout)212        expected_rc = exit_codes.AVOCADO_ALL_OK213        self.assertEqual(214            result.exit_status,215            expected_rc,216            f"Avocado did not return rc {expected_rc}:\n{result}",217        )218    def test_runner_ignore_missing_references_all_missing(self):219        cmd_line = (220            f"{AVOCADO} run --disable-sysinfo "221            f"--job-results-dir {self.tmpdir.name} "222            f"badtest.py badtest2.py --ignore-missing-references"223        )224        result = process.run(cmd_line, ignore_status=True)225        self.assertIn(b"Suite is empty. There is no tests to run.", result.stderr)226        expected_rc = exit_codes.AVOCADO_FAIL227        self.assertEqual(228            result.exit_status,229            expected_rc,230            f"Avocado did not return rc {expected_rc}:\n{result}",231        )232    def test_runner_test_with_local_imports(self):233        prefix = temp_dir_prefix(self)234        with tempfile.TemporaryDirectory(prefix=prefix) as libdir:235            with script.Script(236                os.path.join(libdir, "mylib.py"),237                "def hello():\n    return 'Hello world'",238            ):239                with script.Script(240                    os.path.join(libdir, "test_local_imports.py"),241                    (242                        "from avocado import Test\n"243                        "from mylib import hello\n"244                        "class LocalImportTest(Test):\n"245                        "    def test(self):\n"246                        "        self.log.info(hello())\n"247                    ),248                ) as mytest:249                    cmd_line = (250                        f"{AVOCADO} run --disable-sysinfo "251                        f"--job-results-dir {self.tmpdir.name} "252                        f"{mytest}"253                    )254                    process.run(cmd_line)255    def test_unsupported_status(self):256        with script.TemporaryScript(257            "fake_status.py",258            UNSUPPORTED_STATUS_TEST_CONTENTS,259            "avocado_unsupported_status",260        ) as tst:261            res = process.run(262                (263                    f"{AVOCADO} run --disable-sysinfo "264                    f"--job-results-dir {self.tmpdir.name} {tst} "265                    f"--json -"266                ),267                ignore_status=True,268            )269            self.assertEqual(res.exit_status, exit_codes.AVOCADO_TESTS_FAIL)270            results = json.loads(res.stdout_text)271            self.assertEqual(272                results["tests"][0]["status"],273                "ERROR",274                (f"{results['tests'][0]['status']} != " f"{'ERROR'}\n{res}"),275            )276            self.assertIn(277                "Runner error occurred: Test reports unsupported",278                results["tests"][0]["fail_reason"],279            )280    def test_runner_tests_fail(self):281        cmd_line = (282            f"{AVOCADO} run --disable-sysinfo --job-results-dir "283            f"{self.tmpdir.name} examples/tests/passtest.py "284            f"examples/tests/failtest.py examples/tests/passtest.py"285        )286        result = process.run(cmd_line, ignore_status=True)287        expected_rc = exit_codes.AVOCADO_TESTS_FAIL288        self.assertEqual(289            result.exit_status,290            expected_rc,291            f"Avocado did not return rc {expected_rc}:\n{result}",292        )293    def test_runner_test_fail_with_warning(self):294        cmd_line = (295            f"{AVOCADO} run --disable-sysinfo --job-results-dir "296            f"{self.tmpdir.name} examples/tests/failtest_with_warning.py"297        )298        result = process.run(cmd_line, ignore_status=True)299        expected_rc = exit_codes.AVOCADO_TESTS_FAIL300        self.assertEqual(301            result.exit_status,302            expected_rc,303            f"Avocado did not return rc {expected_rc}:\n{result}",304        )305    def test_runner_nonexistent_test(self):306        cmd_line = (307            f"{AVOCADO} run --disable-sysinfo --job-results-dir "308            f"{self.tmpdir.name} bogustest"309        )310        result = process.run(cmd_line, ignore_status=True)311        expected_rc = exit_codes.AVOCADO_JOB_FAIL312        unexpected_rc = exit_codes.AVOCADO_FAIL313        self.assertNotEqual(314            result.exit_status,315            unexpected_rc,316            f"Avocado crashed (rc {unexpected_rc}):\n{result}",317        )318        self.assertEqual(319            result.exit_status,320            expected_rc,321            f"Avocado did not return rc {expected_rc}:\n{result}",322        )323    def test_runner_doublefail(self):324        cmd_line = (325            f"{AVOCADO} run --disable-sysinfo --job-results-dir "326            f"{self.tmpdir.name} --xunit - "327            f"examples/tests/doublefail.py"328        )329        result = process.run(cmd_line, ignore_status=True)330        expected_rc = exit_codes.AVOCADO_TESTS_FAIL331        unexpected_rc = exit_codes.AVOCADO_FAIL332        self.assertNotEqual(333            result.exit_status,334            unexpected_rc,335            f"Avocado crashed (rc {unexpected_rc}):\n{result}",336        )337        self.assertEqual(338            result.exit_status,339            expected_rc,340            f"Avocado did not return rc {expected_rc}:\n{result}",341        )342        self.assertIn(343            b"TestError: Failing during tearDown. Yay!",344            result.stdout,345            "Cleanup exception not printed to log output",346        )347        self.assertIn(348            b"TestFail: This test is supposed to fail",349            result.stdout,350            (f"Test did not fail with action exception:" f"\n{result.stdout}"),351        )352    def test_uncaught_exception(self):353        cmd_line = (354            f"{AVOCADO} run --disable-sysinfo --job-results-dir "355            f"{self.tmpdir.name} --json - "356            f"examples/tests/uncaught_exception.py"357        )358        result = process.run(cmd_line, ignore_status=True)359        expected_rc = exit_codes.AVOCADO_TESTS_FAIL360        self.assertEqual(361            result.exit_status,362            expected_rc,363            f"Avocado did not return rc {expected_rc}:\n{result}",364        )365        self.assertIn(b'"status": "ERROR"', result.stdout)366    def test_fail_on_exception(self):367        cmd_line = (368            f"{AVOCADO}  run --disable-sysinfo --job-results-dir "369            f"{self.tmpdir.name} --json - "370            f"examples/tests/fail_on_exception.py"371        )372        result = process.run(cmd_line, ignore_status=True)373        expected_rc = exit_codes.AVOCADO_TESTS_FAIL374        self.assertEqual(375            result.exit_status,376            expected_rc,377            f"Avocado did not return rc {expected_rc}:\n{result}",378        )379        self.assertIn(b'"status": "FAIL"', result.stdout)380    def test_cancel_on_exception(self):381        cmd_line = (382            f"{AVOCADO} run --disable-sysinfo --job-results-dir "383            f"{self.tmpdir.name} --json - "384            f"examples/tests/cancel_on_exception.py"385        )386        result = process.run(cmd_line, ignore_status=True)387        expected_rc = exit_codes.AVOCADO_ALL_OK388        self.assertEqual(389            result.exit_status,390            expected_rc,391            f"Avocado did not return rc {expected_rc}:\n{result}",392        )393        result = json.loads(result.stdout_text)394        for test in result["tests"]:395            self.assertEqual(test["status"], "CANCEL")396    def test_assert_raises(self):397        cmd_line = (398            f"{AVOCADO} run --disable-sysinfo --job-results-dir "399            f"{self.tmpdir.name} -- examples/tests/assert.py"400        )401        result = process.run(cmd_line, ignore_status=True)402        expected_rc = exit_codes.AVOCADO_TESTS_FAIL403        self.assertEqual(404            result.exit_status,405            expected_rc,406            f"Avocado did not return rc {expected_rc}:\n{result}",407        )408        self.assertIn(b"Assert.test_assert_raises:  PASS", result.stdout)409        self.assertIn(b"Assert.test_fails_to_raise:  FAIL", result.stdout)410        self.assertIn(b"PASS 1 | ERROR 0 | FAIL 1 ", result.stdout)411    def test_exception_not_in_path(self):412        os.mkdir(os.path.join(self.tmpdir.name, "shared_lib"))413        mylib = script.Script(414            os.path.join(self.tmpdir.name, "shared_lib", "mylib.py"),415            "from avocado import TestCancel\n\n"416            "class CancelExc(TestCancel):\n"417            "    pass",418        )419        mylib.save()420        mytest = script.Script(421            os.path.join(self.tmpdir.name, "mytest.py"),422            RAISE_CUSTOM_PATH_EXCEPTION_CONTENT,423        )424        mytest.save()425        result = process.run(426            f"{AVOCADO} --show test run --disable-sysinfo "427            f"--job-results-dir {self.tmpdir.name} {mytest}"428        )429        self.assertIn(430            b"'fail_reason': 'This should not crash on " b"unpickling in runner'",431            result.stdout,432        )433    def test_runner_timeout(self):434        cmd_line = (435            f"{AVOCADO} run --disable-sysinfo --job-results-dir "436            f"{self.tmpdir.name} examples/tests/timeouttest.py"437        )438        result = process.run(cmd_line, ignore_status=True)439        json_path = os.path.join(self.tmpdir.name, "latest", "results.json")440        with open(json_path, encoding="utf-8") as json_file:441            result_json = json.load(json_file)442        output = result.stdout443        expected_rc = exit_codes.AVOCADO_JOB_INTERRUPTED444        unexpected_rc = exit_codes.AVOCADO_FAIL445        self.assertNotEqual(446            result.exit_status,447            unexpected_rc,448            f"Avocado crashed (rc {unexpected_rc}):\n{result}",449        )450        self.assertEqual(451            result.exit_status,452            expected_rc,453            f"Avocado did not return rc {expected_rc}:\n{result}",454        )455        self.assertIn("timeout", result_json["tests"][0]["fail_reason"])456        # Ensure no test aborted error messages show up457        self.assertNotIn(b"TestAbortError: Test aborted unexpectedly", output)458    def test_silent_output(self):459        cmd_line = (460            f"{AVOCADO} --show=none run --disable-sysinfo "461            f"--job-results-dir {self.tmpdir.name} "462            f"examples/tests/passtest.py"463        )464        result = process.run(cmd_line, ignore_status=True)465        self.assertEqual(result.exit_status, exit_codes.AVOCADO_ALL_OK)466        self.assertEqual(result.stdout, b"")467    def test_show_user_stream(self):468        cmd_line = (469            f"{AVOCADO} --show=app,avocado.test.progress run "470            f"--disable-sysinfo --job-results-dir {self.tmpdir.name} "471            f"examples/tests/logging_streams.py"472        )473        result = process.run(cmd_line, ignore_status=True)474        self.assertEqual(result.exit_status, exit_codes.AVOCADO_ALL_OK)475        self.assertIn(476            b"Plant.test_plant_organic: preparing soil on row 0", result.stdout477        )478    def test_empty_args_list(self):479        cmd_line = AVOCADO480        result = process.run(cmd_line, ignore_status=True)481        self.assertEqual(result.exit_status, exit_codes.AVOCADO_FAIL)482        self.assertIn(483            b"avocado: error: the following arguments are required", result.stderr484        )485    def test_empty_test_list(self):486        cmd_line = (487            f"{AVOCADO} run --disable-sysinfo --job-results-dir " f"{self.tmpdir.name}"488        )489        result = process.run(cmd_line, ignore_status=True)490        self.assertEqual(result.exit_status, exit_codes.AVOCADO_JOB_FAIL)491        self.assertEqual(492            result.stderr,493            (494                b"Test Suite could not be created. No test references"495                b" provided nor any other arguments resolved into "496                b"tests\n"497            ),498        )499    def test_not_found(self):500        cmd_line = (501            f"{AVOCADO} run --disable-sysinfo --job-results-dir "502            f"{self.tmpdir.name} sbrubles"503        )504        result = process.run(cmd_line, ignore_status=True)505        self.assertEqual(result.exit_status, exit_codes.AVOCADO_JOB_FAIL)506        self.assertEqual(result.stdout, b"")507        self.assertEqual(result.stderr, b"Could not resolve references: sbrubles\n")508    def test_invalid_unique_id(self):509        cmd_line = (510            f"{AVOCADO} run --disable-sysinfo "511            f"--job-results-dir {self.tmpdir.name} "512            f"--force-job-id foobar examples/tests/passtest.py"513        )514        result = process.run(cmd_line, ignore_status=True)515        self.assertNotEqual(result.exit_status, exit_codes.AVOCADO_ALL_OK)516        self.assertIn(b"needs to be a 40 digit hex", result.stderr)517        self.assertNotIn(b"needs to be a 40 digit hex", result.stdout)518    def test_valid_unique_id(self):519        cmd_line = (520            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "521            f"--disable-sysinfo "522            f"--force-job-id 975de258ac05ce5e490648dec4753657b7ccc7d1 "523            f"examples/tests/passtest.py"524        )525        result = process.run(cmd_line, ignore_status=True)526        self.assertEqual(result.exit_status, exit_codes.AVOCADO_ALL_OK)527        self.assertNotIn(b"needs to be a 40 digit hex", result.stderr)528        self.assertIn(b"PASS", result.stdout)529    def test_automatic_unique_id(self):530        cmd_line = (531            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "532            f"--disable-sysinfo examples/tests/passtest.py --json -"533        )534        result = process.run(cmd_line, ignore_status=True)535        self.assertEqual(result.exit_status, exit_codes.AVOCADO_ALL_OK)536        r = json.loads(result.stdout_text)537        int(r["job_id"], 16)  # it's an hex number538        self.assertEqual(len(r["job_id"]), 40)539    @skipOnLevelsInferiorThan(2)540    def test_early_latest_result(self):541        """542        Tests that the `latest` link to the latest job results is created early543        :avocado: tags=parallel:1544        """545        cmd_line = (546            f"{AVOCADO} run --disable-sysinfo "547            f"--job-results-dir {self.tmpdir.name} "548            f"examples/tests/passtest.py"549        )550        avocado_process = process.SubProcess(cmd_line)551        try:552            avocado_process.start()553            link = os.path.join(self.tmpdir.name, "latest")554            for _ in range(0, 50):555                time.sleep(0.1)556                if os.path.exists(link) and os.path.islink(link):557                    avocado_process.wait()558                    break559            self.assertTrue(os.path.exists(link))560            self.assertTrue(os.path.islink(link))561        finally:562            avocado_process.wait()563    def test_invalid_python(self):564        test = script.make_script(565            os.path.join(self.tmpdir.name, "test.py"), INVALID_PYTHON_TEST566        )567        cmd_line = (568            f"{AVOCADO} run --disable-sysinfo "569            f"--job-results-dir {self.tmpdir.name} {test}"570        )571        result = process.run(cmd_line, ignore_status=True)572        expected_rc = exit_codes.AVOCADO_TESTS_FAIL573        self.assertEqual(574            result.exit_status,575            expected_rc,576            f"Avocado did not return rc {expected_rc}:\n{result}",577        )578        self.assertIn(f"{test}:MyTest.test_my_name:  ERROR", result.stdout_text)579    @unittest.skipIf(not READ_BINARY, "read binary not available.")580    @skipOnLevelsInferiorThan(1)581    def test_read(self):582        """583        :avocado: tags=parallel:1584        """585        cmd = (586            f"{AVOCADO} run --disable-sysinfo "587            f"--job-results-dir {self.tmpdir.name} "588            f"{READ_BINARY}"589        )590        result = process.run(cmd, timeout=10, ignore_status=True)591        self.assertLess(592            result.duration, 8, (f"Duration longer than expected." f"\n{result}")593        )594        self.assertEqual(595            result.exit_status, 1, (f"Expected exit status is 1" f"\n{result}")596        )597    def test_runner_test_parameters(self):598        cmd_line = (599            f"{AVOCADO} run --disable-sysinfo --job-results-dir "600            f'{self.tmpdir.name} -p "sleep_length=0.01" -- '601            f"examples/tests/sleeptest.py "602        )603        result = process.run(cmd_line, ignore_status=True)604        expected_rc = exit_codes.AVOCADO_ALL_OK605        self.assertEqual(606            result.exit_status,607            expected_rc,608            f"Avocado did not return rc {expected_rc}:\n{result}",609        )610        json_path = os.path.join(self.tmpdir.name, "latest", "results.json")611        with open(json_path, encoding="utf-8") as json_file:612            result_json = json.load(json_file)613        with open(614            result_json["tests"][0]["logfile"], "r+b"615        ) as test_log_file:  # pylint: disable=W1514616            test_log = test_log_file.read()617        self.assertIn(618            b"PARAMS (key=sleep_length, path=*, default=1) => '0.01'", test_log619        )620        self.assertIn(b"Sleeping for 0.01 seconds", test_log)621    def test_other_loggers(self):622        with script.TemporaryScript(623            "mytest.py",624            TEST_OTHER_LOGGERS_CONTENT,625            "avocado_functional_test_other_loggers",626        ) as mytest:627            cmd_line = (628                f"{AVOCADO} run --disable-sysinfo "629                f"--job-results-dir {self.tmpdir.name} -- {mytest}"630            )631            result = process.run(cmd_line, ignore_status=True)632            expected_rc = exit_codes.AVOCADO_ALL_OK633            self.assertEqual(634                result.exit_status,635                expected_rc,636                (f"Avocado did not return rc {expected_rc}:" f"\n{result}"),637            )638            test_log_dir = glob.glob(639                os.path.join(self.tmpdir.name, "job-*", "test-results", "1-*")640            )[0]641            test_log_path = os.path.join(test_log_dir, "debug.log")642            with open(test_log_path, "rb") as test_log:  # pylint: disable=W1514643                self.assertNotIn(b"SHOULD NOT BE ON debug.log", test_log.read())644    def test_store_logging_stream(self):645        cmd = (646            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "647            f"--store-logging-stream=avocado.test.progress "648            f"--disable-sysinfo -- examples/tests/logging_streams.py"649        )650        result = process.run(cmd)651        self.assertEqual(result.exit_status, exit_codes.AVOCADO_ALL_OK)652        progress_info = os.path.join(653            self.tmpdir.name,654            "latest",655            "test-results",656            "1-examples_tests_logging_streams.py_Plant" ".test_plant_organic",657            "avocado.test.progress",658        )659        self.assertTrue(os.path.exists(progress_info))660        with open(progress_info, encoding="utf-8") as file:661            stream_line = file.readline()662            self.assertIn(663                "INFO | 1-examples/tests/logging_streams.py:"664                "Plant.test_plant_organic: preparing soil on row 0",665                stream_line,666            )667class DryRunTest(TestCaseTmpDir):668    def test_dry_run(self):669        examples_path = os.path.join("examples", "tests")670        passtest = os.path.join(examples_path, "passtest.py")671        failtest = os.path.join(examples_path, "failtest.py")672        gendata = os.path.join(examples_path, "gendata.py")673        cmd = (674            f"{AVOCADO} run --disable-sysinfo --dry-run "675            f"--dry-run-no-cleanup --json - "676            f"-- {passtest} {failtest} {gendata}"677        )678        number_of_tests = 3679        result = json.loads(process.run(cmd).stdout_text)680        # Check if all tests were skipped681        self.assertEqual(result["cancel"], number_of_tests)682        for i in range(number_of_tests):683            test = result["tests"][i]684            self.assertEqual(test["fail_reason"], "Test cancelled due to --dry-run")685class RunnerHumanOutputTest(TestCaseTmpDir):686    def test_output_pass(self):687        cmd_line = (688            f"{AVOCADO} run --disable-sysinfo --job-results-dir "689            f"{self.tmpdir.name} examples/tests/passtest.py"690        )691        result = process.run(cmd_line, ignore_status=True)692        expected_rc = exit_codes.AVOCADO_ALL_OK693        self.assertEqual(694            result.exit_status,695            expected_rc,696            f"Avocado did not return rc {expected_rc}:\n{result}",697        )698        self.assertIn(b"passtest.py:PassTest.test:  PASS", result.stdout)699    def test_output_fail(self):700        cmd_line = (701            f"{AVOCADO} run --disable-sysinfo --job-results-dir "702            f"{self.tmpdir.name} examples/tests/failtest.py"703        )704        result = process.run(cmd_line, ignore_status=True)705        expected_rc = exit_codes.AVOCADO_TESTS_FAIL706        self.assertEqual(707            result.exit_status,708            expected_rc,709            f"Avocado did not return rc {expected_rc}:\n{result}",710        )711        self.assertIn(b"examples/tests/failtest.py:FailTest.test:  FAIL", result.stdout)712    def test_output_error(self):713        cmd_line = (714            f"{AVOCADO} run --disable-sysinfo --job-results-dir "715            f"{self.tmpdir.name} examples/tests/errortest.py"716        )717        result = process.run(cmd_line, ignore_status=True)718        expected_rc = exit_codes.AVOCADO_TESTS_FAIL719        self.assertEqual(720            result.exit_status,721            expected_rc,722            f"Avocado did not return rc {expected_rc}:\n{result}",723        )724        self.assertIn(b"errortest.py:ErrorTest.test:  ERROR", result.stdout)725    def test_output_cancel(self):726        cmd_line = (727            f"{AVOCADO} run --disable-sysinfo --job-results-dir "728            f"{self.tmpdir.name} examples/tests/cancelonsetup.py"729        )730        result = process.run(cmd_line, ignore_status=True)731        expected_rc = exit_codes.AVOCADO_ALL_OK732        self.assertEqual(733            result.exit_status,734            expected_rc,735            f"Avocado did not return rc {expected_rc}:\n{result}",736        )737        self.assertIn(738            b"PASS 0 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | " b"INTERRUPT 0 | CANCEL 1",739            result.stdout,740        )741class RunnerExecTest(TestCaseTmpDir):742    def setUp(self):743        super().setUp()744        self.pass_script = script.TemporaryScript(745            "\u00e1 \u00e9 \u00ed \u00f3 \u00fa",746            "#!/bin/sh\ntrue",747            "avocado_exec_test_functional",748        )749        self.pass_script.save()750        self.fail_script = script.TemporaryScript(751            "avocado_fail.sh", "#!/bin/sh\nfalse", "avocado_exec_test_" "functional"752        )753        self.fail_script.save()754    def test_exec_test_pass(self):755        cmd_line = (756            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "757            f'--disable-sysinfo "{self.pass_script.path}"'758        )759        result = process.run(cmd_line, ignore_status=True)760        expected_rc = exit_codes.AVOCADO_ALL_OK761        self.assertEqual(762            result.exit_status,763            expected_rc,764            f"Avocado did not return rc {expected_rc}:\n{result}",765        )766    def test_exec_test_fail(self):767        cmd_line = (768            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "769            f"--disable-sysinfo {self.fail_script.path}"770        )771        result = process.run(cmd_line, ignore_status=True)772        expected_rc = exit_codes.AVOCADO_TESTS_FAIL773        self.assertEqual(774            result.exit_status,775            expected_rc,776            f"Avocado did not return rc {expected_rc}:\n{result}",777        )778    @skipOnLevelsInferiorThan(2)779    def test_runner_onehundred_fail_timing(self):780        """781        We can be pretty sure that a failtest should return immediately. Let's782        run 100 of them and assure they not take more than 30 seconds to run.783        Notice: on a current machine this takes about 0.12s, so 30 seconds is784        considered to be pretty safe here.785        :avocado: tags=parallel:1786        """787        one_hundred = "examples/tests/failtest.py " * 100788        cmd_line = (789            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "790            f"--disable-sysinfo {one_hundred}"791        )792        initial_time = time.monotonic()793        result = process.run(cmd_line, ignore_status=True)794        actual_time = time.monotonic() - initial_time795        self.assertLess(actual_time, 60.0)796        expected_rc = exit_codes.AVOCADO_TESTS_FAIL797        self.assertEqual(798            result.exit_status,799            expected_rc,800            f"Avocado did not return rc {expected_rc}:\n{result}",801        )802    @skipOnLevelsInferiorThan(2)803    def test_runner_sleep_fail_sleep_timing(self):804        """805        Sleeptest is supposed to take 1 second, let's make a sandwich of806        100 failtests and check the test runner timing.807        :avocado: tags=parallel:1808        """809        sleep_fail_sleep = (810            "examples/tests/sleeptest.py "811            + "examples/tests/failtest.py " * 100812            + "examples/tests/sleeptest.py"813        )814        cmd_line = (815            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "816            f"--disable-sysinfo {sleep_fail_sleep}"817        )818        initial_time = time.monotonic()819        result = process.run(cmd_line, ignore_status=True)820        actual_time = time.monotonic() - initial_time821        self.assertLess(actual_time, 63.0)822        expected_rc = exit_codes.AVOCADO_TESTS_FAIL823        self.assertEqual(824            result.exit_status,825            expected_rc,826            f"Avocado did not return rc {expected_rc}:\n{result}",827        )828    def test_non_absolute_path(self):829        test_base_dir = os.path.dirname(self.pass_script.path)830        os.chdir(test_base_dir)831        test_file_name = os.path.basename(self.pass_script.path)832        cmd_line = (833            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "834            f'--disable-sysinfo  "{test_file_name}"'835        )836        result = process.run(cmd_line, ignore_status=True)837        expected_rc = exit_codes.AVOCADO_ALL_OK838        self.assertEqual(839            result.exit_status,840            expected_rc,841            f"Avocado did not return rc {expected_rc}:\n{result}",842        )843    def tearDown(self):844        self.pass_script.remove()845        self.fail_script.remove()846        super().tearDown()847class RunnerReferenceFromConfig(TestCaseTmpDir):848    def setUp(self):849        super().setUp()850        self.config_file = script.TemporaryScript(851            "avocado.conf", "[resolver]\n" "references = ['/bin/true']\n"852        )853        self.config_file.save()854    @skipUnlessPathExists("/bin/true")855    def test(self):856        cmd_line = (857            f"{AVOCADO} --config {self.config_file.path} run "858            f"--job-results-dir {self.tmpdir.name} --disable-sysinfo "859        )860        result = process.run(cmd_line, ignore_status=True)861        expected_rc = exit_codes.AVOCADO_ALL_OK862        self.assertEqual(863            result.exit_status,864            expected_rc,865            f"Avocado did not return rc {expected_rc}:\n{result}",866        )867    def tearDown(self):868        super().tearDown()869        self.config_file.remove()870class RunnerExecTestFailureFields(TestCaseTmpDir):871    def setUp(self):872        super().setUp()873        self.config_file = script.TemporaryScript(874            "avocado.conf",875            "[simpletests.status]\n" "failure_fields = ['stdout', 'stderr']\n",876        )877        self.config_file.save()878    def test_exec_test_failure_fields(self):879        fail_test = os.path.join(BASEDIR, "examples", "tests", "failtest.sh")880        cmd_line = (881            f"{AVOCADO} --config {self.config_file.path} run "882            f"--job-results-dir {self.tmpdir.name} "883            f"--disable-sysinfo -- {fail_test}"884        )885        result = process.run(cmd_line, ignore_status=True)886        expected_rc = exit_codes.AVOCADO_TESTS_FAIL887        self.assertEqual(888            result.exit_status,889            expected_rc,890            f"Avocado did not return rc {expected_rc}:\n{result}",891        )892        self.assertNotIn("Exited with status: '1'", result.stdout_text)893    def tearDown(self):894        super().tearDown()895        self.config_file.remove()896class PluginsTest(TestCaseTmpDir):897    def test_sysinfo_plugin(self):898        cmd_line = f"{AVOCADO} sysinfo {self.tmpdir.name}"899        result = process.run(cmd_line, ignore_status=True)900        expected_rc = exit_codes.AVOCADO_ALL_OK901        self.assertEqual(902            result.exit_status,903            expected_rc,904            f"Avocado did not return rc {expected_rc}:\n{result}",905        )906        sysinfo_files = os.listdir(self.tmpdir.name)907        self.assertGreater(len(sysinfo_files), 0, "Empty sysinfo files dir")908    def test_list_plugin(self):909        cmd_line = f"{AVOCADO} list"910        result = process.run(cmd_line, ignore_status=True)911        expected_rc = exit_codes.AVOCADO_ALL_OK912        self.assertEqual(913            result.exit_status,914            expected_rc,915            f"Avocado did not return rc {expected_rc}:\n{result}",916        )917        self.assertNotIn(b"No tests were found on current tests dir", result.stdout)918    def test_list_error_output(self):919        cmd_line = f"{AVOCADO} list sbrubles"920        result = process.run(cmd_line, ignore_status=True)921        self.assertEqual("", result.stdout_text)922    def test_plugin_list(self):923        cmd_line = f"{AVOCADO} plugins"924        result = process.run(cmd_line, ignore_status=True)925        expected_rc = exit_codes.AVOCADO_ALL_OK926        self.assertEqual(927            result.exit_status,928            expected_rc,929            f"Avocado did not return rc {expected_rc}:\n{result}",930        )931        self.assertNotIn(b"Disabled", result.stdout)932    def test_config_plugin(self):933        cmd_line = f"{AVOCADO} config "934        result = process.run(cmd_line, ignore_status=True)935        expected_rc = exit_codes.AVOCADO_ALL_OK936        self.assertEqual(937            result.exit_status,938            expected_rc,939            f"Avocado did not return rc {expected_rc}:\n{result}",940        )941        self.assertNotIn(b"Disabled", result.stdout)942    def test_config_plugin_datadir(self):943        cmd_line = f"{AVOCADO} config --datadir "944        result = process.run(cmd_line, ignore_status=True)945        expected_rc = exit_codes.AVOCADO_ALL_OK946        self.assertEqual(947            result.exit_status,948            expected_rc,949            f"Avocado did not return rc {expected_rc}:\n{result}",950        )951        self.assertNotIn(b"Disabled", result.stdout)952    def test_disable_plugin(self):953        cmd_line = f"{AVOCADO} plugins"954        result = process.run(cmd_line, ignore_status=True)955        expected_rc = exit_codes.AVOCADO_ALL_OK956        self.assertEqual(957            result.exit_status,958            expected_rc,959            f"Avocado did not return rc {expected_rc}:\n{result}",960        )961        self.assertIn(b"Collect system information", result.stdout)962        config_content = "[plugins]\ndisable=['cli.cmd.sysinfo',]"963        config = script.TemporaryScript("disable_sysinfo_cmd.conf", config_content)964        with config:965            cmd_line = f"{AVOCADO} --config {config} plugins"966            result = process.run(cmd_line, ignore_status=True)967            expected_rc = exit_codes.AVOCADO_ALL_OK968            self.assertEqual(969                result.exit_status,970                expected_rc,971                (f"Avocado did not return rc {expected_rc}:" f"\n{result}"),972            )973            self.assertNotIn(b"Collect system information", result.stdout)974    def test_plugin_order(self):975        """976        Tests plugin order by configuration file977        First it checks if html, json, xunit and zip_archive plugins are enabled.978        Then it runs a test with zip_archive running first, which means the html,979        json and xunit output files do not make into the archive.980        Then it runs with zip_archive set to run last, which means the html,981        json and xunit output files *do* make into the archive.982        """983        def run_config(config_path):984            cmd = (985                f"{AVOCADO} --config {config_path} "986                f"run examples/tests/passtest.py --archive "987                f"--job-results-dir {self.tmpdir.name} "988                f"--disable-sysinfo"989            )990            result = process.run(cmd, ignore_status=True)991            expected_rc = exit_codes.AVOCADO_ALL_OK992            self.assertEqual(993                result.exit_status,994                expected_rc,995                (f"Avocado did not return rc {expected_rc}:" f"\n{result}"),996            )997        result_plugins = ["json", "xunit", "zip_archive"]998        result_outputs = ["results.json", "results.xml"]999        if python_module_available("avocado-framework-plugin-result-html"):1000            result_plugins.append("html")1001            result_outputs.append("results.html")1002        cmd_line = f"{AVOCADO} plugins"1003        result = process.run(cmd_line, ignore_status=True)1004        expected_rc = exit_codes.AVOCADO_ALL_OK1005        self.assertEqual(1006            result.exit_status,1007            expected_rc,1008            f"Avocado did not return rc {expected_rc}:\n{result}",1009        )1010        for result_plugin in result_plugins:1011            self.assertIn(result_plugin, result.stdout_text)1012        config_content_zip_first = "[plugins.result]\norder=['zip_archive']"1013        config_zip_first = script.TemporaryScript(1014            "zip_first.conf", config_content_zip_first1015        )1016        with config_zip_first:1017            run_config(config_zip_first)1018            archives = glob.glob(os.path.join(self.tmpdir.name, "*.zip"))1019            self.assertEqual(len(archives), 1, "ZIP Archive not generated")1020            zip_file = zipfile.ZipFile(archives[0], "r")1021            zip_file_list = zip_file.namelist()1022            for result_output in result_outputs:1023                self.assertNotIn(result_output, zip_file_list)1024            os.unlink(archives[0])1025        config_content_zip_last = (1026            "[plugins.result]\norder=['html', 'json',"1027            "'xunit', 'non_existing_plugin_is_ignored'"1028            ",'zip_archive']"1029        )1030        config_zip_last = script.TemporaryScript(1031            "zip_last.conf", config_content_zip_last1032        )1033        with config_zip_last:1034            run_config(config_zip_last)1035            archives = glob.glob(os.path.join(self.tmpdir.name, "*.zip"))1036            self.assertEqual(len(archives), 1, "ZIP Archive not generated")1037            zip_file = zipfile.ZipFile(archives[0], "r")1038            zip_file_list = zip_file.namelist()1039            for result_output in result_outputs:1040                self.assertIn(result_output, zip_file_list)1041    def test_Namespace_object_has_no_attribute(self):1042        cmd_line = f"{AVOCADO} plugins"1043        result = process.run(cmd_line, ignore_status=True)1044        expected_rc = exit_codes.AVOCADO_ALL_OK1045        self.assertEqual(1046            result.exit_status,1047            expected_rc,1048            f"Avocado did not return rc {expected_rc}:\n{result}",1049        )1050        self.assertNotIn(b"'Namespace' object has no attribute", result.stderr)1051class ParseXMLError(Exception):1052    pass1053class PluginsXunitTest(TestCaseTmpDir):1054    @unittest.skipUnless(1055        SCHEMA_CAPABLE, "Unable to validate schema due to missing xmlschema library"1056    )1057    def setUp(self):1058        super().setUp()1059        junit_xsd = os.path.join(1060            os.path.dirname(__file__), os.path.pardir, ".data", "jenkins-junit.xsd"1061        )1062        self.xml_schema = xmlschema.XMLSchema(junit_xsd)1063    def run_and_check(self, testname, e_rc, e_ntests, e_nerrors, e_nfailures, e_nskip):1064        cmd_line = (1065            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "1066            f"--disable-sysinfo "1067            f"--xunit - {testname}"1068        )1069        result = process.run(cmd_line, ignore_status=True)1070        xml_output = result.stdout1071        self.assertEqual(1072            result.exit_status, e_rc, f"Avocado did not return rc {e_rc}:\n{result}"1073        )1074        try:1075            xunit_doc = xml.dom.minidom.parseString(xml_output)1076        except Exception as detail:1077            raise ParseXMLError(f"Failed to parse content: {detail}\n{xml_output}")1078        # pylint: disable=I11011079        xunit_file_output = os.path.join(self.tmpdir.name, "latest", "results.xml")1080        self.assertTrue(self.xml_schema.is_valid(xunit_file_output))1081        testsuite_list = xunit_doc.getElementsByTagName("testsuite")1082        self.assertEqual(len(testsuite_list), 1, "More than one testsuite tag")1083        testsuite_tag = testsuite_list[0]1084        self.assertEqual(1085            len(testsuite_tag.attributes),1086            7,1087            (f"The testsuite tag does not have 7 attributes. " f"XML:\n{xml_output}"),1088        )1089        n_tests = int(testsuite_tag.attributes["tests"].value)1090        self.assertEqual(1091            n_tests,1092            e_ntests,1093            (f"Unexpected number of executed tests, XML:\n" f"{xml_output}"),1094        )1095        n_errors = int(testsuite_tag.attributes["errors"].value)1096        self.assertEqual(1097            n_errors,1098            e_nerrors,1099            (f"Unexpected number of test errors, XML:\n" f"{xml_output}"),1100        )1101        n_failures = int(testsuite_tag.attributes["failures"].value)1102        self.assertEqual(1103            n_failures,1104            e_nfailures,1105            (f"Unexpected number of test failures, XML:\n" f"{xml_output}"),1106        )1107        n_skip = int(testsuite_tag.attributes["skipped"].value)1108        self.assertEqual(1109            n_skip, e_nskip, f"Unexpected number of test skips, XML:\n" f"{xml_output}"1110        )1111    def test_xunit_plugin_passtest(self):1112        self.run_and_check(1113            "examples/tests/passtest.py", exit_codes.AVOCADO_ALL_OK, 1, 0, 0, 01114        )1115    def test_xunit_plugin_failtest(self):1116        self.run_and_check(1117            "examples/tests/failtest.py", exit_codes.AVOCADO_TESTS_FAIL, 1, 0, 1, 01118        )1119    def test_xunit_plugin_skiponsetuptest(self):1120        self.run_and_check(1121            "examples/tests/cancelonsetup.py", exit_codes.AVOCADO_ALL_OK, 1, 0, 0, 11122        )1123    def test_xunit_plugin_errortest(self):1124        self.run_and_check(1125            "examples/tests/errortest.py", exit_codes.AVOCADO_TESTS_FAIL, 1, 1, 0, 01126        )1127class ParseJSONError(Exception):1128    pass1129class PluginsJSONTest(TestCaseTmpDir):1130    def run_and_check(1131        self, testname, e_rc, e_ntests, e_nerrors, e_nfailures, e_nskip, e_ncancel=01132    ):1133        cmd_line = (1134            f"{AVOCADO} run --job-results-dir {self.tmpdir.name} "1135            f"--disable-sysinfo --json - "1136            f"--archive {testname}"1137        )1138        result = process.run(cmd_line, ignore_status=True)1139        json_output = result.stdout_text1140        self.assertEqual(1141            result.exit_status, e_rc, f"Avocado did not return rc {e_rc}:\n{result}"1142        )1143        try:1144            json_data = json.loads(json_output)1145        except Exception as detail:1146            raise ParseJSONError(1147                (f"Failed to parse content: {detail}\n" f"{json_output}")1148            )1149        self.assertTrue(json_data, f"Empty JSON result:\n{json_output}")1150        self.assertIsInstance(1151            json_data["tests"], list, "JSON result lacks 'tests' list"1152        )1153        n_tests = len(json_data["tests"])1154        self.assertEqual(n_tests, e_ntests, "Different number of expected tests")1155        n_errors = json_data["errors"]1156        self.assertEqual(n_errors, e_nerrors, "Different number of expected tests")1157        n_failures = json_data["failures"]1158        self.assertEqual(n_failures, e_nfailures, "Different number of expected tests")1159        n_skip = json_data["skip"]1160        self.assertEqual(n_skip, e_nskip, "Different number of skipped tests")1161        n_cancel = json_data["cancel"]1162        self.assertEqual(n_cancel, e_ncancel)1163        return json_data1164    def test_json_plugin_passtest(self):1165        self.run_and_check(1166            "examples/tests/passtest.py", exit_codes.AVOCADO_ALL_OK, 1, 0, 0, 01167        )1168    def test_json_plugin_failtest(self):1169        self.run_and_check(1170            "examples/tests/failtest.py", exit_codes.AVOCADO_TESTS_FAIL, 1, 0, 1, 01171        )1172    def test_json_plugin_skiponsetuptest(self):1173        self.run_and_check(1174            "examples/tests/cancelonsetup.py", exit_codes.AVOCADO_ALL_OK, 1, 0, 0, 0, 11175        )1176    def test_json_plugin_errortest(self):1177        self.run_and_check(1178            "examples/tests/errortest.py", exit_codes.AVOCADO_TESTS_FAIL, 1, 1, 0, 01179        )1180if __name__ == "__main__":...plant.py
Source:plant.py  
2import time3from avocado import Test4progress_log = logging.getLogger("progress")5class Plant(Test):6    def test_plant_organic(self):7        rows = self.params.get("rows", default=3)8        # Preparing soil9        for row in range(rows):10            progress_log.info("%s: preparing soil on row %s",11                              self.name, row)12        # Letting soil rest13        progress_log.info("%s: letting soil rest before throwing seeds",14                          self.name)15        time.sleep(2)16        # Throwing seeds17        for row in range(rows):18            progress_log.info("%s: throwing seeds on row %s",19                              self.name, row)20        # Let them grow...logging_streams.py
Source:logging_streams.py  
2import time3from avocado import Test4class Plant(Test):5    """Logs parts of the test progress in an specific logging stream."""6    def test_plant_organic(self):7        progress_log = logging.getLogger("avocado.test.progress")8        rows = int(self.params.get("rows", default=3))9        # Preparing soil10        for row in range(rows):11            progress_log.info("%s: preparing soil on row %s", self.name, row)12        # Letting soil rest13        progress_log.info("%s: letting soil rest before throwing seeds", self.name)14        time.sleep(1)15        # Throwing seeds16        for row in range(rows):17            progress_log.info("%s: throwing seeds on row %s", self.name, row)18        # Let them grow19        progress_log.info("%s: waiting for Avocados to grow", self.name)20        time.sleep(2)...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!!
