Skip to content

2. Configuration

Oleksii Lisikh edited this page Feb 27, 2026 · 3 revisions

Configuration

This page documents all configuration options for neotest-scala.

Quick Reference

require("neotest").setup({
  adapters = {
    require("neotest-scala")({
      -- Static args passed to sbt
      args = { "--no-colors" },
      
      -- Optional file logger settings
      logging = {
        enabled = true,
        level = "info", -- debug | info | warn | error
      },
      
      -- Or dynamic args based on context
      args = function(context)
        -- context contains: path, framework, project_name, build_target_info
        return { "-v" }
      end,
    })
  }
})

Configuration Options

args

Arguments to pass to sbt when running tests.

Type Default Description
string[] or function {} Extra args for the sbt command

Static Args

Pass a fixed list of arguments:

require("neotest-scala")({
  args = { "--no-colors", "-v" }
})

Dynamic Args

Use a function for context-aware arguments:

require("neotest-scala")({
  args = function(context)
    -- context is a table with:
    --   path              - full path to the test file
    --   framework         - detected test library name (e.g., "munit", "scalatest")
    --   project_name      - sbt project name
    --   build_target_info - Metals build target information
    
    -- Example: verbose output for zio-test only
    if context.framework == "zio-test" then
      return { "-v" }
    end
    
    return {}
  end
})

Context Fields

Field Type Description
path string Full path to the project root
framework string Detected test library: "utest", "munit", "scalatest", "specs2", or "zio-test"
project_name string sbt project name (without -test suffix)
build_target_info table Raw Metals build target data

logging

Controls file-based plugin logging.

Field Type Default Description
enabled boolean true Enables/disables logging
level string "info" Minimum level: debug, info, warn, error

Logs are written to /tmp/neotest-scala/log/<YYYY-MM-DD>.log. Each entry includes the module logger name (for example adapter, results, metals).

require("neotest-scala")({
  logging = {
    enabled = true,
    level = "debug",
  }
})

build_spec payload logging is emitted at INFO level.


How Test Commands Are Built

neotest-scala builds sbt commands based on what you're running:

Run All Tests in Project

sbt <project>/test

Run Tests in a Specific Class

sbt <project>/testOnly com.example.MyTestSuite

Run a Single Test

The command varies by test library:

Library Single Test Syntax
ScalaTest sbt <project>/testOnly com.example.MyTest -- -z "test name"
munit sbt <project>/testOnly -- "com.example.MyTestSuite.test name" (bloop falls back to suite scope)
utest sbt <project>/testOnly -- "com.example.MyTestSuite.test name" (interpolated names fall back to suite scope)
zio-test sbt <project>/testOnly com.example.MyTest -- -t "test name"
specs2 sbt <project>/testOnly com.example.MyTest (single test limited)

Note: specs2 has limited support for running individual tests due to framework limitations.


Test File Detection

Files are detected as test files based on naming conventions:

-- Files matching these patterns (case-insensitive) are test files:
"*test*.scala"   -- e.g., MyTest.scala, TestSpec.scala
"*spec*.scala"   -- e.g., UserSpec.scala, SpecHelper.scala (also matched)
"*suite*.scala"  -- e.g., TestSuite.scala

Test Discovery with Treesitter

neotest-scala uses Treesitter queries to discover tests. The following patterns are detected:

Object/Class Definitions

// Detected as test namespaces
object MyTestSuite extends TestSuite { ... }
class MySpec extends AnyFunSuite { ... }

Test Definitions

// munit, utest, zio-test, ScalaTest FunSuite
test("my test name") { ... }

// zio-test suiteAll
suiteAll("my suite") { ... }

// ScalaTest FreeSpec, specs2 mutable.Specification
"my test name" - { ... }
"my test name" in { ... }
"my test name" should { ... }
"my test name" can { ... }
"my test name" >> { ... }

Framework Auto-Detection

The adapter automatically detects which test library is in use by examining the project's classpath via Metals:

  1. Queries Metals for build target information
  2. Scans classpath JARs for known test library patterns
  3. Falls back to ScalaTest if no library detected
Library Detection Pattern
specs2 specs2-core_*.jar
munit munit_*.jar
scalatest scalatest_*.jar
utest utest_*.jar
zio-test zio-test_*.jar

Neotest Strategy Configuration

Integrated Strategy

Run tests in a terminal buffer:

require('neotest').run.run({ strategy = 'integrated' })

DAP Strategy (Debugging)

Run tests with the debugger:

require('neotest').run.run({ strategy = 'dap' })

Nearest-test DAP always launches file-level debug for reliability.

See Debugging for full debugging setup.


Complete Configuration Example

require("neotest").setup({
  adapters = {
    require("neotest-scala")({
      args = function(context)
        -- Verbose output for CI
        if os.getenv("CI") then
          return { "-v", "--no-colors" }
        end
        
        -- Different args by framework
        if context.framework == "specs2" then
          return { "--sequential" }
        end
        
        return {}
      end,
    })
  },
  -- Neotest general config
  status = { virtual_text = true },
  output = { open_on_run = true },
  summary = {
    open = "botright vsplit | vertical resize 40"
  },
})

Related Pages

Clone this wiki locally