1. Open Source Vlog - Where Do We Even Start? 2. Open Source Vlog - Housekeeping and Merging Pull Requests 3. Open Source Vlog - Setting Up Rspec 4. Open Source Vlog - Setting Up For The Future 5. Open Source Vlog - Just Deleting Things 6. Open Source Vlog - Building A Calendar From Scratch 7. Open Source Vlog - Refactoring Our Calendar 8. Open Source Vlog - Filtering Events 9. Open Source Vlog - Finding a balance between Ruby and ERB 10. Open Source Vlog - Simple And Clean RubyGem With Rails Engines 11. Elegant Refactoring for Week and Month Calendars 12. Open Source Vlog - Refactoring Events And Uploading Version 2.0 13. Open Source Vlog - Rails Generators 14. Open Source Vlog - Sorting Calendar Events 15. Open Source Vlog - Writing Rspec Tests 16. Upgrading simple_calendar for Rails 5 17. Recurring events with the ice_cube gem 18. Adding Exceptions To Recurring Events
Episode 64 · June 26, 2015
Here's how to setup Rspec for an open source project
What's up guys? It's day three of the vlog, the first day was the set up, figuring out what we should contribute to, decided to work on simple_calendar. Yesterday, we went through the open tickets, the issues and the pull requests that I had open, cleaned up a bunch of those, and then I was really happy to wake up to three new ones, so we've got Rodrigo and Maclover7 working on simple_calendar which is really really fun. So what we're going to do is look at what has happened in the last 24 hours, I guess since last time since I did the vlog and see what's up. So I've noticed that one of them, Rodrigo wants to add that to Travis CI to the app so that we can have this in the README, you may have seen this on other GitHub repositories, either down here in the pull request area, it will show if the pull requests have passed the tests, and it can be run on Travis CI which is sweet, so it will automatically run the tests when you push something, so that is really cool. I definitely recommend using that. Travis CI is one of those ones that is used the most. Let's pull up their website here. It's probably one of the most used open source projects. There's Circle CI, and I use that at work, actually, and Travis is awesome, they're all really great. that anything to encourage you to run your tests more often is a good thing. We're going to take a look at this then and see what we can do. First we'll probably need to get Rspecs set up and installed, so that we actually have tests to run because Travis CI or any of these continuous integrations servers are pretty much useless without it. So let's see what we've got here. We all know that we break stuff, let's take a look at his example. Awesome, this is his own personal website and the Rspec tests running on Circle CI, awesome.
We need to install the Travis gem, I need to login to Travis, the GitHub API key, which I might have to edit out by the way, I don't want to give that out and init travis in the repository. Now let's take a look at the other two pull requests we've got in the last 24 hours, so Rodrigo added Rspec with documentation format flag which is awesome. Here's the file that he's added. So we've got three changed files, this is an Rspec config file, it basically just says what are the default options we should have of color, he added the format documentation in there, so that will print out the Rspec tests in the documentation, so you can look that up if you want, but I wouldn't worry about it. It's just a different way of displaying the tests output, and it's a spec/simle_calendar_spec.rb is all the test we have the regular spec helper that we're going to require which is added down here below,
describe SimpleCalendar module, it has a version number.
it requires simple_calendar and that is successful. It's a great test to have to make sure that works appropriately, although I wonder if that works, because we've already describing simple_calendar, so the assumption is that it exists already, that it's already required in the library... I'm not quite sure, we may need to look into that. I don't know if these tests are doing exactly what the intention is, so we may have to dive into those, but moving on next, it looks like the default generated our spec helper file which is great, we have all the comments of various options, the explanations and what can be configured in here. This looks good, the only thing I want to make sure that we take a look at here is that these
requires simple_calendar and this
require 'rails' tests actually do what we want them to do. I'm actually going to go ahead and merge this one. I think it's good, and we can work on those tests as well. So the same as before, I'm just going to do the instructions here at the bottom to make sure that we grab this from the command line. It's good practice to be in, we want to use Git from the command line as much as possible. Create the new branch, pull the changes down into that branch, we can save that. That is what we expected, and the same thing as before, you check out the master branch. You merge those, and then you push to 'origin master'.
We got a rejection here, so this is one of those times where we've done something that's different where the master branch on GitHub is different than what we have locally, so we can look at our logs here. This was merging that branch, and this was merging his into the Rspec branch. So let's take a look and see what GitHub has for simple calendar as the last commit here. So we have this commit with the
b2ce as the hash. If we run Git log we should see that here at the bottom, or at some point in here. We don't have this latest commit that we pushed up previously. So we actually need to get
pull origin master to make sure that we get that latest code from GitHub, that is one of those times where you push some stuff up to GitHub, maybe you've merged with the "Merge" button on the GitHub's pull request UI or something, and there's commits on GitHub that aren't on your local machine, and you need to pull those into your local machine. Just one of those things that definitely happens more often when you're working on two computers, or you're working with two people or more, you end up having to do a lot of merging, and it's good to get familiar with all of that, especially doing it manually in the commands rather than doing it with pull requests from GitHub, because there's a lot of stuff you actually need to do when you're working with a team, always good to do that by hand if you can. So cool, that merge pulled down the code from GitHub, the latest version and merged successfully so now we actually can push up all of those merges of that pull request into GitHub, so now you should see that the pull request is closed, and go to this. It's been successfully merged, thank you Rodrigo, that was awesome. Now let's take a look at that next one.
"Added RSpec for testing and removed RubyForge project link". Everybody is working on the same thing, which is another interesting thing, a lot of people will do very similar next steps, and so one of these pieces managing open source is going to be managing other people trying to do the same thing, so we need to look at all of the things that are going on, and make sure that we handle those appropriately. One thing that's interesting here is that here, in the gem spec change that Maclover7 put in, he removed the RubyForge project. I don't really remember what RubyForge was for, I don't remember really being around and having ever to use it. So it shut down in 2013, I don't think I've ever used id, it's just kind of old, so it's deprecated, removing this from the gem's stuff makes sense, and another thing here is that he added the development dependency of RSpec, which is something. I don't think we actually have in the other one, and so that is super useful. When you write your gem spec, you want to make sure that you add your dependencies for running this in someone else's project, but there's development dependencies, and those are used for when you're doing development, so if you run your tests with Rspec, you need to make sure that you add Rspec into your gemspec file. That is certainly a line of code that we should add. shoulda is another dependency that he's added, which could be good. If you don't know Rspec shoulda, you can take a look at that. Thoughbot made it, they do a lot of awesome stuff. It allows you to say should and reference objects doing that, which is pretty cool, so you can have this, so when you're describing posts you can say the post should belong to a user, and it will automatically know how to translate the reference there, so it knows what it's talking about, so it reads a little bit more like english, which I think it's great. It depends on how we end up writing our tests, we can use it, we don't have to use it. There's other Rspec syntax for this, this is something that a lot of people do use, and I believe that we use it in some of our tests at work as well. Here's a little bit different, the spec helper file is different. spec_helper.rb is usually what it is that is the default, so usually you have a spec helper file an it should look like this. I think generally when you create a new Rspec project, it's named differently, you can tell that you set it up manually, which is cool. He's got a much lighter way config, it's a lot easier to read, let's see if there's any differences. We've got Rspec configure, so here actually there's some loading of paths and directories and requires before hand, and then Rspec configure block, so
fail_fast = true,
filter_run :focused => true. fail_fast means that when the first test fails, you want to kill the running the test suite, because a test failed. Sometimes that's super useful, other times you want to count how many tests have failed, it's kind of a personal preference, it's nice to know if the test suite failed and able to jump in immediately. I personally like to not fail_fast, so I can see if there's consistent errors throughout the test suite. Sometimes that tells you that if you get the same error, that you're doing duplicates in your tests, so it could be a sign that you're writing tests in your code that are duplicated and you could remove some of those tests, or rearrange them, so that they test smaller pieces rather than duplicating stuff making the test suite slow. Merit to both of those, fail_fast is awesome if you've already written a really great test suite and you know exactly what you're doing. Always a good option.
Then, he added spec/simple_calendar_spec.rb, this one is interesting. It's very similar to the simple_calendar that we have here, and this one tests that it has a version number and so does this one. What's interesting is that this one expects the version number to not be nil, and this one expects it to be equal to a specific version number string, now there's a big difference between those and the robustness of the tests. This simple_calendar equal to a string is great because it's very exacting, but it actually very hard for us to continue maintaining because well, when I release the next version, it's going to be not 1.1.10, it's going to be 1.1.11 or it might be 1.2.0, so this test is not actually as useful as you might expect, it's good right now, but it makes more work for us to maintain in the future, and I would go with expect this variable to not be nil. This is actually what I would recommend keeping around, and again, if you could reference simple_calendar version, then requiring the gem is maybe not going to test anything, because clearly it's already loaded for this test to actually run and pass. I think these two tests we actually might want to remove, as long as we can get to this point. If our test suite runs at all, we have to assume that simple_calendar loaded, because that's what we're testing, and probably our dependency is loaded which is rails. If we can go our test suite to run, you can kind of assume that this is loaded properly so, I would actually delete those two and just keep this one around and not use this "has a version number" test. We also have a spec/support/railtie.rb This is a simple_calendar rails railtie initializer object. Maybe this is setting up for testing the railtie, so if you look in lib/simple_calendar/railtie.rb we have a railtie, and all of this does is it inherits from rails's railtie functionality, and railtie just says: Hey, when you wrote this gem, we're going to add this initializer, and it's code that rails will run when you include this gem. When you set up your rails app, and it gets configured and loaded, so this really just says: All those view helpers you've created for the calendar, month calendar and week calendar, go ahead and add those into the view helpers module. Include that in there so that they're available throughout the rails app. That's really all that does, and I'm going to guess that the intention is for this to test that railtie, I've actually never tested that railtie before so maybe we should take a look at checking out some other people's example's on that.
Draper is a gem that has a railtie, and it's similar. It's a view decorator kind of thing, and maybe they have a spec for this, so let's see if we can find anything. Yeah, we may just want to do a regular old integration spec, let's see if we can find anything. Theres a
require 'support/shared_examples/view_helpers', and if we go there, we might be able to see in here what it's doing, and maybe we can reverse engineer our own way of testing that. Maybe we don't really need to be super worried about it either. It could be something as simple as saying: Once this loads, ActionView is going to send that into view helpers, maybe we can just access ActionView base, and see if the week_calendar method exists. Maybe that's all we need to do and as long as this method gets called, maybe that's how we can test that. Maybe we can get away with something simpler but we'll have to wait an see. Or find someone who does know how to do that properly. I think we can just take this railtie code here and leave a comment for Maclover7 and ask him how does this help us, test the railti, because we can assume that that's what it's for. It also might be overriding the rails railtie, so that it's like a stub that we can access, so we'll find out. Let's ask him "Does this help us test the railtie inclusion in a Rails app?", we'll find out. So we've decided that we want to keep at least the other version of this spec specifically, I think we'll just stick with the default for the spec for now, but something we definitely should use is the add_developement_dependency Rspeec, we definitely need that in our gem. If you were to run our Rspec, so Rspec installed on this machine outside of this gem for other gems. Plenty of other gems use our rspec to test it, you're going to notice that you're going to get an error, and that's our rspec-core is not part of the bundle, so you add it to the gemfile so you actually need to go and add this into the gemspec in order to run rspec like that, so rather than pasting in the error, we should paste in this add development dependency. This is certainly useful, and basically required for us to move forward here too. Now, if we run
bundle install that will install rails and the dependencies like rspec. Now if we run our rspec, it should run the tests and it does, and that's awesome. We've made great progress, we've got the setup got through two great pull requests that we got yesterday, so now let's wrap this up today and let's make a commit
git commit -m "Added rspec to the gemspec as a dev dependency" and then let's make a separate commit for removing those requires, because I'm pretty sure that the requires seem to already be done, especially if we required rails at the top of the file, I think that the require rails test is kind of duplicating things, and maybe doesn't test exactly what we want. Let's just keep it as simple as this and make this commit to clean up those specs, and please let me know in the comments if we can make that better, if these tests actually do work and I'm just misunderstanding things. Let's say
git commit -m "Remove require tests" That's a terrible commit, but I'm tired and we'll leave it at that. Not the way to put your commit messages but sometimes you have to.
We got through these two pull requests, I think that is set up correctly, and the last thing I'd like to do is wait to see what we find out about this comment on the railtie, and the last thing we'll do is add in the travis.yml file so we can get the Travis CI into our gem, so let's go do that. Since we've got a ruby gem here and we're not going to use the rake command for much other than running specs, let's actually configure this so that when you type
rake, it will run rspec instead. So rather than having to type in rspec and use that every time, we should be able to type in "rake" and make rspec the default here.
Let's google "rake rspec default" and see what we can find. If you paste this code in, this will add the rake tasks from rspec to your application, so when you run
rake spec, this will run the tests which is awesome, it loads up all of the directories and handles that for you, and that's good, but then, this isn't actually setting the default rake tasks, so we can say
task default: :spec, now if we run rake, this should just run into running
rake spec for us. That is all we need to do to make rake automatically run our spec tests by default. This is what is pretty common to do anyways for a gem, probably only really need to run your tests like that. There's not really any other things aside from the regular bundler gem tasks, which are releasing the gem and updating or releasing new versions, it's pretty much it. This is useful for us to add, and then that also allows us when we're building the Travis CI set up, that it can use the default
rake command and execute the code. Otherwise you would have to say: Here's the specific command to run the tests, you would have to override it and it's not a big deal for us to override it, but also it makes sense to just type
rake to run our tests. We can basically crete this .travis.yml file now. We need to set the language and we can specify the ruby versions that we want to test this against, and then see how this goes. I'm going to do that, and I'm going to open up .travis.yml, let's make this file. Let's paste this in and let's do 2.2.2, let's do all the stable versions: 2.1.6, 2.0.0. We could do jruby, I don't think it really matters this, we don't have anything too special going on so let's just keep it at these, and we can add more of whatever we want to do later, but this gem's like really straightforward, it's just regular old ruby code, so if there's anything that's specific to one of these languages like jruby or you're doing something that they maybe don't support, then it would make more sense to test against those, but in this case we're not really doing anything these can't support. Even if we just tested against 2.2.2, I would be totally fine with it, it's not a big deal. If we were doing a more complicated gem that might deal with threading or something complicated like that, that jruby does really different from MRI, that would be a situation where we would define all those to test against. Let's add these two to our gemfile, and let's see about adding the Travis CI image, embedding the status image. These are the little "builds passing", images that are really useful for embedding into your README, you're README is the perfect place for that, and people are starting to put a lot of those code climate GPAs and whatever, and I think it's awesome, I think we should definitely do that. Let's just put it right here at the top. I just grabbed their example here, and I believe we can take this url, and that is that.
Let's fix this url and we want the master branch, and that should be it, we should be good. This should automatically show up correctly in our README. That should be all that we really need to do for this, so let's add that to the README, let's commit this.
git commit -m "Add Travis CI and make rspec the default rake task", that's it, that's really all we need, let's
git push origin master, and let's see what we've got on the main repository's README. "build failing", click on that. We should actually correct the url, so that it takes us to Travis CI. If we go to Travis CI, we should be able to see this, and it's probably running the tests. If it is running the tests then we've got his all set up correctly, I've already gone in to my account and turned on Travis CI for this repository, we don't have to worry about that, but let's see what happens. It did run the tests 30 minutes ago, and maybe there's a current one running right now?
Let's update this in the meantime so that we have the image as a link. You can do a nested one which is interesting, I don't know if GitHub can do that, we may have to check that up. Or maybe this isn't worth dealing with, let's not worry about it, this seems like one of those things it's not a big deal. Let's see if we can restart this build and see if this is going to work. Our last commit was 49fd. Here's 49fd, this number 2 is started, let's find out.
That was it, all of our tests passed. One test, but on three ruby versions, it's pretty good. The tests ran pretty slow, I had to cut that out, that was really really boring to wait through that for like 10 minutes. This vlog has gone on really long, I didn't expect it to go on for this long, but we'v got through all of these, we got an extra thing done, I got the rspec stuff set up, pull requests merged, I got a pull request reviewed, and we've got Travis CI set up, so that was pretty good. Not bad.
That took longer than expected, but day three of the vlog is done, we've got all of our open source stuff that we intended to do, I really just wanted to get our specs set up today, tomorrow the goal is to do something more with the tests over the first rspec set up and I think we just need to talk about what tests we want, how much we want to test, what type of test we want to do. I think some integration, some unit tests will be the balancing we want to strike, and we'll see if anybody else has things going in the meantime, so talk to you next vlog. Peace
Transcript written by Miguel