 refresh gwybodaeth I want to make one thing very clear for certain members in the audience. I'm not in fact Australian. I'm actually from a small cold Island nation of the coast of Europe, called Britain. I now live in Sydney. Which is a very large country. In fact, you can see Britain is a percentage wise very small part of a sort of side of Australia and the reason why I'm here talking to you today is I have the honor of being one of the Caught team members for R-Spec. So, first off, hands up if you've heard of R-Spec. That's a good percentage. Hands up if you use R-Spec. Okay, okay, we're going well. Hands up if you've heard of version three. Still a good number, good, the marketing is working. Hands up if you've used version three. That is actually a good percentage of you, I'm glad. So, why is this important? Why is R-Spec three important in particular? So, have you all heard of semantic versioning? Hands up again? Good, so we all know that in patch releases we should only be able to fix bugs. In minor releases we can add new features, but we must not make any breaking changes. And we know that in major versions we get to make those breaking changes. So, just quickly going over the history of R-Spec because it is actually quite an old and venerable project at this stage. Released in 2005 with R-Spec zero versions. So these are the very first sort of minor versions that were quite frankly a little bit of a hack. This was way before my time on the project, way before most people who currently maintain it's time on the project. That's been through several sets of maintainers. And it wasn't until 2007, a couple of years later, that R-Spec one was released and it became stable, you could use it, people actually tested products and shipped cool stuff. And it took another three years until R-Spec two was released, which is the version that most of you are probably most familiar with at this point in time. When it was released we actually reached about 85 different contributors to R-Spec at this point. It had most of the features we all know and love. And it was during this time of course that Rails 3 came out and R-Spec is sort of grown in usage as Rails is grown in usage. So if we fast forward to 2014 now, we actually have at this point a couple of hundred contributors have committed stuff to R-Spec. And we've finally released version three, which has actually been the product of more than a year's work. So why should you care? The astute among you will have noticed, of course, that this talk title contains a pun. They expect you to care. And even more astute of you will notice that I slipped up and said, should you care? I'm sorry, there was no happy accident. It was in fact the product of engineering for this talk. It's because it's the most recent, most visible change that we've sort of made, especially around three. It's not the only change that's in three, but it's the one that most people are now actually noticing the expect syntax. If this was a blog post, the TLDR of this talk would be that releasing version three is about cleaning house, about removing deprecated things and making painful recommendations. The expect syntax is that one of those painful recommendations. A year or two ago, I would have been happy writing should syntax. I would have been more than happy to write should you care for this talk. Just a quick show of hands. Who actually uses the expect syntax? And who uses the should syntax? Hi, Constantine. We all know what the expect syntax looks like. You generally expect something to match some matcher. We all know that the should syntax is slightly shorter and we expect some object to should match. The expect syntax is not actually that new. A lot of people refer to it as the new expect syntax. It was actually released in July 2012 in aspect 2.11. Somehow that escaped a lot of people's notice. Even before that, you could use it to write block expectations. In fact, you had to if you wanted to test that you were raising errors correctly. But in 3.x, as we refer to the 3.0 series, it becomes the recommended syntax. It now has full equivalence with the should syntax, something that didn't have prior to 3.0. This talk is about why you should care about that. Just quickly. Object.should becomes expect object to matcher. Object.should receive becomes expect object to receive. Object.stub becomes allow to receive. Should receive some vowels. We initially weren't going to replace this syntax, but we have people complaining. So we have given you receive messages. And we've had a lot of people complaining about should being deprecated. A fun fact about should being deprecated. It's not. What's happened with aspect 3 is that we deprecated the usage of should automatically. We are trying to get away from you just assuming everything will always work. The big scary warning message it creates forces people to think it's deprecated. I should actually apologise for that. That's something we slipped up on. We didn't think that people would kind of assume people would read the message and not just see should deprecated. And it's caused a lot of people to switch to expect which we like. But what actually made us change this recommendation? The answer to that is monkey patching. Most Rubyists are familiar with this expression. We open a classroom module and we insert some code. This syntax is monkey patching. It's putting should on to every object in the system. And it can go horribly wrong. The original reason for writing the expect syntax was cases like this, which is a proxy object. When the expect syntax was introduced, this actually would have tried to be tested like this. And it wouldn't work. Because the way that obstude is monkey patched into kernel overrides on the object, and B fuzzy tries to match against fuzzy question mark, turns out they go false back to the method missing, and you get an error about the method not actually existing on the object you're proxying to as opposed to on the proxy itself. That bug was fixed when expect was introduced. In preparation for this talk, I had to make sure that this was fixed. And I actually found that 3.0 has a subtle bug, whereby we are deprecating parts of the predicate matches with private methods. This actually trips up the private method warning, so I'm going to have to fix that later on in the conference. And there was also a rather nasty bug surrounding active record where proxy objects for collections would actually remove should, and people would complain that, I should not find my method anymore, and you're like, well, why is that? So realistically, the reason why we're deprecating the usage of automatic should, is to get rid of this chap, the evil monkey in the closet. Our drive, as I said, we want to remove as much monkey patching from our spec as possible. And that necessitated a change to our syntax so that we can provide the right aesthetics so that we can banish the evil monkey from our closet. And that's what the deprecation measure is telling you. We're telling you that we want you to tell us when you want us to monkey patch. We want that to eventually be the default. It's not where we are now. At the moment, monkey patching is still automatically included, but we want it not to be. We want to extract and isolate our code from your code to help you test your code. And this has actually led to one of the other new features in aspect. So previously, of course, the DSL look starts with a describe, and you have context. And that's actually monkey patched into main. It's only monkey patched into main. It's not exposed anywhere else. We go to a lot of effort to try and reduce that surface API. But in aspect three, you can now do this, which is a simple four-letter change in the top left-hand corner. You can now actually have a completely non-monkey patch mode. You can enable that with very nice conflict-disabled monkey patching. It's not the default because of backwards compatibility. So for the moment, zero monkey patching mode is an opt-in, but we'd really like it to be the default eventually. So part of this philosophy is just trying to keep our stuff out of your way. One of the other biggest changes in aspect three surrounds the four matters. These are probably the biggest extensions for aspect. This is what most people will actually... And they extend from everything from custom formatter to CI to NANCAP. So hands up, who has used a custom formatter? Has anyone written a custom formatter here? That's good. So the new aspect three puts a lot of modularisation into the formatter stuff. We're actually now using notification objects to send to formatters, which we weren't before, because we'd like you to be able to write formatters like this. There's no inheritance here. We're not including any modules. This is the purest sort of poro formatter you can write. All you've got to do is tell aspect what notifications you expect, and then you receive notification value objects. All of this is documented in our docs, of course, but I just wanted to touch on that because it leads me into the philosophy of where we're actually trying to take aspect. We're trying to isolate all of our code from your code. We're trying to drive down various APIs so that they're easier to use, and we're trying to help you write better tests, which leads me to my next... This is one of the contentious points in aspect. Does anyone use its? So its in aspect three has been extracted into a separate gem. When I say its, I don't mean the one-line syntax. I don't mean it should. Incidentally, this actually isn't monkey patching because we own the context of the spec. We weren't even going to replace this with an expect syntax equivalent until everyone complained, so we made it as expected. I guess a bit of feedback from everyone helps make everyone's life easier. But no, when I say its, I'm talking about the value test. They've always been a bit of a personal style. Some people like them, some people don't. We've taken the decision to extract into a gem because we don't think it fits with the core philosophy of aspect as a behaviour-driven tool. It's... They tend to lie to you in how they end up documented themselves. So with a quick example, if you were to have an object and you were to implement this name method like this and you see we've got Bob Jones, the test here is saying its name is expected to equal Bob Jones. This test, the implementation is fine. The problem is with the output. The output of this dot because it's literally taking your code and printing it is a lie. That's not what the name method actually does. It's not we're always going to return Bob Jones. With a little bit of refactoring, this test becomes something more like this. All I've done is changed the doc string. The implementation of the test is roughly the same. But now, when we run that documentation output, we get the component first and last. So now the test is expressing the behaviour of the test and not what the actual value is. That's why we've chosen to recommend that aspect, its method be not used. That's why we've extracted for the third game. You're still welcome to use aspect. It's still maintained by the core team, but we don't want it to be by default. So now that we're talking about behaviour, that segway has been nicely into talking about verified doubles. This is an all new feature for aspect three. It was actually mostly ported from Xavier Shea's aspect fire. Xavier Shea is now on the core team to help us maintain it. It's awesome and I'm super excited about these because they're essentially contract tests for free. So just quickly, if you were to write an instance double, this is how you invoke a verified double. This is no different to writing double name values, the same as you would done in aspect two. Because in isolation, it doesn't do anything. It's like, okay, sure, you've expressed yourself. But when you load in a definition for that object, aspect will now say, well, hang on a minute, we know about this object. You've just stubbed out this method, but it doesn't exist. The double will verify that you have actually met the method contract. So when we implement that, it will now pass. The only caveat here is that it doesn't actually verify the output against the method output. So because Ruby is dynamic, it's not going to check that a string, if you've stubbed it to be a string and it actually returns true, it's not going to go and invoke the method for you. Because that would be expensive and that would defeat the sort of speed part of using mocks in the first place. So it's not quite true contract testing because it doesn't deal with the sort of type signature. But it does do a pretty good job of making sure you haven't typoed your method names. A common use case is to sort of, you know, have your mocks in your unit tests. And then when you load the whole suite for integration, all of your unit tests will then automatically check that the methods exist on the real objects. And we can do this with already existing partial objects too. This will actually pass because even though object doesn't receive other, this is an opt-in feature. So that passes straight off the bat. But if I tell it to verify partial doubles, that's what we call stubbing on an existing object, it will again fail correctly. So that's all about verifying your behaviour. And yeah, that's all about verifying your behaviour. Now most of the other things in aspect three are really about cleaning house. As I said, there are four years of development that's happened on two and for most of those four years we've been carrying around backwards compatibility for aspect one. So in aspect three we are removing methods like stub, bang. It's always been the same as stub. It's never done anything differently. But we're going to remove it. Similarly, because we want to reduce confusion, we're removing both stub and mock as ways of creating doubles. They've always been a test double. For some reason we have three methods for the same thing. So we just remove two of them. We've made sure, we've tried to sort of reduce some confusion. So we now disallow statements like this, which you used to be able to specify that you could receive a message at least zero times, which is kind of a confusing English statement. So we've removed that. This one is slightly contentious. You can no longer specify that you can't raise a specific error. Sorry, the inverse. So you can specify that you raise a specific error, but you can't specify you don't raise a specific error. It's so confusing I'm even getting my tongue tied actually trying to say it. If you want to sort of specify that something doesn't raise a specific error, you're better off rescuing it yourself and expecting the right thing has been raised. But this follows a lot of bugs, because it's like, well, okay, my code's blown up. It's blown up with an argument error. But I was expecting a record invalid error and oh well, I guess that failure is not important. So we've removed that. We've removed some of the older aspect of sort of integration magic. So it's like autotest support. Because, well, most people either use Guard or something else or they don't. And it's kind of something that shouldn't live within the core gem. If there's any textmate fans in the audience, I'm afraid we've removed the textmate format in. I'm not sure there's anyone left who uses textmate. Anyone? One person? Wow. But one of the... This is another contentious one. Can everyone read that? That's a before all hook accessing a let. That's now disabled, because that is sharing state amongst instances of your tests. And we've disallowed that to try and increase the isolation of tests. So now if you try to do that, you'll get a nasty error message. Please read it. It explains how to fix it. And that's a duplicate slide. Similarly, we've disallowed access to partial doubles inside mocks. Sorry, inside before all hooks. The reason for this is again trying to prevent you from sharing state between tests. If you need to sort of do that, then we give you a temporary scope. If you need to do some mocking and stubbing so you can do some one-time setup before a sweep, but we don't want those doubles leaking between examples. So if anyone uses those features, I'm sorry, but it's for your own good. So all of these sort of different things that we've changed and we've made it a pain for you and I'm sorry. So let's talk about upgrading from two to three. So a lot of you said you were using three. How many of you still have projects that are running two? And how many of you have had problems upgrading those suites? Less hands, good. So we went through the whole process of inventing 2.99 and then three. 2.99 is officially the last release in the two series, which is designed so that you upgrade to 2.99. You run that, your suite will still run, it's still fully compatible with 2.14, but you'll get a ton of warnings telling you what's changed. You fix those warnings, then you can do upgrade to three and it will run green. Now that sounds like a pain for some people. So one marvellous person who is now on the aspect core team invented transpec. Who's heard of transpec? Right. All of the rest of you, go to GitHub when you've got some stable wifi and look up transpec. Transpec is an automatic dynamic analysis tool, it runs with your specs and converts all your specs to aspect three compatible. You have to be on 2.99 for it to work properly because it will only translate stuff that works. So if you're running 2.14 into transpec, it will just update to the latest. But if you're running 2.99, it will convert everything into an aspect three compatible. So if we look at a quick example, this is a random spec I'm found I made up. We've got a couple of things that disallow, we've got the it's, we're using the should syntax, we've got an equals equals operator that's no longer allowed and a few other bits and pieces. If we run transpec, you get an output similar to this. It's basically run aspect and it's checked that it's all green and then it's gone okay. So what if you actually tried to test and then you get a list of conversions. And so it returns our previous example into this, which is the only oddity here is what it's done to aspect it. You'll notice it's rather than including the gem, it's describing length and actually going to the effort. The fact that it can figure that out is magic. It's awesome. It's a little bit strange but it's awesome. So if you take away one thing from this talk is that transpec is awesome and you should all use it. So hopefully that's outlined and clarified some of the decisions we've made behind things in aspect three. I'm really keen to avoid cargo culting in our testing culture. I think it's what leads to us to making bristle tests and trying to avoid then leading to self-aggrandising blog posts about TDD is dead. I think that's something is to do with lack of understanding of what perhaps we're always doing. So I really encourage you to sort of research the decisions in testing and not just cargo cult. And I just want to say thank you to all for the listening. Thank you to every single one of these people for contributing to our spec. And I hope you've enjoyed my talk. I'm more of a mini test person, but I just wanted to say that I respect your work. I have to give Aaron credit for the last minute puns on the before and after talk slides. They were initially introduction and concluding until you made the pun. I just want to thank the entire aspect crew who are making this transition so easy. It's actually pretty amazing to see how smooth it was from 2.99 up to 3. I'm glad. Thank you.