Best Python code snippet using autotest_python
pipeline.py
Source:pipeline.py  
1'''2Build the pipeline workflow by plumbing the stages together.3'''4from ruffus import Pipeline, suffix, formatter, add_inputs, output_from5from stages import Stages6def make_pipeline(state):7    '''Build the pipeline by constructing stages and connecting them together'''8    # Build an empty pipeline9    pipeline = Pipeline(name='fastq2bam')10    # Get a list of paths to all the FASTQ files11    input_files = state.config.get_option('files')12    # Stages are dependent on the state13    stages = Stages(state)14    # The original files15    # This is a dummy stage. It is useful because it makes a node in the16    # pipeline graph, and gives the pipeline an obvious starting point.17    pipeline.originate(18        task_func=stages.original_files,19        name='original_files',20        output=input_files)21    #22    # performs fastqc on fastq inputs23    # 24    pipeline.transform(25        task_func=stages.fastqc,26        name='fastqc',27        input=output_from('original_files'),28        filter=formatter('(?P<path>.+)/(?P<filename>.+).fastq.gz'),29        output='{path[0]}/{filename[0]}_fastqc')30    #31    # converts the fastq inputs to pre-aligned bams32    #33    pipeline.transform(34        task_func=stages.fastq2bam,35        name='fastq2bam',36        input=output_from('original_files'),37        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+)_R1.fastq.gz'),38        add_inputs=add_inputs('{path[0]}/{sample[0]}_R2.fastq.gz'),39        extras=['{sample[0]}'],40        output='{path[0]}/{sample[0]}.bam')41    #42    # validates pre-aligned bams x.bam -> x.validation43    #44    pipeline.transform(45        task_func=stages.validate_prealigned_bam,46        name='validate_prealigned_bam',47        input=output_from('fastq2bam'),48        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).bam'),49        output='{path[0]}/{sample[0]}.validation')50    # aligns pre-aligned bam x.bam -> x.mapped.bam51    pipeline.transform(52        task_func=stages.align,53        name='align',54        input=output_from('validate_prealigned_bam'),55        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).validation'),56        add_inputs=add_inputs('{path[0]}/{sample[0]}.bam'),57        output='{path[0]}/{sample[0]}.mapped.bam')58    # generates stats about an aligned bam59    pipeline.transform(60        task_func=stages.align_stats_bedtools,61        name='align_stats_bedtools',62        input=output_from('align'),63        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),64        output='{path[0]}/{sample[0]}.genomecov.stats')65    # generates stats about an aligned bam66    pipeline.transform(67        task_func=stages.align_stats_picard,68        name='align_stats_picard',69        input=output_from('align'),70        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),71        output='{path[0]}/{sample[0]}.picard.stats')72    #73    # runs the Sanger variant calling pipeline74    #75    #pipeline.transform(76    #    task_func=stages.analyse_wgs,77    #    name='analyse_wgs',78    #    input=output_from('align'),79    #    filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),80    #    output='{path[0]}/{sample[0]}.wgs.1.1.2/manifest')81    # runs the components of the Sanger variant calling pipeline82    pipeline.transform(83        task_func=stages.analyse_wgs_prepare,84        name='analyse_wgs_prepare',85        input=output_from('align'),86        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),87        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.prepare')88    pipeline.transform(89        task_func=stages.analyse_wgs_reference_files,90        name='analyse_wgs_reference_files',91        input=output_from('align'),92        add_inputs=add_inputs(output_from('analyse_wgs_prepare')),93        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),94        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.reference_files')95    pipeline.transform(96        task_func=stages.analyse_wgs_init,97        name='analyse_wgs_init',98        input=output_from('align'),99        add_inputs=add_inputs(output_from('analyse_wgs_reference_files')),100        filter=formatter('(?P<path>.*)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),101        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.init')102    # block 1103    pipeline.transform(104        task_func=stages.analyse_wgs_verify_WT,105        name='analyse_wgs_verify_WT',106        input=output_from('align'),107        add_inputs=add_inputs(output_from('analyse_wgs_init')),108        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),109        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.verify_WT')110    pipeline.transform(111        task_func=stages.analyse_wgs_geno,112        name='analyse_wgs_geno',113        input=output_from('align'),114        add_inputs=add_inputs(output_from('analyse_wgs_init')),115        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),116        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.geno')117    #pipeline.transform(118    #    task_func=stages.analyse_wgs_cgpPindel_input,119    #    name='analyse_wgs_cgpPindel_input',120    #    input=output_from('align'),121    #    add_inputs=add_inputs(output_from('analyse_wgs_init')),122    #    filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),123    #    output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.cgpPindel_input')124    pipeline.transform(125        task_func=stages.analyse_wgs_alleleCount,126        name='analyse_wgs_alleleCount',127        input=output_from('align'),128        add_inputs=add_inputs(output_from('analyse_wgs_init')),129        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),130        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.alleleCount')131    # block 2132    pipeline.transform(133        task_func=stages.analyse_wgs_cgpPindel,134        name='analyse_wgs_cgpPindel',135        input=output_from('align'),136        add_inputs=add_inputs(output_from('analyse_wgs_init')),137        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),138        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.cgpPindel')139    pipeline.transform(140        task_func=stages.analyse_wgs_BRASS_input,141        name='analyse_wgs_BRASS_input',142        input=output_from('align'),143        add_inputs=add_inputs(output_from('analyse_wgs_init')),144        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),145        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.BRASS_input')146    pipeline.transform(147        task_func=stages.analyse_wgs_BRASS_cover,148        name='analyse_wgs_BRASS_cover',149        input=output_from('align'),150        add_inputs=add_inputs(output_from('analyse_wgs_init')),151        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),152        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.BRASS_cover')153    pipeline.transform(154        task_func=stages.analyse_wgs_CaVEMan_split,155        name='analyse_wgs_CaVEMan_split',156        input=output_from('align'),157        add_inputs=add_inputs(output_from('analyse_wgs_init')),158        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),159        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.CaVEMan_split')160    # block 2.5161    pipeline.transform(162        task_func=stages.analyse_wgs_ascat,163        name='analyse_wgs_ascat',164        input=output_from('align'),165        add_inputs=add_inputs(output_from('analyse_wgs_CaVEMan_split')),166        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),167        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.ascat')168    # after block 2169    pipeline.transform(170        task_func=stages.analyse_wgs_ascat_prep,171        name='analyse_wgs_ascat_prep',172        input=output_from('align'),173        add_inputs=add_inputs(output_from('analyse_wgs_ascat')),174        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),175        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.ascat_prep')176    pipeline.transform(177        task_func=stages.analyse_wgs_pindel_prep,178        name='analyse_wgs_pindel_prep',179        input=output_from('align'),180        add_inputs=add_inputs(output_from('analyse_wgs_cgpPindel')),181        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),182        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.pindel_prep')183    # parallel block 3184    pipeline.transform(185        task_func=stages.analyse_wgs_verify_MT,186        name='analyse_wgs_verify_MT',187        input=output_from('align'), 188        add_inputs=add_inputs(output_from('analyse_wgs_verify_WT'), output_from('analyse_wgs_prepare'), output_from('analyse_wgs_ascat')),189        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),190        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.verify_MT')191    pipeline.transform(192        task_func=stages.analyse_wgs_CaVEMan,193        name='analyse_wgs_CaVEMan',194        input=output_from('align'), 195        add_inputs=add_inputs(output_from('analyse_wgs_CaVEMan_split'), output_from('analyse_wgs_ascat_prep'), output_from('analyse_wgs_cgpPindel')),196        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),197        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.CaVEMan')198    pipeline.transform(199        task_func=stages.analyse_wgs_BRASS,200        name='analyse_wgs_BRASS',201        input=output_from('align'), 202        add_inputs=add_inputs(output_from('analyse_wgs_BRASS_cover'), output_from('analyse_wgs_BRASS_input'), output_from('analyse_wgs_prepare')),203        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),204        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.BRASS')205    pipeline.transform(206        task_func=stages.analyse_wgs_cgpPindel_annot,207        name='analyse_wgs_cgpPindel_annot',208        input=output_from('align'),209        add_inputs=add_inputs(output_from('analyse_wgs_pindel_prep')),210        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),211        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.cgpPindel_annot')212    # block 5213    pipeline.transform(214        task_func=stages.analyse_wgs_cgpFlagCaVEMan,215        name='analyse_wgs_cgpFlagCaVEMan',216        input=output_from('align'),217        add_inputs=add_inputs(output_from('analyse_wgs_CaVEMan')),218        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),219        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.cgpFlagCaVEMan')220    # pre block 6221    pipeline.transform(222        task_func=stages.analyse_wgs_CaVEMan_annot_prep,223        name='analyse_wgs_CaVEMan_annot_prep',224        input=output_from('align'),225        add_inputs=add_inputs(output_from('analyse_wgs_cgpFlagCaVEMan')),226        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),227        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.CaVEMan_annot_prep')228    # pre block 6229    pipeline.transform(230        task_func=stages.analyse_wgs_caveman_prep,231        name='analyse_wgs_caveman_prep',232        input=output_from('align'),233        add_inputs=add_inputs(output_from('analyse_wgs_CaVEMan_annot_prep')),234        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),235        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.caveman_prep')236    # block 6237    pipeline.transform(238        task_func=stages.analyse_wgs_CaVEMan_annot,239        name='analyse_wgs_CaVEMan_annot',240        input=output_from('align'),241        add_inputs=add_inputs(output_from('analyse_wgs_caveman_prep')),242        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),243        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.CaVEMan_annot')244    # done245    pipeline.transform(246        task_func=stages.analyse_wgs_finish,247        name='analyse_wgs_finish',248        input=output_from('align'), 249        add_inputs=add_inputs(output_from('analyse_wgs_CaVEMan_annot'), output_from('analyse_wgs_BRASS'), output_from('analyse_wgs_cgpPindel_annot'), output_from('analyse_wgs_alleleCount'), output_from('analyse_wgs_verify_MT'), output_from('analyse_wgs_verify_WT')),250        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),251        output='{path[0]}/{sample[0]}.wgs.1.1.2-completed.finish')252    #253    # runs the delly singularity container254    #255#    pipeline.transform(256#        task_func=stages.delly,257#        name='delly',258#        input=output_from('align'),259#        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),260#        output='{path[0]}/{sample[0]}.delly.completed')261    pipeline.transform(262        task_func=stages.gridss,263        name='gridss',264        input=output_from('align'),265        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),266        output='{path[0]}/{sample[0]}.gridss.completed')267    pipeline.transform(268        task_func=stages.muse,269        name='muse',270        input=output_from('align'),271        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),272        output='{path[0]}/{sample[0]}.muse.completed')273    pipeline.transform(274        task_func=stages.mutect1,275        name='mutect1',276        input=output_from('align'),277        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),278        output='{path[0]}/{sample[0]}.mutect1.completed')279#    pipeline.transform(280#        task_func=stages.mutect2,281#        name='mutect2',282#        input=output_from('align'),283#        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),284#        output='{path[0]}/{sample[0]}.mutect2.completed')285    pipeline.transform(286        task_func=stages.platypus,287        name='platypus',288        input=output_from('align'),289        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),290        output='{path[0]}/{sample[0]}.platypus.completed')291    pipeline.transform(292        task_func=stages.varscan_germline,293        name='varscan_germline',294        input=output_from('align'),295        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),296        output='{path[0]}/{sample[0]}.varscan.completed')297#    pipeline.transform(298#        task_func=stages.varscan_germline_indel,299#        name='varscan_germline_indel',300#        input=output_from('align'),301#        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),302#        output='{path[0]}/{sample[0]}.varscan_indel.completed')303    pipeline.transform(304        task_func=stages.hmmcopy,305        name='hmmcopy',306        input=output_from('align'),307        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),308        output='{path[0]}/{sample[0]}.hmmcopy.completed')309    pipeline.transform(310        task_func=stages.callable_bases,311        name='callable_bases',312        input=output_from('align'),313        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),314        output='{path[0]}/{sample[0]}.callable_bases.completed')315    pipeline.transform(316        task_func=stages.somatic_sniper,317        name='somatic_sniper',318        input=output_from('align'),319        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),320        output='{path[0]}/{sample[0]}.somatic_sniper.completed')321    pipeline.transform(322        task_func=stages.contest,323        name='contest',324        input=output_from('align'),325        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),326        output='{path[0]}/{sample[0]}.contest.completed')327#    pipeline.transform(328#        task_func=stages.delly2,329#        name='delly2',330#        input=output_from('align'),331#        filter=formatter('(?P<path>.+)/(?P<sample>[a-zA-Z0-9]+).mapped.bam'),332#        output='{path[0]}/{sample[0]}.delly2.completed')333    ...test_tasks_thread.py
Source:test_tasks_thread.py  
2import time3import pytest4from labthings.actions import pool, thread5def test_task_with_args():6    def task_func(arg, kwarg=False):7        pass8    task_obj = thread.ActionThread(9        "task_func", target=task_func, args=("String arg",), kwargs={"kwarg": True}10    )11    assert isinstance(task_obj, threading.Thread)12    assert task_obj._target == task_func13    assert task_obj._args == ("String arg",)14    assert task_obj._kwargs == {"kwarg": True}15def test_task_without_args():16    def task_func():17        pass18    task_obj = thread.ActionThread("task_func", target=task_func)19    assert isinstance(task_obj, threading.Thread)20    assert task_obj._target == task_func21    assert task_obj._args == ()22    assert task_obj._kwargs == {}23def test_task_properties():24    def task_func(arg, kwarg=False):25        pass26    task_obj = thread.ActionThread(27        "task_func", target=task_func, args=("String arg",), kwargs={"kwarg": True}28    )29    assert task_obj.status == task_obj._status30    assert task_obj.id == task_obj._ID31    assert task_obj.status == task_obj._status32    assert task_obj.output == task_obj._return_value33def test_task_update_progress():34    def task_func():35        pool.current_action().update_progress(100)36        return37    task_obj = thread.ActionThread("task_func", target=task_func)38    task_obj.start()39    task_obj.join()40    assert task_obj.progress == 10041def test_task_update_data():42    def task_func():43        pool.current_action().update_data({"key": "value"})44        return45    task_obj = thread.ActionThread("task_func", target=task_func)46    task_obj.start()47    task_obj.join()48    assert task_obj.data == {"key": "value"}49def test_task_start():50    def task_func():51        return "Return value"52    task_obj = thread.ActionThread("task_func", target=task_func)53    assert task_obj._status == "pending"54    assert task_obj._return_value is None55    task_obj.start()56    task_obj.join()57    assert task_obj._return_value == "Return value"58    assert task_obj._status == "completed"59def test_task_get():60    def task_func():61        time.sleep(0.1)62        return "Return value"63    task_obj = thread.ActionThread("task_func", target=task_func)64    task_obj.start()65    assert task_obj.get() == "Return value"66def test_task_get_noblock():67    def task_func():68        time.sleep(0.1)69        return "Return value"70    task_obj = thread.ActionThread("task_func", target=task_func)71    task_obj.start()72    task_obj.join()73    assert task_obj.get(block=False, timeout=0) == "Return value"74def test_task_get_noblock_timeout():75    def task_func():76        time.sleep(0.1)77        return "Return value"78    task_obj = thread.ActionThread("task_func", target=task_func)79    task_obj.start()80    with pytest.raises(TimeoutError):81        assert task_obj.get(block=False, timeout=0)82@pytest.mark.filterwarnings("ignore:Exception in thread")83def test_task_exception():84    exc_to_raise = Exception("Exception message")85    def task_func():86        raise exc_to_raise87    task_obj = thread.ActionThread("task_func", target=task_func)88    task_obj.start()89    task_obj.join()90    assert task_obj._status == "error"91    assert task_obj._return_value == str(exc_to_raise)92def test_task_stop():93    def task_func():94        while not pool.current_action().stopped:95            time.sleep(0)96    task_obj = thread.ActionThread("task_func", target=task_func)97    task_obj.start()98    task_obj.started.wait()99    assert task_obj._status == "running"100    task_obj.stop()101    task_obj.join()102    assert task_obj._status == "cancelled"103    assert task_obj._return_value is None104def test_task_stop_timeout():105    def task_func():106        while True:107            time.sleep(0)108    task_obj = thread.ActionThread("task_func", target=task_func)109    task_obj.start()110    task_obj.started.wait()111    assert task_obj._status == "running"112    task_obj.stop(timeout=0)113    task_obj.join()114    assert task_obj._status == "cancelled"115    assert task_obj._return_value is None116def test_task_terminate():117    def task_func():118        while True:119            time.sleep(0.5)120    task_obj = thread.ActionThread("task_func", target=task_func)121    task_obj.start()122    task_obj.started.wait()123    assert task_obj._status == "running"124    task_obj.terminate()125    task_obj.join()126    assert task_obj._status == "cancelled"127    assert task_obj._return_value is None128def test_task_terminate_not_running():129    def task_func():130        return131    task_obj = thread.ActionThread("task_func", target=task_func)132    task_obj.start()133    task_obj.join()134    assert task_obj.terminate() is False135def test_task_log_with_incorrect_thread():136    task_obj = thread.ActionThread(None)137    task_log_handler = thread.ThreadLogHandler(task_obj, task_obj._log)138    # Should always return False if called from outside the log handlers thread139    assert task_log_handler.thread == task_obj...test_tasks_pool.py
Source:test_tasks_pool.py  
1import threading2from labthings import actions3def test_spawn_without_context(task_pool):4    def task_func():5        pass6    task_obj = task_pool.spawn("task_func", task_func)7    assert isinstance(task_obj, threading.Thread)8def test_spawn_with_context(app_ctx, task_pool):9    def task_func():10        pass11    with app_ctx.test_request_context():12        task_obj = task_pool.spawn("task_func", task_func)13        assert isinstance(task_obj, threading.Thread)14def test_update_task_data(task_pool):15    def task_func():16        actions.update_action_data({"key": "value"})17    task_obj = task_pool.spawn("task_func", task_func)18    task_obj.join()19    assert task_obj.data == {"key": "value"}20def test_update_task_data_main_thread():21    # Should do nothing22    actions.update_action_data({"key": "value"})23def test_update_task_progress(task_pool):24    def task_func():25        actions.update_action_progress(100)26    task_obj = task_pool.spawn("task_func", task_func)27    task_obj.join()28    assert task_obj.progress == 10029def test_update_task_progress_main_thread():30    # Should do nothing31    actions.update_action_progress(100)32def test_tasks_list(task_pool):33    assert all(isinstance(task_obj, threading.Thread) for task_obj in task_pool.threads)34def test_tasks_dict(task_pool):35    assert all(36        isinstance(task_obj, threading.Thread)37        for task_obj in task_pool.to_dict().values()38    )39    assert all(k == str(t.id) for k, t in task_pool.to_dict().items())40def test_discard_id(task_pool):41    def task_func():42        pass43    task_obj = task_pool.spawn("task_func", task_func)44    assert str(task_obj.id) in task_pool.to_dict()45    task_obj.join()46    task_pool.discard_id(task_obj.id)47    assert not str(task_obj.id) in task_pool.to_dict()48def test_cleanup_task(task_pool):49    import time50    def task_func():51        pass52    # Make sure at least 1 actions is around53    task_pool.spawn("task_func", task_func)54    # Wait for all actions to finish55    task_pool.join()56    assert len(task_pool.threads) > 057    task_pool.cleanup()...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!!
