How to Use IEx.pry in Elixir Tests

Elixir’s IEx.pry is a great debugging tool.

It allows you to stop time (“pry”) in the middle of your application in order to inspect the conditions in which your app is currently running.

However, if you’ve ever had to try and use IEx.pry while running your Elixir tests using mix test, you’ve probably encountered a problem.

It won’t actually work.

You may have seen an error similar to this:

Cannot pry #PID<0.474.0> at Example.ProjectsTest ... 
Is an IEx shell running?

I’ll show you the way to use IEx.pry/0 in your Elixir tests and a couple of quick tips to make using IEx.pry in your tests even easier.

Solution

The solution is straightforward. You have to run your mix tests in an interactive elixir session.

How do you do that?

Simply prepend your mix test command with iex -S.

For example, iex -S mix test would run all of your available tests and anywhere you’ve put an IEx.pry the shell will ask you:

Request to pry #PID<0.464.0> at Example.ExampleTest...

....

Allow? [Yn]

Typing Y will drop you into the pry prompt.

Avoiding Timeouts Using IEx.pry in ExUnit

If you are going to be debugging for a while in your pry shell, you should consider adding the the --trace to the test task, i.e. iex -S mix test --trace to avoid timeouts while you are in IEx.pry.

Otherwise, your test process may timeout and crash while you are still debugging using pry. It may raise an ExUnit.TimeoutError after 60 seconds:

 ** (ExUnit.TimeoutError) test timed out after 60000ms. You can change the timeout:
...

Running One Test File or Line Numbers

You can, of course, do the same thing when running a single test file or even a single test.

# Run single test file
iex -S mix test --trace path/to/simple_test.exs

# Run single test
iex -S mix test --trace path/to/simple_test.exs:12

But here’s the deal:

If you are like me, you rarely run your Elixir tests in an interactive shell.

Why?

Because I want to write a test, run it quickly, watch it fail, and then make it pass. Over and over. Iterating quickly. I don’t have time to stop and run an interactive session every time.

Occasionally, however, I run into bugs when making my Elixir tests pass. When this occurs, my debugging workflow works like this:

I’ll try a couple of different things and if none of those reveals the bug, I’ll drop in a IEx.pry somewhere in my test (don’t forget to require IEx).

I do this enough that remembering the correct sequence of commands and typing them out becomes time-consuming and tedious. So, I’ve come up with a few tricks to speed this process up.

Here are two tips that will allow you to do this quickly.

VIM map for IEx Pry

Dropping in a IEx.pry in your code requires that you add both require IEx and IEx.pry to your code.

That is too much typing.

So, to save my hands from carpal tunnel, I have leveraged mappings in Vim. I added this mapping to my .vimrc file:

nmap <leader>r orequire IEx; IEx.pry<esc>

Now, all I have to do is hit “[spacebar] + r” to insert a require IEx; IEx.pry into my test. But, that is only have the problem. I’ll need to run my test again with an IEx shell.

Shell alias for IEx shell tests

Let’s say you’ve added IEx.pry to your test, but now you want to run the same test you just ran again, but this time using pry.

You’ll probably have to go back through your history, find the test you ran, then move your cursor to the beginning of the line, then add iex -S to your mix test command.

Or if you are like me, I’ll often forget to prepend the iex -S in front of my mix test.

Too. Much. Typing.

I came up with simple Bash/Zsh alias that I use all the time and now, you can too.

# Zsh users
alias repry='fc -e - mix\ test=iex\ -S\ mix\ test\ --trace mix\ test'

# Bash users
alias repry='fc -s mix\ test=iex\ -S\ mix\ test\ --trace mix\ test'

What does this alias do? Well, it uses the ‘fc’ command in *nix that searches for the last mix test in your command history and then replaces the mix test with iex -S mix test --trace. This alias works regardless of whether I ran my entire test suite using mix test or ran one test using a specific line number.

Here’s a graphic to pull it all together:

IEx Pry Test

Hope this information was helpful. If you have any questions or have another tip, feel free to leave a comment below.

This post is part of my series of Elixir Tutorials


Freelance Elixir & Ruby on Rails DeveloperHey, I’m Adam. I’m guessing you just read this post from somewhere on the interwebs. Hope you enjoyed it.

You can also follow me on the Twitters at: @DeLongShot