~ views

Prompting OpenAI to create proper RSpec tests & creating a Neovim "Generate RSpec Tests" command


Asking OpenAI to generate RSpec tests for your Rails application can be a powerful way to tackle a large amount of tech debt programmatically, or generate specs — depending on how much you trust your AI’s responses.

I found that by default, OpenAI’s GPT-3.5 and GPT-4 model would generate RSpec request specs using get ":create" or post ":update" instead of proper routes such as api_v1_users_path or api_v1_user_path(user.id). It was slightly tricky to generate a prompt with the exact wording so that OpenAI would only use proper routes. To implement this, I was able to use the Neovim plugin ChatGPT.nvim and create a custom actions file in the default folder where ChatGPT.nvim looks for custom actions: /Users/aaron/.config/nvim/lua/config/gpt/actions/rails.json. I couldn’t find another example of a gpt/actions/*.json file on Github, so I thought I actually might be the first one to do this, at least publicly on GitHub.

I hope you find this helpful!

“RSpec” prompt

Note that the backticks are there to cause AI to finish a “started” markdown code block, and the curly braces are template inputs for the Neovim command.

For the following instructions, do not use \"get :create\" etc and
instead use full routes like \"api_v1_birds_path\". Implement RSpec tests for
the following code.\n\nCode:\n```{{filetype}}\n{{input}}\n```\n\nTests:\n```{{filetype}}

“Missing method” prompt

You are a Ruby on Rails programmer.
Implement the {{method}} method(s) for the following code.\n\nExisting
code:\n```{{filetype}}\n{{input}}\n```\n\n```{{filetype}}

actions.json

{
"WriteRailsMethod": {
"type": "chat",
"opts": {
"template": "You are a Ruby on Rails programmer. Implement the {{method}} method(s) for the following code.\n\nExisting code:\n```{{filetype}}\n{{input}}\n```\n\n```{{filetype}}",
"title": "Write Rails code",
"strategy": "replace",
"params": {
"model": "gpt-3.5-turbo",
"stop": ["```"]
}
},
"args": {
"method": {
"type": "string",
"optional": "true"
}
}
},
"WriteRSpecTests": {
"type": "chat",
"opts": {
"title": "Write RSpec tests",
"template": "For the folllowing instructions, do not use \"get :create\" etc and instead use full routes like \"api_v1_birds_path\". Implement RSpec tests for the following code.\n\nCode:\n```{{filetype}}\n{{input}}\n```\n\nTests:\n```{{filetype}}",
"strategy": "append",
"params": {
"model": "gpt-3.5-turbo",
"stop": ["```"],
"max_tokens": 2048
}
}
},
"WriteRSpecShouldaFactoryBotTests": {
"type": "chat",
"opts": {
"title": "Write RSpec tests",
"template": "For the following command, use shoulda_matchers and assume FactoryBot factories exist for all models. Implement RSpec tests for the following code.\n\nCode:\n```{{filetype}}\n{{input}}\n```\n\nTests:\n```{{filetype}}",
"strategy": "append",
"params": {
"model": "gpt-3.5-turbo",
"stop": ["```"]
}
}
}
}

ChatGPT.nvim command configuration

For lazyvim, configure the keys section of ChatGPT.nvim like so:

{
"jackMort/ChatGPT.nvim",
dependencies = {
"MunifTanjim/nui.nvim",
"nvim-lua/plenary.nvim",
"nvim-telescope/telescope.nvim",
},
cond = function()
local api_key = os.getenv("OPENAI_API_KEY")
return api_key and api_key ~= "" and true or false
end,
opts = {
actions_paths = {
-- Add the path to the actions.json file you've created, mine was called rails.json
actions_config_path .. "/rails.json",
},
api_key_cmd = 'op item get "Neovim ChatGPT" --fields credential',
openai_params = {
model = "gpt-3.5-turbo-16k", -- "gpt-4"
frequency_penalty = 0,
presence_penalty = 0,
max_tokens = 300,
temperature = 0.3,
top_p = 0.3,
n = 1,
-- Lower temperature and top_p can help with repetitive responses and make the AI more creative
-- temperature = 0,
-- top_p = 1,
},
openai_edit_params = {
model = "gpt-3.5-turbo-16k",
-- model = "gpt-4",
frequency_penalty = 0,
presence_penalty = 0,
temperature = 0,
top_p = 1,
n = 1,
},
show_quickfixes_cmd = "Trouble quickfix",
},
cmd = {
"ChatGPT",
"ChatGPTActAs",
"ChatGPTCompleteCode",
"ChatGPTEditWithInstructions",
"ChatGPTRun",
},
-- stylua: ignore
keys = {
-- ... default keys above
{ "<leader>Ra", "<cmd>ChatGPTRun WriteRailsMethod<cr>", desc = "Write Rails code" },
{ "<leader>Rt", "<cmd>ChatGPTRun WriteRSpecTests<cr>", desc = "Write RSpec tests", mode = "v" },
}
}

WriteRailsMethod video

WriteRSpecTests video

Back to top