Skip to content

Testing functions that return a closure #364

Description

@mwhamgenomics

In one of my pipelines, I have a custom function that creates a closure that I can then apply to Channel.filter. Grossly oversimplified, it looks something like:

// lib/functions.nf
def create_filter(samples) {
    println 'Creating closure'
    def filter = {
        println "Running closure on ${it}"
        return samples.size() == 0 || samples.contains(it[0].id)
    }
    return filter
}


// main.nf
include { create_filter } from './lib/functions.nf'

params.samples = ''

workflow {
    def filter = create_filter(
        params.samples.toString().tokenize(','),
    )
    ch = Channel.of([[id: 'a'], 1], [[id: 'b'], 2], [[id: 'c'], 3])
    .filter(filter)
    .view()

    emit:
    output = ch
}

This works when I try running it as a workflow. The workflow in main.nf creates the closure, then Channel.filter runs it and filters my channel to the values specified:

$ nextflow run main.nf --samples a,c
Nextflow 26.04.2 is available - Please consider updating your version to it

 N E X T F L O W   ~  version 25.10.4

Launching `main.nf` [nice_dubinsky] DSL2 - revision: 1f92baa16e

Creating closure
Running closure on [[id:a], 1]
Running closure on [[id:b], 2]
Running closure on [[id:c], 3]
[[id:a], 1]
[[id:c], 3]

But when I try writing a test for it, I get some unexpected behaviour:

// tests/lib/functions.nf.test
nextflow_function {
    name 'Test functions.nf'
    script 'lib/functions.nf'

    test('Test create_filter') {
        function "create_filter"
        when {
            function {
                """
                input[0] = ['a', 'c']
                """
            }
        }
        then {
            assert function.success
        }
    }
}
$ nf-test test tests/lib/functions.nf.test

🚀 nf-test 0.9.4
https://www.nf-test.com
(c) 2021 - 2024 Lukas Forer and Sebastian Schoenherr

Warning: This pipeline has no nf-test config file.

Test functions.nf

  Test [1fd1e4fb] 'Test create_filter' FAILED (4.154s)

  Assertion failed: 

  assert function.success
         |        |
         |        false
         com.askimed.nf.test.lang.function.Function@6b9c69a9 (toString() == null)

  Nextflow stdout:

  Creating closure
  Running closure on null
  ERROR ~ Cannot invoke method getAt() on null object

   -- Check script '/Users/mwham/workspace/test_nf/lib/functions.nf' at line: 6 or see '/Users/mwham/workspace/test_nf/.nf-test/tests/1fd1e4fb8bc7c15f13359f703754ecb/meta/nextflow.log' file for more details
  Nextflow stderr:

  Nextflow 26.04.2 is available - Please consider updating your version to it

FAILURE: Executed 1 tests in 4.17s (1 failed)

create_filter is supposed to just create the closure, and I was hoping to then run some more assertions against it in the then block, but the println statements in the stdout are indicating that something in the test runner is jumping the gun and evaluating the closure prematurely. Any ideas what's going on, and/or any workarounds?

Many thanks,
Murray

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions