Using atom to automate unit tests in C with Ceedling


#1

I’m trying to use Atom to write unit tests with Ceedling and C production code side-by-side. It would be great if any time I save the source code, Atom could automatically execute a shell command (e.g. “ceedling test:all”) to re-check all of the unit tests.

It seems like packages like on-save or save-autorun should be able to do this, but I have been unable to make them work. Any suggestions?


#2

The TextEditor has an onDidSave event, and the global atom.workspace has a TextEditor subscription method. So you can subscribe a function to be run on every TextEditor, and if it’s the right kind of file also subscribe a function to run each time the TextEditor saves.


#3

I got the following onDidSave event working:

atom.workspace.observeTextEditors (editor) ->
editor.onDidSave ->
console.log “Saved! #{editor.getPath()}”

and this successfully prints the “Saved!” message to the atom Console. It’s not obvious how to generalize this to execute a command.

For example, normally, from a platformio-ide-terminal window pointed to the project directory, I execute the command “ceedling test:all”. Can this type of command be executed from the console?

Thanks for your patience… I’m very new to Atom


#4

process-palette can handle this. You can run a command that triggers when you save, but it would be more effective and less dependent on brittle init.coffee code to design a save-and-run workflow step (you can replace ctrl-s situationally or opt for ctrl-shift-s or whatever you want) using settings like the following:

That command will prompt you to save all of the files in your project (you can change it) and then run whatever command you ask it to.


#5

Running the commands is less Atom and more NodeJS (which Atom uses underneath); but yes, it’s possible. Here’s an example

const child_process = require("child_process")

atom.workspace.observeTextEditors(editor => {
  if (!wantToSubscribe(editor)) return
  editor.onDidSave(() => {
    child_process.exec("ceedling test:all", (err, stdout) => {
      if (err) atom.notifications.addError(err)
    })
  })
})

function wantToSubscribe (editor) {
  const scopes = editor.getRootScopeDescriptor().getScopesArray()
  return scopes.length > 0 && scopes[0] === "source.c"
}

process-palette may still be the better choice, but I like having access to the raw JS to fine tune execution and result handling.

Documentation on child_process can be found here


#6

Thanks! I was able to get it working with the following setup:


#7

With this setup, I have the process-palette output streamed to “Panel.” Unfortunately, this panel isn’t an interactive shell, where I could type additional commands. Is it possible to choose the process-palette Target as a separate shell window (e.g. a terminal window provided by the package platformio-ide-terminal)?


#8

It’s possible to make it happen, but to my knowledge nobody has done so yet. platformio-ide-terminal makes available some external methods that allow other packages to use it. This is a core feature of Atom, and all that’s required for process-palette to make use of the terminal service is for it to ask. There’s a chance that I might find the time to implement this myself (I know how, in theory), and if you’re interested in learning more about Atom packages it would be a great exploration.

For now, the most expedient answer would be to have process-palette open a separate window for the command to run in. You can do that on Windows with cmd /c "ceedling test:all && pause", which will spawn a new window, run your program, and give you a “press any key” prompt before it closes itself.