├── .github └── workflows │ ├── makefile.yml │ └── stylua.yml ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── lua └── neotest-bash │ ├── core │ ├── dir_filter.lua │ ├── file_checker.lua │ ├── positions_discoverer.lua │ ├── result_builder.lua │ ├── root_finder.lua │ └── spec_builder.lua │ ├── init.lua │ └── util │ ├── command_builder.lua │ └── result_list.lua ├── scripts └── test └── tests ├── core ├── dir_filter_spec.lua ├── position_discoverer_spec.lua ├── result_builder_spec.lua └── spec_builder_spec.lua ├── fixtures ├── example_test.sh └── no_test_functions_here_test.sh ├── init_spec.lua └── minimal_init.vim /.github/workflows/makefile.yml: -------------------------------------------------------------------------------- 1 | name: CI / Tests 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | 16 | - name: Setup Maven Action 17 | uses: s4u/setup-maven-action@v1.9.0 18 | 19 | - uses: rhysd/action-setup-vim@v1 20 | with: 21 | neovim: true 22 | 23 | - name: Install dependencies 24 | run: make install 25 | 26 | - name: Run tests 27 | run: make test 28 | -------------------------------------------------------------------------------- /.github/workflows/stylua.yml: -------------------------------------------------------------------------------- 1 | name: Stylua Format 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: JohnnyMorganz/stylua-action@v3 17 | with: 18 | token: ${{ secrets.GITHUB_TOKEN }} 19 | version: latest # NOTE: we recommend pinning to a specific version in case of formatting changes 20 | # CLI arguments 21 | args: --check . 22 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dependencies/neotest"] 2 | path = dependencies/neotest 3 | url = https://github.com/nvim-neotest/neotest 4 | [submodule "dependencies/nvim-treesitter"] 5 | path = dependencies/nvim-treesitter 6 | url = https://github.com/nvim-treesitter/nvim-treesitter.git 7 | [submodule "dependencies/plenary.nvim"] 8 | path = dependencies/plenary.nvim 9 | url = https://github.com/nvim-lua/plenary.nvim.git 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ricardo Casía 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: install test 2 | 3 | test: 4 | ./scripts/test 5 | 6 | test-fail-fast: 7 | ./scripts/test --fail-fast 8 | update: 9 | git submodule update --init --recursive 10 | 11 | install: clean update 12 | nvim --headless -u tests/minimal_init.vim -c "TSInstallSync bash | quit" 13 | 14 | clean: 15 | rm -rf dependencies 16 | 17 | validate: 18 | stylua --check . 19 | 20 | format: 21 | stylua . 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |

neotest-bash

6 |

Neotest adapter for Bash, using bashunit

7 |
8 | 9 | ![image](https://github.com/rcasia/neotest-bash/assets/31012661/e9c1c928-7136-4c29-a17c-cf70c971ca76) 10 | 11 | 12 | ## 🔧 Installation 13 | 14 | It requires [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) 15 | >Make sure you have the bash parser installed. Use `:TSInstall bash` 16 | 17 | [vim-plug](https://github.com/junegunn/vim-plug) 18 | ```vim 19 | Plug 'rcasia/neotest-bash' 20 | ``` 21 | 22 | > **NOTE**: this plugin expects the `bashunit` binary to be in `./lib/bashunit`. 23 | 24 | ## ⚙ Configuration 25 | ```lua 26 | require("neotest").setup({ 27 | adapters = { 28 | require("neotest-bash") 29 | } 30 | }) 31 | ``` 32 | -------------------------------------------------------------------------------- /lua/neotest-bash/core/dir_filter.lua: -------------------------------------------------------------------------------- 1 | DirFilter = {} 2 | 3 | ---Filter directories when searching for test files 4 | ---@async 5 | ---@param name string Name of directory 6 | ---@param rel_path string Path to directory, relative to root 7 | ---@param root string Root directory of project 8 | ---@return boolean 9 | function DirFilter.filter_dir(name, rel_path, root) 10 | return true 11 | end 12 | 13 | return DirFilter 14 | -------------------------------------------------------------------------------- /lua/neotest-bash/core/file_checker.lua: -------------------------------------------------------------------------------- 1 | FileChecker = {} 2 | 3 | ---@async 4 | ---@param file_path string 5 | ---@return boolean 6 | function FileChecker.isTestFile(file_path) 7 | -- test files end with test.sh 8 | return file_path:match("test.sh$") 9 | end 10 | 11 | return FileChecker 12 | -------------------------------------------------------------------------------- /lua/neotest-bash/core/positions_discoverer.lua: -------------------------------------------------------------------------------- 1 | local lib = require("neotest.lib") 2 | 3 | PositionsDiscoverer = {} 4 | 5 | ---Given a file path, parse all the tests within it. 6 | ---@async 7 | ---@param file_path string Absolute file path 8 | ---@return neotest.Tree | nil 9 | function PositionsDiscoverer.discover_positions(file_path) 10 | local query = [[ 11 | (function_definition 12 | name: (word) @test.name 13 | (#match? @test.name "^test_") 14 | ) @test.definition 15 | ]] 16 | 17 | return lib.treesitter.parse_positions(file_path, query) 18 | end 19 | 20 | return PositionsDiscoverer 21 | -------------------------------------------------------------------------------- /lua/neotest-bash/core/result_builder.lua: -------------------------------------------------------------------------------- 1 | local ResultList = require("neotest-bash.util.result_list") 2 | 3 | ResultBuilder = {} 4 | 5 | ---@async 6 | ---@param spec neotest.RunSpec 7 | ---@param result neotest.StrategyResult 8 | ---@param tree neotest.Tree 9 | ---@return table 10 | function ResultBuilder.build_results(spec, result, tree) 11 | local results = ResultList:new() 12 | local is_file = string.match(spec.symbol, "_test.sh") ~= nil 13 | 14 | if not is_file then 15 | for _, node in tree:iter_nodes() do 16 | local node_data = node:data() 17 | if node_data.name == spec.symbol then 18 | results:add_result_with_code(node_data, result.code) 19 | end 20 | end 21 | end 22 | 23 | return results:to_table() 24 | end 25 | 26 | return ResultBuilder 27 | -------------------------------------------------------------------------------- /lua/neotest-bash/core/root_finder.lua: -------------------------------------------------------------------------------- 1 | local lib = require("neotest.lib") 2 | 3 | SpecBuilder = {} 4 | ---Find the project root directory given a current directory to work from. 5 | ---Should no root be found, the adapter can still be used in a non-project context if a test file matches. 6 | ---@async 7 | ---@param dir string @Directory to treat as cwd 8 | ---@return string | nil @Absolute root dir of test suite 9 | function SpecBuilder.findRoot(dir) 10 | local matchers = { 11 | ".git", 12 | "lib", 13 | } 14 | for _, matcher in ipairs(matchers) do 15 | local root = lib.files.match_root_pattern(matcher)(dir) 16 | if root then 17 | return root 18 | end 19 | end 20 | 21 | return nil 22 | end 23 | 24 | return SpecBuilder 25 | -------------------------------------------------------------------------------- /lua/neotest-bash/core/spec_builder.lua: -------------------------------------------------------------------------------- 1 | local root_finder = require("neotest-bash.core.root_finder") 2 | local CommandBuilder = require("neotest-bash.util.command_builder") 3 | 4 | SpecBuilder = { 5 | ---@param args neotest.RunArgs 6 | ---@return nil | neotest.RunSpec | neotest.RunSpec[] 7 | build_spec = function(args) 8 | local tree = args.tree 9 | local tree_data = tree:data() 10 | local path = tree_data.path 11 | local root = root_finder.findRoot(tree_data.path) 12 | 13 | local commands = {} 14 | for _, node in tree:iter_nodes() do 15 | local node_data = node:data() 16 | if node_data.type == "test" then 17 | local command = CommandBuilder:new() 18 | local symbol = node_data.name 19 | 20 | command:filter(symbol) 21 | command:executable("./lib/bashunit") 22 | command:path(path) 23 | 24 | -- add command to list of commands 25 | commands[#commands + 1] = { 26 | command = command:build(), 27 | cwd = root, 28 | symbol = symbol, 29 | } 30 | end 31 | end 32 | 33 | return commands 34 | end, 35 | } 36 | 37 | return SpecBuilder 38 | -------------------------------------------------------------------------------- /lua/neotest-bash/init.lua: -------------------------------------------------------------------------------- 1 | local FileChecker = require("neotest-bash.core.file_checker") 2 | local RootFinder = require("neotest-bash.core.root_finder") 3 | local DirFilter = require("neotest-bash.core.dir_filter") 4 | local PositionsDiscoverer = require("neotest-bash.core.positions_discoverer") 5 | local SpecBuilder = require("neotest-bash.core.spec_builder") 6 | local ResultBuilder = require("neotest-bash.core.result_builder") 7 | 8 | ---@class neotest.Adapter 9 | ---@field name string 10 | NeotestBashAdapter = { name = "neotest-bash" } 11 | 12 | ---Find the project root directory given a current directory to work from. 13 | ---Should no root be found, the adapter can still be used in a non-project context if a test file matches. 14 | ---@async 15 | ---@param dir string @Directory to treat as cwd 16 | ---@return string | nil @Absolute root dir of test suite 17 | function NeotestBashAdapter.root(dir) 18 | return RootFinder.findRoot(dir) 19 | end 20 | 21 | ---Filter directories when searching for test files 22 | ---@async 23 | ---@param name string Name of directory 24 | ---@param rel_path string Path to directory, relative to root 25 | ---@param root string Root directory of project 26 | ---@return boolean 27 | function NeotestBashAdapter.filter_dir(name, rel_path, root) 28 | return DirFilter.filter_dir(name, rel_path, root) 29 | end 30 | 31 | ---@async 32 | ---@param file_path string 33 | ---@return boolean 34 | function NeotestBashAdapter.is_test_file(file_path) 35 | return FileChecker.isTestFile(file_path) 36 | end 37 | 38 | ---Given a file path, parse all the tests within it. 39 | ---@async 40 | ---@param file_path string Absolute file path 41 | ---@return neotest.Tree | nil 42 | function NeotestBashAdapter.discover_positions(file_path) 43 | return PositionsDiscoverer.discover_positions(file_path) 44 | end 45 | 46 | ---@param args neotest.RunArgs 47 | ---@return nil | neotest.RunSpec | neotest.RunSpec[] 48 | function NeotestBashAdapter.build_spec(args) 49 | return SpecBuilder.build_spec(args) 50 | end 51 | 52 | ---@async 53 | ---@param spec neotest.RunSpec 54 | ---@param result neotest.StrategyResult 55 | ---@param tree neotest.Tree 56 | ---@return table 57 | function NeotestBashAdapter.results(spec, result, tree) 58 | return ResultBuilder.build_results(spec, result, tree) 59 | end 60 | 61 | return NeotestBashAdapter 62 | -------------------------------------------------------------------------------- /lua/neotest-bash/util/command_builder.lua: -------------------------------------------------------------------------------- 1 | local CommandBuilder = { 2 | _executable = "", 3 | _path = "", 4 | _filter = "", 5 | 6 | --- @return CommandBuilder 7 | new = function(self) 8 | local o = o or {} 9 | setmetatable(o, self) 10 | self.__index = self 11 | return o 12 | end, 13 | 14 | --- @param executable string @executable bashunit executable binary 15 | executable = function(self, executable) 16 | self._executable = executable 17 | return self 18 | end, 19 | 20 | --- @param path string @path to test file 21 | path = function(self, path) 22 | self._path = path 23 | return self 24 | end, 25 | 26 | ---@param filter string @filter by test name 27 | filter = function(self, filter) 28 | self._filter = filter 29 | return self 30 | end, 31 | 32 | --- @return string @command to run 33 | build = function(self) 34 | if self._filter == "" then 35 | return self._executable .. " " .. self._path 36 | end 37 | return self._executable .. " " .. self._path .. " --filter " .. self._filter 38 | end, 39 | } 40 | 41 | return CommandBuilder 42 | -------------------------------------------------------------------------------- /lua/neotest-bash/util/result_list.lua: -------------------------------------------------------------------------------- 1 | ExitCode = { 2 | Success = 0, 3 | } 4 | 5 | local ResultList = { 6 | -- needs to be static 7 | _results = {}, 8 | 9 | new = function(self) 10 | self.__index = self 11 | return setmetatable({}, self) 12 | end, 13 | 14 | add_successful_result = function(self, result) 15 | self._results[result.id] = { 16 | status = "passed", 17 | } 18 | end, 19 | 20 | add_failed_result = function(self, result) 21 | self._results[result.id] = { 22 | status = "failed", 23 | } 24 | end, 25 | 26 | add_skipped_result = function(self, result) 27 | self._results[result.id] = { 28 | status = "skipped", 29 | } 30 | end, 31 | 32 | add_result_with_code = function(self, result, code) 33 | if code == ExitCode.Success then 34 | self:add_successful_result(result) 35 | else 36 | self:add_failed_result(result) 37 | end 38 | end, 39 | 40 | -- @returns boolean whether all results passed 41 | are_all_passed = function(self) 42 | for id, v in pairs(self._results) do 43 | if v.status ~= "passed" then 44 | return false 45 | end 46 | end 47 | return true 48 | end, 49 | 50 | --- @returns table copy of results 51 | to_table = function(self) 52 | -- makes a copy 53 | local results = {} 54 | for id, v in pairs(self._results) do 55 | results[id] = v 56 | end 57 | 58 | return results 59 | end, 60 | } 61 | 62 | return ResultList 63 | -------------------------------------------------------------------------------- /scripts/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | tempfile=$(mktemp) 5 | 6 | 7 | if [[ -n $1 ]] && [[ $1 == "--fail-fast" ]]; then 8 | echo "Running tests with --fail-fast" 9 | nvim --headless --noplugin -u tests/minimal_init.vim \ 10 | -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/minimal_init.vim', sequential = true, keep_going = false}" | tee "${tempfile}" 11 | elif [[ -n $1 ]]; then 12 | nvim --headless --noplugin -u tests/minimal_init.vim -c "PlenaryBustedFile $1" | tee "${tempfile}" 13 | else 14 | nvim --headless --noplugin -u tests/minimal_init.vim \ 15 | -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/minimal_init.vim'}" | tee "${tempfile}" 16 | fi 17 | 18 | # Plenary doesn't emit exit code 1 when tests have errors during setup 19 | errors=$(sed 's/\x1b\[[0-9;]*m//g' "${tempfile}" | awk '/(Errors|Failed) :/ {print $3}' | grep -v '0') 20 | 21 | rm "${tempfile}" 22 | 23 | if [[ -n $errors ]]; then 24 | echo "Tests failed" 25 | exit 1 26 | fi 27 | 28 | exit 0 29 | -------------------------------------------------------------------------------- /tests/core/dir_filter_spec.lua: -------------------------------------------------------------------------------- 1 | ---@diagnostic disable: undefined-global 2 | 3 | local plugin = require("neotest-bash") 4 | 5 | describe("dir_filter", function() 6 | it("should not filter dirs", function() 7 | local name = "tests" 8 | local rel_path = "tests" 9 | local root = root 10 | local result = plugin.filter_dir(name, rel_path, root) 11 | 12 | assert.is_true(result) 13 | end) 14 | end) 15 | -------------------------------------------------------------------------------- /tests/core/position_discoverer_spec.lua: -------------------------------------------------------------------------------- 1 | local plugin = require("neotest-bash") 2 | local async = require("nio").tests 3 | 4 | local current_dir = vim.fn.expand("%:p:h") 5 | 6 | describe("PositionDiscoverer", function() 7 | async.it("discovers test with prefix 'test_' ", function() 8 | --given 9 | local filename = current_dir .. "/tests/fixtures/example_test.sh" 10 | 11 | --when 12 | local tree = plugin.discover_positions(filename) 13 | 14 | --then 15 | -- local test_file_node = tree:to_list()[1] 16 | local test_function_node = tree:to_list()[2][1] 17 | local test_function_node_2 = tree:to_list()[3][1] 18 | local actual_test_name = test_function_node.name 19 | local actual_test_name_2 = test_function_node_2.name 20 | 21 | assert.are.equal("test_sum_1_plus_1", actual_test_name) 22 | assert.are.equal("test_sum_2_plus_2", actual_test_name_2) 23 | 24 | -- there is only one test function 25 | assert.are.equal(2, #tree:children()) 26 | end) 27 | 28 | async.it("ignores functions that are not tests", function() 29 | --given 30 | local filename = current_dir .. "/tests/fixtures/no_test_functions_here_test.sh" 31 | 32 | --when 33 | local tree = plugin.discover_positions(filename) 34 | 35 | --then 36 | local children = tree:children() 37 | 38 | assert.are.equal(0, #children) 39 | end) 40 | end) 41 | -------------------------------------------------------------------------------- /tests/core/result_builder_spec.lua: -------------------------------------------------------------------------------- 1 | ---@diagnostic disable: undefined-global 2 | 3 | local plugin = require("neotest-bash") 4 | local async = require("nio").tests 5 | 6 | local function read_tree_from_file(file_path) 7 | return plugin.discover_positions(file_path) 8 | end 9 | 10 | describe("result_builder", function() 11 | async.it("should build results for successful tests", function() 12 | -- given 13 | local tree = read_tree_from_file("tests/fixtures/example_test.sh") 14 | local result = { 15 | code = 0, 16 | } 17 | local spec = { 18 | symbol = "example_test.sh", 19 | } 20 | 21 | -- when 22 | local results = plugin.results(spec, result, tree) 23 | 24 | -- then 25 | -- assert all tests passed by checking result table 26 | for _, res in pairs(results) do 27 | assert.are.equal("passed", res.status) 28 | end 29 | end) 30 | 31 | async.it("should build results for failed tests", function() 32 | -- given 33 | local tree = read_tree_from_file("tests/fixtures/example_test.sh") 34 | local result = { 35 | code = 1, 36 | } 37 | local spec = { 38 | symbol = "example_test.sh", 39 | } 40 | 41 | -- when 42 | local results = plugin.results(spec, result, tree) 43 | 44 | -- then 45 | -- assert all tests failed by checking result table 46 | for _, res in pairs(results) do 47 | assert.are.equal("failed", res.status) 48 | end 49 | end) 50 | end) 51 | -------------------------------------------------------------------------------- /tests/core/spec_builder_spec.lua: -------------------------------------------------------------------------------- 1 | ---@diagnostic disable: undefined-global 2 | local async = require("nio").tests 3 | 4 | local plugin = require("neotest-bash") 5 | local root_finder = require("neotest-bash.core.root_finder") 6 | 7 | --- mock root finder 8 | local function mock_root_finder(mocked_root) 9 | root_finder.findRoot = function() 10 | return mocked_root 11 | end 12 | end 13 | 14 | local function mock_args_tree(data) 15 | return { 16 | tree = { 17 | data = function() 18 | return data 19 | end, 20 | }, 21 | extra_args = {}, 22 | } 23 | end 24 | 25 | describe("spec_builder", function() 26 | pending("should run command for a test file", function() 27 | -- given 28 | local args = mock_args_tree({ 29 | name = "test.sh", 30 | path = "/home/user/project/test.sh", 31 | type = "file", 32 | }) 33 | 34 | local mocked_root = "/home/user/mocked/directory/" 35 | mock_root_finder(mocked_root) 36 | 37 | -- when 38 | local result = plugin.build_spec(args) 39 | 40 | -- then 41 | local expected_spec = { 42 | command = "./lib/bashunit /home/user/project/test.sh", 43 | cwd = mocked_root, 44 | symbol = "test.sh", 45 | } 46 | 47 | assert.are.same(expected_spec, result) 48 | end) 49 | 50 | pending("should run command for a test function inside a test file", function() 51 | -- given 52 | local args = mock_args_tree({ 53 | name = "test_it_works", 54 | path = "/home/user/project/test.sh", 55 | type = "test", 56 | }) 57 | 58 | local mocked_root = "/home/user/mocked/directory/" 59 | mock_root_finder(mocked_root) 60 | 61 | -- when 62 | local result = plugin.build_spec(args) 63 | 64 | -- then 65 | local expected_spec = { 66 | command = "./lib/bashunit /home/user/project/test.sh --filter test_it_works", 67 | cwd = mocked_root, 68 | symbol = "test_it_works", 69 | } 70 | 71 | assert.are.same(expected_spec, result) 72 | end) 73 | 74 | async.it("should run a list of commands from a tree node selection", function() 75 | -- given 76 | -- 77 | local path = "tests/fixtures/example_test.sh" 78 | local tree = plugin.discover_positions(path) 79 | local args = { tree = tree } 80 | local mocked_root = "/home/user/mocked/directory/" 81 | mock_root_finder(mocked_root) 82 | 83 | -- when 84 | local result = plugin.build_spec(args) 85 | 86 | -- then 87 | local expected_spec = { 88 | { 89 | command = "./lib/bashunit tests/fixtures/example_test.sh --filter test_sum_1_plus_1", 90 | cwd = mocked_root, 91 | symbol = "test_sum_1_plus_1", 92 | }, 93 | { 94 | command = "./lib/bashunit tests/fixtures/example_test.sh --filter test_sum_2_plus_2", 95 | cwd = mocked_root, 96 | symbol = "test_sum_2_plus_2", 97 | }, 98 | } 99 | 100 | assert.are.same(expected_spec, result) 101 | end) 102 | end) 103 | -------------------------------------------------------------------------------- /tests/fixtures/example_test.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | test_sum_1_plus_1() { 4 | assert_equals 2 $(1 + 1) 5 | } 6 | 7 | function test_sum_2_plus_2() { 8 | assert_equals 4 $(2 + 2) 9 | } 10 | 11 | this_is_not_a_test() { 12 | echo "This is not a test" 13 | } 14 | 15 | -------------------------------------------------------------------------------- /tests/fixtures/no_test_functions_here_test.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | this_is_not_a_test() { 4 | echo "This is not a test" 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/init_spec.lua: -------------------------------------------------------------------------------- 1 | describe("NeotestBash plugin", function() 2 | it("loads", function() 3 | local neotest_bash = require("neotest-bash") 4 | end) 5 | end) 6 | -------------------------------------------------------------------------------- /tests/minimal_init.vim: -------------------------------------------------------------------------------- 1 | set runtimepath+=. 2 | set runtimepath+=./dependencies/plenary.nvim 3 | set runtimepath+=./dependencies/neotest 4 | set runtimepath+=./dependencies/nvim-treesitter 5 | runtime! plugin/plenary.vim 6 | --------------------------------------------------------------------------------