nvidia/udf-gen-test
Assists with generating a unit test for an Apache Spark UDF. This is step 1 of 3 in the UDF conversion workflow (udf-gen-test -> udf-convert-to-* -> udf-benchmark). Use this skill when you have a CPU UDF and need to create a unit test for the UDF before converting it into a GPU-compatible implementation.
npx skills add https://github.com/NVIDIA/cudf-spark --skill udf-gen-test
Before making any edits, create a visible TODO checklist for every workflow step in this skill and keep it updated. Do not produce a final answer until every required checklist item is marked complete.
Derive <CamelName> and <snake_name> from the UDF class name.
> Note: Commands require access to /tmp (Spark temp storage) and /dev (GPU device). If commands fail due to sandbox restrictions, re-run them unsandboxed.
The project can be found under this skill's templates directory.
cp -r templates/scala <project_root>/<CamelName>/
This provides a complete Maven project with all test and benchmark infrastructure.
Before copying code, decide whether the input UDF is already self-contained:
The template project should contain the smallest self-contained implementation of the target CPU UDF.
Place the resulting source file(s) in the source directory:
<CamelName>/src/main/java/com/udf/<CamelName>/src/main/scala/com/udf/Set the package declaration to com.udf:
package com.udf;package com.udfRead src/test/scala/com/udf/UnitTest.scala. Replace placeholders with the actual camel/snake UDF name.
Fill in the TODO methods following the docstrings. Include diverse edge cases in createTestData (nulls, empty strings, malformed inputs, varying lengths).
The generated tests should serve as a strong specification of the CPU UDF behavior over a documented input domain, and are intended to prove that a GPU or SQL implementation preserves the CPU UDF behavior.
For each input type and visible UDF branch, include applicable examples from these coverage dimensions:
Assertions should verify schema, row count, deterministic ordering, output values, null propagation, and exception/default behavior. Every visible UDF branch should be covered by the unit test or explicitly documented as out of scope.
udfName argument. This ensures the correct registered UDF is exercised.mvn test -Dsuites=com.udf.UnitTest
If it fails, analyze the error output (stdout/stderr) and fix the test code. Continue iterating until the test passes.
The template projects use JaCoCo (Java) / scoverage (Scala) code coverage tools.
# Java UDF
mvn -Pcoverage test jacoco:report -Dsuites=com.udf.UnitTest
# Scala UDF
mvn -Pcoverage scoverage:report -Dsuites=com.udf.UnitTest
For a Java UDF, read target/site/jacoco/jacoco.csv and inspect LINE, BRANCH, and METHOD counters for the target CPU UDF class and local helper classes. In jacoco.xml, counters appear as <counter type="..."> elements, and source-line misses appear under <sourcefile><line nr="..." mi="..." ci="..." mb="..." cb="...">.
For a Scala UDF, read target/scoverage.xml and inspect statement, branch, and method-level coverage for the target CPU UDF class/object and local helper classes/objects. scoverage XML stores package/class/method statement-rate and branch-rate attributes, and each executable statement has line, branch, and invocation-count attributes.
Use the coverage report as actionable feedback:
If a missed line, statement, branch, or method path cannot or should not be tested, add a clear comment explaining why. Examples include:
Report the relevant counters for the target CPU UDF and local helper classes/objects:
<method> elements.NOTE: JaCoCo and scoverage will not track source-level coverage in external JARs. If the UDF relies on external JAR business logic, make a note of this residual coverage gap.
After the test passes, verify that:
If any quality checks fail, revise the test code and re-run.
Upon successful completion:
<project_root>/<CamelName>/src/test/scala/com/udf/UnitTest.scalaThese outputs are required for Step 2: Convert UDF.
Take nvidia/udf-gen-test from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.