RSpec
A Big Look at MiniTest
Summarized using AI

A Big Look at MiniTest

by Mark Bates

In his talk at RubyConf AU 2014, Mark Bates provides an overview of MiniTest, a lightweight testing framework included with Ruby starting from version 1.9. He discusses its benefits, structure, and how it can effectively be used in both simple and Rails applications. The core themes of the presentation include:

  • Introduction to MiniTest: Mark highlights that MiniTest is often overlooked despite its powerful capabilities, which are bundled with Ruby.

  • Comparison to Other Testing Frameworks: He contrasts MiniTest with RSpec and TestUnit, pointing out that while RSpec provides extensive functionality, most of what developers need can be achieved using MiniTest with less complexity.

  • Key Features of MiniTest: The framework is composed of eight files, three of which are essential. Mark emphasizes its simple syntax and structure similar to RSpec, making it easily accessible for developers already familiar with Ruby testing.

  • Custom Matchers and Assertions: Mark illustrates how developers can write custom matchers in MiniTest, allowing them to tailor the testing framework to their specific needs without cluttering the object space.

  • Mocking and Stubbing: He mentions that mocking and stubbing can significantly enhance test performance. Mark encourages using Ruby's built-in capabilities along with existing libraries like Mocha or FlexMock for complex scenarios.

  • Best Practices in MiniTest: Mark emphasizes the importance of maintaining clean tests through the use of expectations that start with 'must_' which prevents pollution of the kernel object space.

  • Integration with Rails: He discusses how MiniTest can be set up effortlessly within a Rails application and encourages the audience to consider its use over more complex alternatives, especially in speed and efficiency.

  • CI Tool Compatibility: MiniTest works seamlessly with Continuous Integration (CI) tools like Travis CI, enhancing its usability in modern development environments.

Mark concludes by encouraging Ruby developers to utilize MiniTest, highlighting its ease of installation, speed, and the substantial amount of functionality it offers, noting available resources for further learning at RubyConf AU 2014. By promoting practical use cases and strategies within the framework, he aims for developers to adopt MiniTest for efficient and effective testing in their projects.

00:00:07.060 Thank you! There's popcorn downstairs, and Andres is downstairs now. Here we've got this to mark.
00:00:12.710 J-Mac is a big person with a big smile who loves big hugs. True? Bring it here!
00:00:20.750 Okay, bringing the big booming bear hug.
00:00:27.290 The hug is authored by a programming book in CoffeeScript. He's Paul McCartney's cousin.
00:00:32.630 Don't ask him to sing. Please welcome my fate—and so did that!
00:00:43.670 I want to just give you an introduction. I am NOT Paul McCarthy's cousin, but ask me later, and I do have a really, really good Paul McCartney story for you.
00:00:49.609 I am also not Ryan Bates, if that is what you were expecting to see. Hi Josh, thanks for coming!
00:00:55.789 I am the author of three books: "Programming in CoffeeScript," "Distributed Programming with Ruby," and my latest, "Conquering the Command Line." I have some to give away!
00:01:04.250 This is what it looks like when you win one! I'm very excited—this is not me trying to bash my head on this thing, by the way.
00:01:10.790 So, if I suddenly fall unconscious, don’t be alarmed. I do have a couple of giveaways.
00:01:20.630 Before I do that though, I'm also the voice behind a site called Metacast.TV. It features weekly screencasts about Ruby, Rails, JavaScript, Postgres, and Go.
00:01:27.420 It's a lot of fun! Enjoy a free month of Ruby AU 2014, and learn about all sorts of things. So before I give away books and before we dive into MiniTest, I know who really went to the GitHub drink-up last night!
00:01:40.549 Good number of people. Who here flew in from really far away very recently? And who here is just generally tired this morning?
00:01:52.880 That's what I thought, so let's all stand up! If you said you weren’t tired, we wouldn't do this. Let's all stand up!
00:02:05.780 There we go, let’s get the blood flowing. Everybody stand up, come on. Roko t-shirt, stand up! It's a small room!
00:02:12.560 Now, everybody reach up into the sky! Good! Now reach out for every t-shirt!
00:02:19.340 Alright, let’s all do some twists. Everybody do some twists! Stretch it out!
00:02:24.410 Waking up, that’s good! We like to get people moving.
00:02:32.060 Now everybody, let's stay standing for just a minute.
00:02:37.510 Today we're going to take a big look at MiniTest. Alright?
00:02:43.340 This is the Green Dot—it’s what Rubyists love! I’ll be honest, my wife is here with me in Sydney.
00:02:48.650 If she wasn't, I'd probably be making out with the Green Dot in my hotel room at night! That's how much I love the Green Dot.
00:02:55.070 Nothing makes us feel better than to see a bunch of green dots going across our screen.
00:03:01.940 Red dots make us sad, green dots make us happy! When we see a screen like this, we all know we can sleep well at night.
00:03:08.239 We know our code is perfect, wonderful, and very well tested. Okay, maybe not perfect, especially if you're writing Zach's code.
00:03:14.239 But, it's at least somewhat tested, right? Green dots make us happy.
00:03:19.610 Alright, let's get back to serious business.
00:03:24.880 The first thing we do when we set up a new project is set up a testing framework.
00:03:32.000 At this point, you usually think, 'Oh my god! I should write my own testing framework, because how hard could it be?' Who here has thought that before?
00:03:37.810 Raise your hand! At least one person has.
00:03:45.310 I'm here to say, please don’t! And I’ll tell you why.
00:03:51.350 There’s a site called the Ruby Toolbox; who here has heard of the Ruby Toolbox?
00:03:58.519 Fantastic! It's an amazing site written by a big hulking German guy named Christoph.
00:04:03.590 If you see Christophe, buy him a drink. He smokes a lot, drinks a lot, so he’ll be open to that!
00:04:10.790 But the Ruby Toolbox is a great place. You can go find a new plugin for your app.
00:04:15.980 I want to write that tags for my application, what's the latest and greatest?
00:04:22.040 It gives you a lot of information. Here is the MiniTest one, for example.
00:04:29.780 It tells you the last time it was updated, how many commits, and how many downloads.
00:04:37.909 It's a really helpful tool to get a good idea of what these plugins are and what they do.
00:04:44.810 I did a little search for testing unit testing plugins, and these are some of the ones I found.
00:04:52.340 I know RSpec, MiniTest, TestUnit, Bacon, and it starts getting a little wonky as we go along here.
00:04:59.140 Other people have had your idea, and I'm here to tell you, don't do it!
00:05:06.120 The reason is we already have MiniTest. MiniTest is already with us, and it's there every day. Most people don’t realize we have it.
00:05:14.300 Good things indeed come in small packages, as we can all agree. The Mini Cooper—everybody loves the Mini Cooper!
00:05:21.169 Mini me, who doesn’t love Mini Me?
00:05:26.270 You get mini bottles of booze on airplanes that make you feel like a giant!
00:05:31.460 And when you hold them, it’s a fun feeling!
00:05:36.589 Anyway, back to the topic of MiniTest: MiniTest comes in eight files.
00:05:41.180 Honestly, there are about three that actually do anything. For example, one is a gay pride formatter that will rainbow color your test results.
00:05:50.419 It’s awesome, although probably not incredibly useful.
00:05:56.120 It really comes down to about three different files that make up a solid testing framework.
00:06:02.659 This is a little bit of what MiniTests look like. This was the MiniTest spec; it looks very much like RSpec, as we will see going forward.
00:06:10.249 This is MiniTest unit, for those of you who have a preference for test unit.
00:06:16.279 Now, one interesting thing to note about these two files I just showed you is if you were to take the time and quickly type these into Vim or Sublime.
00:06:23.629 Then run them as Ruby; chances are they would run for you and the tests would actually pass.
00:06:30.919 And we did that without any gems! How the heck do we do that?
00:06:38.029 It ships with Ruby people! It's there, on your computer, already!
00:06:46.599 If you have Ruby greater than 1.9, and why don't you if you don’t? Seriously!
00:06:54.229 If you have Ruby 1.9 or above, you already have MiniTest.
00:07:00.120 You have what you need to run testing. It is also available as a gem.
00:07:10.810 The reason why it's available is that the gem is easier to develop outside of the Ruby pipeline.
00:07:17.440 So I highly recommend you use the gem. You can install it with 'gem install mini-test'.
00:07:23.630 But if you're on a long flight from LA to Sydney with no internet, you can still write tests without needing Bundler.
00:07:30.510 It has a very familiar syntax to RSpec.
00:07:37.550 Who here has used RSpec before? Who here has never used RSpec?
00:07:44.790 Now, I know you're timid... who here uses TestUnit?
00:07:52.640 Really? Oh, you poor thing! We'll buy you a drink later to help you out!
00:07:58.740 So, Ruby 1.9 refers to MiniTest to replace the TestUnit in the Ruby core library.
00:08:06.360 Thus it is readily available to you.
00:08:12.630 We'll take a quick look at the basics, and some of the differences between MiniTest, Spec, and Test Unit.
00:08:20.399 Who here is involved with Rails and are you excited?
00:08:27.680 It’s coming up. I think it has a bright future.
00:08:34.299 So, here's a basic MiniTest spec: describe something, do it, it does something.
00:08:41.640 These are all very RSpec-like. If you already know RSpec, you know what you need to be familiar with MiniTest.
00:08:45.270 I could probably end the talk right there and still cover before and after setups and teardowns.
00:08:51.360 We can do nesting, just like we'd expect!
00:08:56.630 For those who don't know what lets are, lets memorize or encapsulate what's inside that code block.
00:09:03.240 That allows us to access another place, just like RSpec.
00:09:07.890 We also have subjects, just like RSpec.
00:09:13.920 What’s fascinating about this is that I keep saying 'just like RSpec', but if you go into a project that uses RSpec and do 'bundle open RSpec'...
00:09:20.320 You can see how many files are there.
00:09:27.320 Then do 'bundle open' on all the files for all the gems that RSpec requires.
00:09:31.890 Then go and look at the MiniTest code to see how much they can do in three files.
00:09:38.310 Versus what RSpec does in about six gems.
00:09:41.720 It’s important to see, you can achieve similar results.
00:09:44.240 Context blocks, we can’t do context blocks in MiniTests.
00:09:50.050 If you run that, you get an undefined method context.
00:09:56.790 But we can fix that easily by aliasing it off.
00:10:02.870 It's quite simple to alias context to describe—it’s just pure Ruby!
00:10:08.650 We can do pendings with MiniTests.
00:10:14.870 There are three different ways to do that: it does something without a block.
00:10:21.180 We can skip it, or we can skip with a message.
00:10:27.920 Pretty straightforward! Run that, and you'll have a bunch of successful tests.
00:10:33.850 Expectations, this is one of the things I like most about MiniTests.
00:10:39.350 It's got really nice expectations that are very simple.
00:10:44.390 They don’t clutter up your object space like other testing frameworks such as RSpec.
00:10:51.830 These are the expectations that are included with MiniTests.
00:10:57.820 They all start with 'must_'.
00:11:02.350 So when you're looking at the methods that are available, you know which ones belong to MiniTests.
00:11:07.510 They all run with 'must_' which keeps things neat.
00:11:14.610 You won't pollute the kernel object space or your object’s space.
00:11:22.100 It’s very clean and simple, like 'must be empty', 'must respond to', 'must send', 'must have output', etc.
00:11:27.350 Also, the opposite is 'won't'.
00:11:31.640 If you know one, you'll remember the other. For instance, 'must be' means it won't be.
00:11:38.850 Or 'must match' meaning it won’t match. Very straightforward!
00:11:44.610 Here's a little code showing you what a bunch of them achieve.
00:11:51.490 You have 'must raise', 'must include', 'won't include', 'must be nil', 'must be empty', and many more.
00:11:56.500 I love the assertiveness of this framework. It’s not wishy-washy; it clearly states expectations.
00:12:01.720 It should be equal and not hopeful; it’s definitive!
00:12:09.100 Here’s an example of some of the expectations in action.
00:12:15.370 It’s very direct with things like 'must raise', 'must include', and 'won't include'.
00:12:22.480 These offer great clarity in your testing.
00:12:30.000 Much of what we accomplish with assertions can be done simply, without any convoluted syntax.
00:12:37.840 It’s quite refreshing!
00:12:43.670 That said, if we compare this to TestUnit, we can create assertions that don’t affect your namespace.
00:12:52.720 It allows us to assert truth or falseness without contaminating our object.
00:12:58.560 You won’t find these methods on the objects you're testing.
00:13:06.060 That approach garners extra respect for Ruby as a testing language.
00:13:11.570 Many tests support mocking and stubbing.
00:13:18.040 Who here does a lot of mocking and stubbing?
00:13:24.000 Cool! The rest of you should do a lot of mocking and stubbing!
00:13:29.160 Your tests will run significantly faster that way.
00:13:36.930 Testing support in MiniTest is very basic.
00:13:43.920 There are only about three real files involved.
00:13:49.950 Let’s break this down further.
00:13:56.510 You get a MiniTest mock: you can create a mock object.
00:14:02.670 You can set expectations on it.
00:14:06.020 The verify step ensures those expectations are met.
00:14:14.370 You can also stub on an object with a stub block.
00:14:21.060 We do the same thing; we have an instance of something and stub the method.
00:14:29.370 These techniques are effective, allowing your tests to run smoothly.
00:14:36.000 Ruby also excels in mocking and stubbing.
00:14:43.200 Let’s create a struct that behaves as if it had a complex object.
00:14:51.000 You can replace heavy network classes with a struct or an open struct.
00:14:57.080 This allows for cleaner, simpler tests.
00:15:04.410 This method fades away when the instance is disposed of.
00:15:09.640 Many tests demonstrate that we don’t need a complex mocking system.
00:15:16.230 It’s all built into Ruby!
00:15:21.120 However, there are great mocking libraries available, like Mocha and FlexMock.
00:15:28.150 These offer certain levels of convenience.
00:15:37.410 You might feel inclined to write your own, but please don’t!
00:15:44.980 Instead, go to Ruby Toolbox and check what's already been done.
00:15:51.000 You'll find alternatives to save you time.
00:15:58.920 Custom assertions are easily made in MiniTest.
00:16:06.180 Who here has created custom assertions in RSpec?
00:16:14.070 A few of you! MiniTest allows for this in a far simpler manner.
00:16:20.340 For example, you might want to create an assertion called 'must_round_to'.
00:16:30.500 You can simply open up the MiniTest assertions module.
00:16:36.919 Create a new method called 'assert_rounded' or name it whatever you wish.
00:16:43.960 Just ensure you assert that it's equal.
00:16:51.320 This method returns true/false, and you can supply a message.
00:16:58.050 Now, here's where it gets even more interesting.
00:17:03.850 You have to do something with these methods created.
00:17:10.320 MiniTest won’t put these assertions on your objects until you instruct it to.
00:17:16.790 You do that by using the 'infect_assertion' method.
00:17:22.408 It's more simple than you may think!
00:17:30.080 So you can etch into numeric values, so that they can round.
00:17:36.970 You're not concerned with how other data types manage that.
00:17:42.920 We have a MiniTest, a spec equivalent, which is really straightforward!
00:17:48.440 We can install a MiniTest spec Rails gem; there's one available.
00:17:55.919 They do need some updates; users may find it somewhat lacking. If you know the author, encourage them!
00:18:01.880 You can create a test helper with requirements as we insert more tests.
00:18:08.230 It's straightforward, incorporating pending task checks and so forth.
00:18:16.360 MiniTest expectations allow you to include effects in blocks.
00:18:25.070 You can, and we generally assert methods for redirecting.
00:18:30.450 You can implement type checks like 'must redirect'.
00:18:37.740 You don’t have to call a myriad of responses—keeping your code clean.
00:18:44.490 I'll reference the slides later; they'll have all these examples.
00:18:51.490 There's a little rake task to set this up, which is a touch of low-hanging fruit.
00:18:57.030 It's instant easy fixes that would benefit anyone learning about the gem.
00:19:07.520 One of the nice things about MiniTest is you run tests with pure Ruby.
00:19:15.550 This means you can avoid chains of commands.
00:19:23.110 Use it directly in your Rails folder!
00:19:29.140 You can seamlessly incorporate standard functionality into your tests.
00:19:34.270 If you like guard, who here uses guard?
00:19:42.500 You should be using it for everything!
00:19:48.500 I rely on it for everything, even silly things.
00:19:56.150 Okay, here's my guard file. It's integral for developing your test process.
00:20:01.670 MGM provides neat enhancements that allow you to optimize testing.
00:20:09.350 You simply don’t need to pass in special flags to obtain results.
00:20:17.330 It optimizes the search for files and knows where to look.
00:20:23.280 If you're active in Capybara, it has provisions too.
00:20:30.840 In conclusion, it's a familiar syntax for those seasoned with RSpec.
00:20:37.800 You likely picked it up quickly and went, 'I already know this!'
00:20:45.330 95% of functionality inherent in RSpec lies within MiniTest!
00:20:52.550 What’s happening in that extra 5% that requires hundreds of lines of code?
00:20:59.030 MiniTest is incredibly lightweight! Look at my gemfile.lock.
00:21:05.650 These show what RSpec requires—note how much is necessary in comparison.
00:21:11.780 Ultimately, you won't need any extras installed outside of what's already present.
00:21:19.660 Quickly benchmark RSpec against MiniTest.
00:21:24.820 Generally, Rails testing is slower, while MiniTest has a better speed rating!
00:21:32.420 And let’s be real: every second counts in development.
00:21:40.500 So I urge you to explore testing solutions while prioritizing both effectiveness and efficiency.
00:21:49.140 Please view the resources I recommend. Check my screencast site!
00:21:55.560 There are references like, 'Perform MiniTest in Rails' which cover all the basics.
00:22:03.930 You can obtain valuable information, and it’s all free at Ruby AU 2014!
00:22:10.750 Now, any questions?
00:22:17.700 Yes, sir! You asked about the 95% that MiniTest covers?
00:22:23.980 The biggest component you're missing is the ability to tag tests.
00:22:31.200 For example, with VCR, you want tags for tests to harness specific behavior.
00:22:39.400 But, there's also a MiniTest gem out there that provides tagging functionality!
00:22:45.940 It's not often I don't use it, but if you want it, the option is there.
00:22:50.740 This shared expectation is an element of that 5%.
00:22:59.760 For tasks that rely on these shared expectations, you can create a module that includes methods.
00:23:06.690 Or you can develop your own custom assertions for those needs.
00:23:12.160 That's important to know! Anyone else have questions?
00:23:19.130 Yes, one more question—kindly hurry as we are running behind!
00:23:25.720 Does MiniTest work well with CI tools like Travis?
00:23:32.730 Yes! It can run any Ruby-related tasks efficiently!
00:23:40.210 Josh could answer this better than I could.
00:23:46.120 Travis runs successfully with MiniTest!
00:23:52.850 So, thanks everybody for your time today. I appreciate it!
Explore all talks recorded at RubyConf AU 2014
+16