From 3dcf708d3457661d6d22449954c2e3f4cc64fc2c Mon Sep 17 00:00:00 2001 From: Smirnov Oleksandr Date: Sat, 22 Mar 2025 21:08:33 +0200 Subject: [PATCH] refactor: some refactoring of tests (#102) * feat(tests): add utils that does most of tests boilerplate * refactor(tests): rewrite using new thing * refactor(tests): clean up everywhere * refactor(tests): remove boilerplate even further * refactor(tests): soon it will be too far * refactor(tests): some test renaming --- spec/integration/comment_test.lua | 25 ++------- spec/integration/gotests_test.lua | 32 +++--------- spec/integration/iferr_test.lua | 39 +++++--------- spec/integration/impl_test.lua | 52 ++++++------------- spec/integration/struct_tags_test.lua | 74 ++++++++------------------- spec/testutils.lua | 53 ++++++++++++++++++- 6 files changed, 114 insertions(+), 161 deletions(-) diff --git a/spec/integration/comment_test.lua b/spec/integration/comment_test.lua index 9cad5f7..38e7909 100644 --- a/spec/integration/comment_test.lua +++ b/spec/integration/comment_test.lua @@ -1,32 +1,15 @@ local t = require "spec.testutils" - -local child = MiniTest.new_child_neovim() -local T = MiniTest.new_set { - hooks = { - post_once = child.stop, - pre_case = function() - child.restart { "-u", t.mininit_path } - end, - }, -} +local child, T = t.setup "comment" local function do_the_test(fixture, pos) - local tmp = t.tmpfile() - local fixtures = t.get_fixtures("comment/" .. fixture) - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr "%", unpack(pos) }) + local rs = t.setup_test("comment/" .. fixture, child, pos) child.cmd "GoCmt" child.cmd "write" - t.eq(t.readfile(tmp), fixtures.output) - - -- without it all other(not even from this module) tests are falling - t.deletefile(tmp) + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) end -T["comment"] = MiniTest.new_set {} T["comment"]["should add comment to package"] = function() do_the_test("package", { 1, 1 }) end diff --git a/spec/integration/gotests_test.lua b/spec/integration/gotests_test.lua index 57f3142..fcba8a7 100644 --- a/spec/integration/gotests_test.lua +++ b/spec/integration/gotests_test.lua @@ -1,15 +1,5 @@ local t = require "spec.testutils" - -local child = MiniTest.new_child_neovim() -local T = MiniTest.new_set { - hooks = { - post_once = child.stop, - pre_case = function() - child.restart { "-u", t.mininit_path } - end, - }, -} -T["gotests"] = MiniTest.new_set {} +local child, T = t.setup "gotests" --- NOTE: :GoTestAdd is the only place that has actual logic --- All other parts are handled `gotests` itself. @@ -21,27 +11,19 @@ local function read_testfile(fpath) end T["gotests"]["should add test for function under cursor"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "tests/function" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr "%", 3, 6 }) + local rs = t.setup_test("tests/function", child, { 3, 5 }) child.cmd "GoTestAdd" - t.eq(fixtures.output, read_testfile(tmp)) + t.eq(rs.fixtures.output, read_testfile(rs.tmp)) + t.cleanup(rs) end T["gotests"]["should add test for method under cursor"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "tests/method" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr "%", 5, 19 }) + local rs = t.setup_test("tests/method", child, { 5, 19 }) child.cmd "GoTestAdd" - t.eq(fixtures.output, read_testfile(tmp)) + t.eq(rs.fixtures.output, read_testfile(rs.tmp)) + t.cleanup(rs) end return T diff --git a/spec/integration/iferr_test.lua b/spec/integration/iferr_test.lua index 9c5ffdb..fff53ba 100644 --- a/spec/integration/iferr_test.lua +++ b/spec/integration/iferr_test.lua @@ -1,40 +1,27 @@ local t = require "spec.testutils" +local child, T = t.setup "iferr" -local child = MiniTest.new_child_neovim() -local T = MiniTest.new_set { - hooks = { - post_once = child.stop, - pre_case = function() - child.restart { "-u", t.mininit_path } - end, - }, -} -T["iferr"] = MiniTest.new_set {} -T["iferr"]["works"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "iferr/iferr" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr "%", 8, 2, 0 }) +T["iferr"]["should add if != nil {"] = function() + local rs = t.setup_test("iferr/iferr", child, { 8, 2 }) child.cmd "GoIfErr" child.cmd "write" - t.eq(t.readfile(tmp), fixtures.output) + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) end -T["iferr"]["works with custom message"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "iferr/message" - t.writefile(tmp, fixtures.input) +T["iferr"]["should add if err with custom message"] = function() + child.lua [[ + require("gopher").setup { + iferr = { message = 'fmt.Errorf("failed to %w", err)' } + } ]] - child.lua [[ require("gopher").setup { iferr = { message = 'fmt.Errorf("failed to %w", err)' } } ]] - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr "%", 6, 2, 0 }) + local rs = t.setup_test("iferr/message", child, { 6, 2 }) child.cmd "GoIfErr" child.cmd "write" - t.eq(t.readfile(tmp), fixtures.output) + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) end return T diff --git a/spec/integration/impl_test.lua b/spec/integration/impl_test.lua index bbbbf6f..602d2b1 100644 --- a/spec/integration/impl_test.lua +++ b/spec/integration/impl_test.lua @@ -1,55 +1,35 @@ local t = require "spec.testutils" +local child, T = t.setup "impl" -local child = MiniTest.new_child_neovim() -local T = MiniTest.new_set { - hooks = { - post_once = child.stop, - pre_case = function() - child.restart { "-u", t.mininit_path } - end, - }, -} -T["impl"] = MiniTest.new_set {} -T["impl"]["works w io.Writer"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "impl/writer" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr(tmp), 3, 0 }) +T["impl"]["should do impl with 'w io.Writer'"] = function() + local rs = t.setup_test("impl/writer", child, { 3, 0 }) child.cmd "GoImpl w io.Writer" child.cmd "write" -- NOTE: since "impl" won't implement interface if it's already implemented i went with this hack - local rhs = fixtures.output:gsub("Test2", "Test") - t.eq(t.readfile(tmp), rhs) + local rhs = rs.fixtures.output:gsub("Test2", "Test") + t.eq(t.readfile(rs.tmp), rhs) + t.cleanup(rs) end -T["impl"]["works r Read io.Reader"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "impl/reader" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) +T["impl"]["should work with full input, 'r Read io.Reader'"] = function() + local rs = t.setup_test("impl/reader", child) child.cmd "GoImpl r Read io.Reader" child.cmd "write" - local rhs = fixtures.output:gsub("Read2", "Read") - t.eq(t.readfile(tmp), rhs) + local rhs = rs.fixtures.output:gsub("Read2", "Read") + t.eq(t.readfile(rs.tmp), rhs) + t.cleanup(rs) end -T["impl"]["works io.Closer"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "impl/closer" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr(tmp), 3, 6 }) +T["impl"]["should work with minimal input 'io.Closer'"] = function() + local rs = t.setup_test("impl/closer", child, { 3, 6 }) child.cmd "GoImpl io.Closer" child.cmd "write" - local rhs = fixtures.output:gsub("Test2", "Test") - t.eq(t.readfile(tmp), rhs) + local rhs = rs.fixtures.output:gsub("Test2", "Test") + t.eq(t.readfile(rs.tmp), rhs) + t.cleanup(rs) end return T diff --git a/spec/integration/struct_tags_test.lua b/spec/integration/struct_tags_test.lua index 9552339..1c97001 100644 --- a/spec/integration/struct_tags_test.lua +++ b/spec/integration/struct_tags_test.lua @@ -1,65 +1,40 @@ local t = require "spec.testutils" +local child, T = t.setup "struct_tags" -local child = MiniTest.new_child_neovim() -local T = MiniTest.new_set { - hooks = { - post_once = child.stop, - pre_case = function() - child.restart { "-u", t.mininit_path } - end, - }, -} -T["struct_tags"] = MiniTest.new_set {} T["struct_tags"]["should add tag"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "tags/add" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr(tmp), 3, 6, 0 }) + local rs = t.setup_test("tags/add", child, { 3, 6 }) child.cmd "GoTagAdd json" child.cmd "write" - t.eq(t.readfile(tmp), fixtures.output) + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) end T["struct_tags"]["should remove tag"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "tags/remove" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr(tmp), 4, 6, 0 }) + local rs = t.setup_test("tags/remove", child, { 4, 6 }) child.cmd "GoTagRm json" child.cmd "write" - t.eq(t.readfile(tmp), fixtures.output) + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) end T["struct_tags"]["should be able to handle many structs"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "tags/many" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr(tmp), 10, 3, 0 }) + local rs = t.setup_test("tags/many", child, { 10, 3 }) child.cmd "GoTagAdd testing" child.cmd "write" - t.eq(t.readfile(tmp), fixtures.output) + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) end T["struct_tags"]["should clear struct"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "tags/clear" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr(tmp), 3, 1, 0 }) + local rs = t.setup_test("tags/clear", child, { 3, 1 }) child.cmd "GoTagClear" child.cmd "write" - t.eq(t.readfile(tmp), fixtures.output) + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) end T["struct_tags"]["should add more than one tag"] = function() @@ -80,32 +55,27 @@ T["struct_tags"]["should add more than one tag"] = function() child.cmd "write" t.eq(t.readfile(tmp), fixtures.output) + + ---@diagnostic disable-next-line:missing-fields + t.cleanup { tmp = tmp } end T["struct_tags"]["should add tags on var"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "tags/var" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr(tmp), 5, 3 }) + local rs = t.setup_test("tags/var", child, { 5, 6 }) child.cmd "GoTagAdd yaml" child.cmd "write" - t.eq(t.readfile(tmp), fixtures.output) + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) end T["struct_tags"]["should add tags on short declr var"] = function() - local tmp = t.tmpfile() - local fixtures = t.get_fixtures "tags/svar" - t.writefile(tmp, fixtures.input) - - child.cmd("silent edit " .. tmp) - child.fn.setpos(".", { child.fn.bufnr(tmp), 4, 3 }) + local rs = t.setup_test("tags/svar", child, { 4, 3 }) child.cmd "GoTagAdd xml" child.cmd "write" - t.eq(t.readfile(tmp), fixtures.output) + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) end return T diff --git a/spec/testutils.lua b/spec/testutils.lua index 32c19ab..1a31e10 100644 --- a/spec/testutils.lua +++ b/spec/testutils.lua @@ -6,6 +6,23 @@ local testutils = {} testutils.mininit_path = vim.fs.joinpath(base_dir, "scripts", "minimal_init.lua") testutils.fixtures_dir = vim.fs.joinpath(base_dir, "spec/fixtures") +---@param name string +---@return MiniTest.child, table +function testutils.setup(name) + local child = MiniTest.new_child_neovim() + local T = MiniTest.new_set { + hooks = { + post_once = child.stop, + pre_case = function() + child.restart { "-u", testutils.mininit_path } + end, + }, + } + + T[name] = MiniTest.new_set {} + return child, T +end + ---@generic T ---@param a T ---@param b T @@ -36,8 +53,12 @@ function testutils.deletefile(fpath) vim.fn.delete(fpath) end +---@class gopher.TestUtilsFixtures +---@field input string +---@field output string + ---@param fixture string ----@return {input: string, output: string} +---@return gopher.TestUtilsFixtures function testutils.get_fixtures(fixture) return { input = testutils.readfile(vim.fs.joinpath(testutils.fixtures_dir, fixture) .. "_input.go"), @@ -45,4 +66,34 @@ function testutils.get_fixtures(fixture) } end +---@class gopher.TestUtilsSetup +---@field tmp string +---@field fixtures gopher.TestUtilsFixtures + +---@param fixture string +---@param child MiniTest.child +---@param pos? number[] +---@return gopher.TestUtilsSetup +function testutils.setup_test(fixture, child, pos) + local tmp = testutils.tmpfile() + local fixtures = testutils.get_fixtures(fixture) + + testutils.writefile(tmp, fixtures.input) + child.cmd("silent edit " .. tmp) + + if pos then + child.fn.setpos(".", { child.fn.bufnr(tmp), unpack(pos) }) + end + + return { + tmp = tmp, + fixtures = fixtures, + } +end + +---@param inp gopher.TestUtilsSetup +function testutils.cleanup(inp) + testutils.deletefile(inp.tmp) +end + return testutils