 Hello everyone. Good evening. I'm Isaac. I'm originally from New Zealand. I've had the pleasure of working with Clojure now full-time, exclusively almost for more than three years. I really enjoyed that. It's a great language. I find not so much because of all the technical details, but it's because it lets you focus on what you're building and gets out of your way. You don't have to worry too much about syntax or the ecosystem or the libraries. Everything else is really good or good enough to get the job done, so it lets you build really awesome software just focusing on the problem at hand. Now having the benefit of working in Singapore with my colleague here in New Zealand, we work on games. We're Clojure 1.9 just came out, which is exciting. It's finally here. It took a while. One of the big features in Clojure 1.9 is ClojureSpec. Up at the top here is a new namespace, Clojure.spec.alpha, which is immediately named as S for short. There's some other namespaces that got added like spec.gen.alpha for generators. Spec.tests.alpha for running tests from generators made from specs. It's called alpha, but most of it already works. It was in the stable version 1.9. If it works for you, you can start using it today. First, I'll go through how it would have done it previously and how you might change your workflow to do it spec. With poker, you obviously have different hands trying to get the best score and want to score a hand to know how good your hand is or how good a player's hand is in the game. A flush is just a function that takes a hand and it counts the distinct suits. Then, if there is one suit across the whole hand, it's flush. How you might test that previously, for 4 Clojure 1.9, we like to represent things as just plain data and Clojure. In a Java, you might create a class with methods on it to represent this, but in Clojure, it's just to have a vector or array of vectors that represent cards in a hand. This is a 5 card hand and each vector is just the suit and the rank of the card. So that's 3 diamonds, 5 diamonds, 1 diamonds, so on. If you were to test that the flush worked with previous testing, you'd probably write out this data structure by hand into your editor and then write some test functions to test that flush called with this data structure that you've written out manually. It's true, but it's false for a straight. You'd run it probably by this up as well. It's already referred as handy. So that's true. You can see just running a test when you call flush with that data structure that it's true and with a straight, it's false, saying it's true that it's false. So the test is both pass. In this case, both tests result in true. So that's awesome, the test pass, so you can put to production. Or maybe not, because we know that often you miss things that you don't think of. Maybe you didn't try every possible combination of card hands that exist in poker and there's one that's scored incorrectly and since in the implementation details of how you wrote your flush function, return the wrong value and then people get the wrong experience in the game. So with generators, what you can do is you can specify how to generate a data structure by specifying the properties, this is a vector of so many items and it contains numbers and the range of, if we go back to the example in the range of 2 to 15, because I didn't use letters to represent ace and Joe just used numbers, and a keyword of diamonds or clubs and so on. And you can actually get generators to produce these automatically like a random sample of possibilities. So I might test 10,000 combinations or having many possible combinations. It could be for whatever data type you're working with. The advantage with that is you're never going to write 10,000 tests manually and no matter how good you are writing tests, you can't possibly try that many variations so it often finds something that you didn't think of. So with spec, a closure spec is just a way to define the shape or the appearance of data. So you can use it for other things other than generators. It's too big to go into a lightning torque and a size of 2 vector. And then you just define a hand as multiple cards. This is a simple example. You also go into more advanced functions once you get into it and you can specify max and min counts, optional keys of maps, required keys, so that was just a basic example of how it works. And then for here you can even define like a player with the keys of name and hand and possibly a score. So with that card defined there, if we go s conform, which checks if a value conforms to a spec and we pass in diamonds. So the thing here is why the resolve is specs are fully namespace keywords. So it's actually in the other namespace that I'm editing, not in the repo namespace so you have to fully qualify it with the namespace at the front. So that returns closure spec invalid because it doesn't conform by having a rank. It doesn't return nil or false because nil or false are conforming values for certain types. And then if you pass in a valid card, it returns the actual data itself. So spec can be used to check in that sense that the shape of a dot type matches what you expect. Then you can even create a generator from that spec with sgen, also say poker card for automatically generate random cards that conform to that spec. Or if you want a hand, you just pass in the hand spec. Being a simple example it's just a random length but you could confine that more down to five. And these are all in the valid range, they're all valid keywords. So every time you run that it's going to give you a different hand of cards, not just one fixed hand that you've put in your test. So what you can do with specifications with spec is that you can automatically run tests against a function with a large range of possible values that conform to those specs. So if I was to run this against the flush function it would get all these different hands generated like 10,000 times or however many you want to run it for. And it would print out the values for which that failed. So you specify the shape of the input data and you specify your expected output based on inputs for the function definitions. That's done with another function in spec called fdef. So it just takes the symbol naming the function and three keywords, args, ret and fn. So args, I'll show you an example in the code. This is a very simple one. Again, it takes a spec that can apply to a list as if you're passed to apply to a function, to call function. So you can say it takes a hand and it should return a Boolean. Then the other keyword which I've been putting here is fn. It receives both the input and the outputs of the function when it's called at test time. So you can specify some constraints within the function between the input data and the output data that conforms to the specs you've made in your tests. So when you run this with a test runner, it'll dump out if any of these specifications about the inputs or the outputs or the relation between the inputs and outputs of the function have failed across a whole range of sample data. So that's about all I have time for in a lightning talk. But I'd just encourage you to go check out the spec ID on Closure website, closure.org. It's a good place to get started. It actually has a card's example as well. Slightly different. And I think for certain use cases this can really find a lot of problems. You normally wouldn't find your code. But others, to be honest, it can be more effortless worth to write the specs I've found. So it can take a lot of time before it all returns. You really have to judge based on the kind of function you're testing, whether it's going to be useful in your use case or not. Any questions? Okay. Thanks.