From Pseudocode to Tests
Tags: tdd, testing, rails, ruby
Published: 2020-11-06 20:27:17

Test Driven Development. Known by all, followed by...definitely *not* all.  I'll admit it, I'm guilty of not following it as a newer developer, but in an effort to stop myself from getting into bad habits from the start, I've made the commitment to becoming more conscientious about testing.  In doing this, I've learned that it really doesn't have to be so time consuming and it isn't as much added work as it initially seems.  In fact, when I use it from the start of a project, it flows quite naturally with my planning-to-coding process.

###My Process Breakdown
For me, my process of building a new app begins with planning out my work in detail using flowcharts and component mapping.  I decide what components I need, what data they'll contain, how they interact, etc.  This is time-consuming, but I've learned it drastically reduces the level of re-work (and frustration) during development.  Here's an example from a recent project:

![Site Planning Diagram](https://dev-to-uploads.s3.amazonaws.com/i/0fovle6h1bm2t8w5q0s7.png)
This would also involve creating user stories, similar to these.  These three stories are also what I'll be using as examples in a moment:

| As a | Pain Point (I need to) | Description (How?) |
|:---:|:---:|:---:|
| User | Register as a new user | Devise Registration |
| User | Log into my account | Devise Authentication |
| User | View my past Orders | navigate to /users/:user_id/orders route from profile |

Once I have my project mapped out, I essentially convert the plans into pseudocode in order to 'get something on the page.' Then I work through each pseudo-function to build it out into actual code.  But if you look at unit testing languages like Jest or Rspec, they sort of resemble pseudocode.  So what I've done is evolved my pseudo-code step into writing out unit tests instead.  Only when they are complete do I begin building out the app functionality to get them to pass.  It takes some getting used to (I'm still working on it), but I'm confident it will be well worth it in the end.

<figure>
<img src="https://dev-to-uploads.s3.amazonaws.com/i/jajkapwlrif82arr9wud.png" alt="Full Site Planning Workflow">
<figcaption>Full Site Planning Workflow</figcaption>
</figure>

Below, you can see the before and after.  I'm using Ruby (Rails) for code and Minitest for testing.

###The Pseudocode (red box)
```
# receive POST '/users/register' request with user_params: name, email, password
def register
  #  user = create new User instance
  #  check validations
  #  if user passes validations
    #  save user to database
    #  return user details
  #  else
    #  do not save user to database
    #  return failure message
  #  end
end

# receive POST '/users/signin' request with user_params: email, password
def login
  #  user = find User in database by params[:email]
  #  check params[:password] matches user.password
  #  if authenticated
    #  set current_user = user
    #  return user details
  #  else
    #  return failure message
  #  end
end

# receive GET '/orders' request
def past_orders
  #  current_user.orders.all
  #  return order details as JSON array
end
```

###The Tests (green box)
```
test 'can register valid user' do
  user = User.new(name: "Fake Guy", email: "test@example.com", password: "password")
  assert user.valid?, "user not valid"
end

test "user can log in with credentials" do
  users = [User.new(email: "test@example.com", password: "password")]
  user = users.find{|u| u.email == "test@example.com"}
  assert_equal user.password, "password"
end

test "user can see past orders" do
  user = User.new(name: "Fake Guy", email: "test@example.com", password: "password")
  one = Order.new(user_id: 1, Num_Items: 2, Total_Price: 400)
  two = Order.new(user_id: 1, Num_Items: 1, Total_Price: 200)
  three = Order.new(user_id: 2, Num_Items: 4, Total_Price: 800)
  assert_equal 2, user.orders.size
end
```

See, not too bad.  The tests require a little bit more thought than pseudo-code, but they are also much more useful while you're writing the real code, and are *even more* useful down the line when you need to make changes.  Hope this helps provide motivation for someone out there who is like me and struggling with "how can I find time to squeeze in testing with everything else going on?"