What is the role, the core purpose of writing tests for your application?
Should you write more unit tests and fewer integration tests, or is it actually the other
way around? You may have heard of the test pyramid with unit tests building the foundation.
In this episode, we'll talk about a variation on that theme called the test column. We talk
about this and more with Brian Okken on episode number 45 of Talk Python to Me, recorded January
27th, 2016.
Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the
ecosystem, and the personalities. This is your host, Michael Kennedy. Follow me on Twitter
where I'm @mkennedy. Keep up with the show and listen to past episodes at talkpython.fm
and follow the show on Twitter via at Talk Python.
This episode is brought to you by Hired and SnapCI. Thank them for supporting the show on
Twitter via at Hired underscore HQ and at Snap underscore CI.
Hey, everyone. I hope you're looking forward to an interesting conversation on testing software
using Python. This week, our guest, Brian Okken, is giving away five copies of his Python testing
frameworks book. If you want to be in the running, be sure to visit talkpython.fm and enter your
email address to become a friend of the show. Now, let's get right to the interview with Brian.
Brian, welcome to the show.
Hey, thanks, Mike.
Yeah, it's really great to have another podcaster and a friend and a fellow Portlander here all
together on Talk Python to talk about testing in Python.
Yeah, I'm excited to be here.
Yeah, yeah. It's really cool. So for the listeners out there who don't know,
Brian is the host of Python Test Podcast, which is a fairly new, but how many episodes have you had?
Are you on the ninth or tenth?
Yeah, I can't remember. I think I did number nine recently.
Yeah, number nine with Harry Percival. Excellent. Listen, that one, that's great. So I'll put a link
to the podcast out there. So you spend a lot of time talking about testing and exploring sort of the
whole spectrum or pyramid of testing in Python on your podcast, on your show.
Yeah, I really want to cover... Actually, the podcast covers everything. I want to cover everything in
software development and software testing.
So we're definitely going to spend a good amount of time talking about that. But let's start at the
beginning. How do you get into programming, Python, that sort of thing?
Well, my first introduction to programming was in high school. I took a basic class.
High school offered basic at Pascal, and I figured basic has to be easier, right? Because it's got basic in
the name. But at the same time, I didn't really get into it too much then. But at the same time,
I had a TRS-80 at home. And I spent a little time like typing in games from game listings from magazines,
like Lunar Lander was one of my favorites. And then, yeah, I didn't do much more until college. I entered
college intending to be an art and math major. And switched about two or three years in, switched to
computer science. And then finished up with a bachelor's and master's at computer science.
That's cool. So where'd Python come into the story?
I learned C++. I learned all sorts of languages, Perl and C++ and others in college. I got a job at Hewlett-Packard doing,
well, at first test systems and then embedded programming of instruments. And that was all C++ and still is.
And then, I don't know, maybe four or five years later, I was in a group that had a Python test framework for testing,
system testing the instrument. And started, that was probably maybe 2000, 2002. And I've been using Python for testing instruments ever since then.
One thing that I think is interesting about that, a lot of times people feel like the programming language that the thing you're testing,
the application or whatever is built in, that's the language in which you have to write the test, right?
So if you're writing a C++ app, you have to fire up CPP unit and do C++ unit testing.
That's not really what you're doing, right? Like you're actually testing code that maybe isn't Python, right?
Yeah, it's all C++ and other languages inside. And we've got, but it's got a, the interface is available.
Anything with an interface that's available from Python, you can use Python test frameworks to test them.
And, you know, right off the bat, I had frameworks that the company gave me and didn't even think about it.
But, yeah, it was probably 2010 when I started looking into other frameworks like unit test and pi test.
Yeah, okay. So let's dig into a little bit of the type of stuff that you test at work, and then we'll come back and talk about your podcast a little more.
So what exactly are you talking about instruments and physical things that you're testing?
And these are written in what, C++ or like embedded systems with C++ or C?
Yeah, it's C++. But these are, you know, there's lots of levels of embedded programming.
There's, you know, embedded programming in like, you know, your car or your phone or your watch or whatever.
But these are big instruments. These are, I don't know, they look like stereo components, but they're, they've got many processors inside.
The box I work on right now runs Windows.
So I'm really writing a Windows application, but I don't really do any Windows stuff myself.
But it's all written in C++, all of my code.
Yeah, the user interface, a lot of people use these for the boxes I work on are mainly used in production lines.
And the production line control uses a, I guess, a string based, it's called Skippy, but it's a, it's a special language to control instruments with.
Yeah, we, so that's, that's how our users control the box. So that's how we test them.
Is that like for like managing factories? So if you're like building cars, like the machines, like put the door on or whatever, like those types of devices?
Or what do you, what exactly are you thinking?
Well, okay, so the box I work on right now is, is called the communications test box, one box tester, but it, so it tests all the RF, the transmit and receive abilities of a mobile phone.
So pretty much, yeah, every, every phone that sells in the world has to go through testing to make sure it, you know, it does it, it, since it's a transmitter, it has to follow FCC rules.
I see. So if I like lived down in San Diego and worked at Qualcomm, maybe I would buy your company's product to test the phone internals that we're building, something like that?
Yeah. And anybody that's got, and any, we do not just cellular, but also like Wi-Fi broadcasting.
So we do Wi-Fi testing and Bluetooth and anything that transmits and receives this box will test pretty much.
Okay, cool. And so to test this embedded C++ app, basically, do you do some sort of C level interop with Python?
And do you expose some kind of API that Python can understand? Or do you do this Skippy API against it? Or what's the story there?
Well, so the magic that glues it all together is a library that's available on PiPi called PiVisa.
So, yeah, there's a, Roden Schwartz and National Instruments and others have these Visa DLLs that you can use to interact, to send Skippy over LAN.
And I use PiVisa to get at that. So it's really easy. You connect those up and you got to, you just have an object that you can send write and read commands to.
Works great.
Would you say that that kind of testing is sort of more holistic or is that more like unit testing?
It sounds to me like my first guess is like you're kind of hitting the outside, like so maybe an integration test type story, yeah?
Yeah, it's definitely like an end-to-end test.
We test, I'm testing our entire system.
But the kind of the, there is, so, you know, in looking at test frameworks, I'm way more interested in how the fixture model is because I use, we use setup and teardown to actually do things like, you know, move signals around and hit switch boxes.
Definitely more of an end-to-end.
But we do use ideas like mock, like if I'm testing the measurement capabilities, for instance, it's difficult to test that against a, like a moving target, like an actual mobile.
So we'll have an arbitrary waveform generator generate a known signal and we test the receive side against the known signal.
And then we can do the other end also, we send our transmission to like a different instrument to test it against something else.
When you think of software architectures, you often hear people talk about things like dependency injection and basically managing and decoupling the dependencies of your software so that you can test the individual pieces, right?
Yeah.
Yeah, definitely.
Yeah, but you, it sounds like your dependencies are more solid than, than maybe others, right?
Like you've got physical devices and like scientific information coming in and, you know, like waveforms.
And so you've, what kind of stuff do you do?
That part actually isn't that different, really.
I mean, because like on a, if you had like a big user database or something on a web application, the real, the real database on in, in the world is going to be a lot different than your like test database.
So that's similar to how our real signals are different from our test signals.
The diff, the difficulty is, is the fuzziness.
So, we often don't really get, because even with a, a, a pure signal from a generator, we've got, you've got noise in the system.
So you can't, you can't just get a, get a number out of a, out of a, a measurement and say, if it's 3.2, then it's correct.
Otherwise it's wrong.
And almost all of our measurements are, are, we've got tolerances around them.
That's really interesting.
Uh, a lot of people write software that is basically deterministic in, in ways that are easy to assess.
So I get a Boolean back or I query for a user and the user is either there or they're not, or they're an, they're an admin or they're a regular user, right?
These super clear distinctions.
But when you get into sort of sciencey spaces, it gets really hard to actually just know, know that you're right.
Yeah.
I mean, if you get back a number and it's off by a thousandth, is that still the same?
Does that count as okay or not?
Right.
That, that can be really challenging.
Yeah.
But there's, I mean, there's, there's ways to do it.
We've got, we, we can, there's, we can split the, we, when we're testing the entire system, it's difficult to tell because it, you know,
if it's off by 10%, it's hard to, you know, visually know, but, but we can, the, the actual numbers that go through the system go through, you know, there's, there's the different pieces are, are tested with different rigor.
So it all works out.
Yeah.
That's an interesting point.
And I'm, I'm actually not, I'm not the guy that, that tests the, the box to make sure that the, that it like actually, like if we say we're putting out like minus 10 dB, that it's actually really 10 dB, minus 10 dB.
That's like some other guy in, in like a manufacturing facility.
Um, I'm, I'm mostly concerned with that, making sure all the heart, all the software didn't muck things up.
So, in, in the end, I trust that the hardware is working correctly and I just want to make sure that the software hasn't mucked up the, the pristine hardware.
Right, right, right.
So you assume that the hardware you've got is actually processing everything.
Okay.
But you've got to gather it, save it, interpret it, all that kind of stuff.
And so you kind of start at that level, right?
Yeah.
And then the, the measurement data that we're turning back, I mean, we're, we're sending back, we've got like thousands of different like measurement points that we're sending back and making sure that we don't muck one of those up.
And then we don't put some, some array in the wrong place.
Um, that's, that's the sort of stuff that I'm really concerned with.
Yeah, that's interesting.
One of my first jobs was working at a place called eye tracking, Inc.
Uh, eye tracking.com.
And we would build these scientific visualization tools and sort of data analysis on top of eye tracking data, right?
Pupil dilation over time, where you're looking, that, that kind of stuff.
And we would end up doing really complicated math sort of pipelines on it, you know, Fourier analysis,
wavelet decomposition, those kinds of things.
And you try to, you know, test the results of one of those things, you know, it's super hard.
So we basically would come up with a reference input and a reference output and go, if the deviation from, from this graph to that graph is, it's not too large, we'll call it, we'll call it the same, right?
Because the, maybe they use something like MATLAB to generate the reference results.
And, you know, the way it deals with floating point numbers might be slightly different than the language we were using or something like that.
Yeah.
It's an interesting challenge that I think a lot of people building, I don't know, more standard business apps.
It doesn't really get on your radar, right?
Because the user is either an admin or not.
You know, assert true, done.
Yeah.
I mean, actually, people that have that sort of a test job, I'm like, what's so hard about this?
Just, you know, write the test and get on with life.
Yeah.
So, okay.
So let's, let's look at some of the frameworks and get some of your thoughts on that.
So let's say the majority of people listening know what unit testing is, what the goals are.
But I know a lot of my listeners are sort of scientists getting into programming or new programmers.
So maybe give us just the elevator pitch.
What is unit testing?
Why do we care?
I'm not sure why we care about unit testing, actually.
Or software testing, rather.
No, so that, that's a, the, the, the phrase unit test is a, is one that's kind of a, a sticky point for me because the, in extreme programming, the, they use the term unit test.
And that just meant any developer test, anything written by developers, not written by the QA team.
And, and in a lot of communities, it's stuck with that.
It is, that's the, the, the use model.
That's what a lot of people commonly term, term a unit test is something written by a developer.
And then in the TDD community, that often isn't the, the definition.
The unit test is often the, the smallest possible, like one function.
You're testing one function at a time.
And I look at, so there's the, the, the most importantly is that the entire, the entire thing is tested.
Your entire software is tested.
And unit testing is, I think there's certain places where you want to go in and test.
I like to put tests anywhere where I have a promise.
If I'm promising anybody other than myself that things are going to work right, we need tests there.
So if I've got a, a library that other team, other team members use or other, other groups use, that needs tests around it.
But the, and in your, anywhere there's interfaces, interfaces between groups or between components.
Those are great places to put tests.
And then of course the entire system function tests.
I think the, the focus on unit testing, unfortunately takes some of the responsibility out of system level testing where I think it's unfortunate.
I think there's different scenarios where things like unit tests matter more and other times they matter less.
So times I think they matter a lot are when you have a lot of people all in the same general code base making changes.
And you don't necessarily know everything that's changing.
Right.
So, so people are checking in changes and you're not necessarily, I mean, you're doing code reviews and stuff, but you're not necessarily like always aware like, oh, they actually changed this method that I was depending on.
And they didn't understand this like implicit contract I built around the return value here or something like that.
Right.
Yeah.
So I think it's really valuable there.
And I think it's valuable for helping, helping build apps where fewer people are working on it.
There there's less churn.
But one of the things that I saw, you know, early two thousands and in response to the extreme programming was people saw that they, they thought they had to do, you know, 95% code coverage.
Everything is TDD.
If you don't start that way, it's bad software.
You just can't write it.
How can you possibly stand up for it?
And, you know, over time I saw a lot of people saying, well, we can't do that.
Right.
We are in too much of a hurry or whatever.
You know, they have whatever excuse.
A lot of times it wasn't totally unreasonable.
We basically say we can't match that level of commitment to testing.
So we're not going to do any.
And I think that that's one of the places where it can actually, that message of like test everything can become negative.
Because, you know, if they had written, like you had said, the thing you're making a promise about, right?
Like if, if you're writing like stock trading software, the part that actually says buy or sell, there should probably be tests on that.
The, the part that logs that the app started probably doesn't need you in a test, right?
There's lots of parts of apps that are just there to support some sort of core.
And that core is much more important that it's tested, I think.
And what do you, what do you think?
Yeah, totally.
It's like, I think, actually, I think you brought it up in one of your podcasts recently that, that it's the thing that, the thing that's making you money.
The reason why somebody is buying your thing.
That's what you should test the heck out of.
Yes, absolutely.
Like if, if, if that is your thing that you build for the world, that little essence of it, you had better test that, right?
Yeah.
But there's, as you know, you ship real software.
It's like, that's like 20% of the code you write.
There's 80% that isn't that.
Well, and then I like, I like code coverage tools.
But my, a lot of times I think that they're, instead of looking at the, there's two ways to get to 100%, right?
There's a, you can either write more tests or you can delete code.
I think you should delete more code.
If you've got, if you've got a, a bunch of software that is not reachable from the, the user interface.
If, if I can't make some section of the code hit that piece of code with, with normal user input, maybe it doesn't need to be there.
That's a really interesting point.
Yeah.
This episode is brought to you by Hired.
Hired is a two-sided curated marketplace that connects the world's knowledge workers to the best opportunities.
Each offer you receive has salary and equity presented right up front, and you can view the offers to accept or reject them before you even talk to the company.
Typically, candidates receive five or more offers within the first week, and there are no obligations, ever.
Sounds awesome, doesn't it?
Well, did I mention the signing bonus?
Everyone who accepts a job from Hired gets a $1,000 signing bonus.
And as Talk Python listeners, it gets way sweeter.
Use the link Hired.com slash Talk Python to me, and Hired will double the signing bonus to $2,000.
Opportunity's knocking.
Visit Hired.com slash Talk Python to me and answer the call.
I've spent more than once, I've been giving some big software projects and said, you know, have a look at this, and then we're going to need to have you help us add a feature or recommend some change.
And there'll be like some method.
I'm like, what does this do?
What does this have anything to do with this code?
It doesn't seem to do anything.
And I'll like study the code and then, you know, two hours later, I'm like, oh, it's never called at all.
Yeah.
Somebody should have just deleted it.
They should have just deleted it and the world would have been a better place.
But instead, you know, I wasted two hours.
Somebody else probably wasted two hours.
And it just gets kicked down the road.
The other thing, one of the things that I actually like, I'm writing more lower level tests than I used to.
I used to mostly focus on high level tests.
But the, and I still do, but lower level tests do have their place.
But the, I like the model of, in test-driven development of the red-green refactor.
But just don't forget the refactor part.
So if a test, putting a test in place makes it so that you cannot refactor something, then maybe that test isn't quite right.
I don't want to, I don't want to restrict my ability to change my mind and redesign something.
So.
I had brought up the, you know, the perfect being the enemy of the good sort of thing where people say, if I can't have really good test coverage, like what, what is it?
Well, I'm not even going to start.
Forget this.
It's too much work to do testing, right?
Yeah.
Well, and that's, you see that a lot when, when a team like looks at, looks at their code and they go, they get a new manager in or a new, somebody comes in and says, hey, we need to add a bunch of tests to this.
But where do you start when you have like a 10 years of legacy code?
You can't just cover everything.
So yeah, there's a, you got to just start somewhere.
You know, I have a book recommendation actually, now that you bring that up.
So there, you know, Michael Feathers is a guy that in the early days of test driven development and extreme programming and all that sort of stuff, he was really active.
And he wrote a book called Working Effectively with Legacy Code.
And it's, you know, given the time, it was a little more C++ focused, but it has some really amazing ideas of like, how do I take this app, which has a million lines of code and zero tests, and start carving out little epochs of code functionality that are supported by tests and ways you can do that that are safe.
And definitely recommend it.
If people are dealing with like huge apps that are not yet tested and put together in a way that makes them basically untestable, check out Michael Feathers' book.
Okay.
Yeah.
Have you seen that one?
Definitely.
I've got a difference of opinion on that one, but I'll just let that go.
No, no, no, no, no.
I wouldn't hear it.
Tell me.
I think it just seems silly to try to add a bunch of unit tests to a bunch of existing code.
I think it's way more profitable for your company to put functionality testing around it.
And because they like the end to end functionality testing of your system.
If, if you know, like you, you need to know if you're going to refactor something, you need to know that the end functionality is still working solid.
And if you have tests in place to guarantee that, then what value is it to, to go in and add like thousands of unit tests?
Sure.
So I think that's a totally, totally valid point.
And I think, you know, it's been like, gosh, it's probably been 12, 13 years since I read that book.
So, you know, I'm, I'm going to only get it like a little bit, right.
But I think the idea was like, suppose you've got some huge, you've got a library you're calling and like you hit the outside method, like some, you know, do your thing library.
And it gives you an answer back rather than trying to set up a whole bunch of tests inside there.
The question was like, well, how could I refactor some dependency or some bits?
Right.
So maybe what you do is you just come up with a bunch of inputs, save the outputs and go long as those don't change.
We're going to call it good.
It was some, some like really basic scaffolding to say the thing kind of looks still okay.
Yeah.
I mean, I, I think looking at, putting tests around the outside and then also looking at the different interfaces in the side of the system and, and maybe sure, maybe adding some different interfaces that weren't there before to try to separate the design.
But all of that involves like a redesign and you're not going to, you're not going to guarantee that you're not breaking external functionality.
It's just, it's just, they don't, they don't test for that.
Yeah, that's right.
So I think that's, that's probably an interesting thing to explore a bit is, can we be talking about unit tests and the whole extreme programming origins of it and all that, but there's kind of what you refer to on your show as like a pyramid of testing capabilities or functionality.
Can you go into that a bit?
Yeah, sure.
Well, I don't really like the test pyramid, but if you, if you do much reading about software testing, you'll run into a test pyramid.
All right.
So the test pyramid, the, the notion, if you read in, do any reading on test software testing, you'll run across references to a test pyramid.
So the idea is, a foundation of unit tests and some integration tests and very little functional tests, just end to end tests.
And, um.
Right.
Kind of like a food pyramid where like the dessert is at the top.
You should have just a little tiny bit and that's the functional bit at the top.
Yeah.
And, what, what, and the, there's the reason is because supposedly functional system testing is, doesn't give you much benefit and it, they break and they're brittle and they're fragile.
I just don't buy it.
Um, and what, what happens I think is developers see that and they go, Oh, okay.
Focus on unit tests and leave, leave the end to end test to QA.
The problem with that big problem with that is a lot of teams don't have a QA anymore.
So there's nobody doing end to end tests.
Somebody's got to.
Um, so it's, if there's no QA, then it's your customers.
And, I don't think that's the right person to do quality assurance.
So I, I, I think that focusing on, maybe a column of tests, it should be a column, not a pyramid.
Do, do the tests where they make sense.
You've got to have full behavior coverage, end to end wise to make sure that your system works the way you promised it's going to work.
And, and also like with, especially with, continuous integration, if you're relying solely on automated tests, those have to be promises that you're trying to keep to the customer.
And then, I don't really know what integration tests are.
There's a lot of definitions for it, but it's the middle part.
And sometimes it's integration test means integrating with the outside world.
So if you're integrating with a database library, it's tests against that.
But then also some people think of, integration tests as between two components or between two functions.
And then unit tests are the, the low level while you're designing your code.
I don't know.
I think that you just need to use your own.
I don't think there's a rule of thumb.
I think you got to use your judgment and put tests where it makes sense.
I think that, yeah, I really feel that that's, that that's good advice, right?
The whole, let's make, make the top part of the pyramid a little fatter and make it more like a column.
Yeah.
So I think that makes a lot of sense because let's say you have a thousand unit tests.
I actually, I'm with you.
I don't really know what an integration test is, but say you have a hundred of those and you're at 10 functional tests, right?
Do you really need the thousand unit tests or are those 10 functional tests enough?
Maybe.
Well, a lot of the arguments for the, a lot of the unit tests are to make sure that, you know, somebody else doesn't break your units or something.
But I don't know if you, I, I just think functional testing needs to be done more.
So, well, you know what I think the origins of it are.
I think it has to do with the TDD side of things like you, it's very difficult to functional TDD.
I think it's, I think it works great.
Uh, well, like, Harry brings it up and it's been brought up by others as kind of a double loop TDD where you, you start, start with the functional test.
And then, and then, while you're trying to fix that functional test, that's failing, you write a bunch of unit tests.
I think that works, works good.
Um, I just, you know, once you have the functional test working, do you need to keep the unit tests?
I don't know.
It's kind of up to you.
Um, I think keep them if, if they're not, I think of a unit test is like scaffolding, right?
So if you're, well, you're, if it helps you to build your software to put a bunch of scaffolding around it.
Great.
But, once it's built, I don't know, some of the scaffolding can come down maybe.
Yeah.
You're left with columns or something, right?
Interesting.
Yeah.
I think that's a good way to look at it.
I think one of the really big values that unit tests provide in to some degree, the functional
tests and integration tests is they get you to think about how your function or object or
API is used from the outside sooner.
Yeah, definitely.
And that, that's why I think focusing on interfaces, if you, if you're really building an interface
that you need to have clean, then it needs to be, it needs to be changeable.
But, and tested, but like if, if, like, so let's say I'm writing a handful of classes that
all work together and I'm, I'm the main developer in this section of code, it's just going to
be me, right?
Um, so if it, I don't think I'm going to put a unit test around every function because that
means every time I want to refactor this system, I've got to change all the unit tests.
As long as this, this subsystem works from the outside world.
I think that's enough.
I think one of the big mistakes that people also make, you know, in addition to being,
letting like the perfect be the enemy of the good and just saying, well, we can't do perfect.
So we're not starting.
I think the other problem is that people write unit test code in a different mental state.
Let's just say test code, right?
Cause you know, it's, it's up and down the, the, the column that you're defining here.
Yeah.
So I think they write those in a different mental state than the core of their application.
Like I've seen plenty of people just go to unit tests and just copy, paste, copy, paste,
like 10 lines of code.
And like, what are you doing?
Like, would you do that in normal code?
Of course you wouldn't, right?
You'd make that a function or some sort of object or something.
Right.
But that makes it way more painful to refactor or evolve your code when you've got 20 copies
of the thing that you have to maintain.
Well, yeah, that's another reason why I think you had to be careful with the whole, like,
have a, have as many unit tests as you can write in a day because it's, it's an, it's
a code asset, but it's also, it's also a, it's a weight around you.
You've got to, you've got to keep it all the time and you've got to change it.
It's, it's code maintenance.
There's test code maintenance just as there is normal code maintenance.
Yeah.
So I think you can structure your test code.
Most people's test code could probably be refactored to be way more maintainable.
And so that's good, but, and people should do that.
But like you say, like more is not always better.
I think if you think of what are the main use cases that a user is going to do with your application,
if you can test those, chances are all those little edge cases that you're testing, if they
were to go wrong, your main user stories or whatever don't really work anymore.
Right.
So do you have to write those little tests?
That's, that's an interesting question.
Well, I think that if, if a user, I, all the edge cases from a user's perspective, from
like an end user, those should be tested.
I definitely think you ought to test the edge cases, but the, the, the edge cases of
every function.
Um, I don't, I don't think so.
If you've got like, like a, one of the examples I've given before is if I've got a, a username
that goes through the system and in some, some function that has to intercept that takes a
string then.
Right.
So do I need to test to make sure that string can handle a thousand characters?
Um, maybe not.
It's interesting to question these assumptions about, you know, how many tests should you have?
How, how should they, should they be in a pyramid where it's, you know, decreasing as you go up
or should they be kind of more flat and so on?
Well, the, it's, it, and it's, it's sort of theoretical, right?
Because it just, it changes with every situation and the tests need to be an asset so that you
can, if they need to be such that you can trust that if the tests pass, your code is good and
whatever the tests have to be so that you can trust that you can check something in and it's
good because the tests pass, that's where you need to be, whatever it takes to get to
there.
Yeah.
And related to that is if you have tests such that it takes 15 minutes to ask the question,
do my test pass, people are going to stop running them and they just become stale.
All right.
This episode is brought to you by SnapCI, the only hosted cloud-based continuous integration
and delivery solution that offers multi-stage pipelines as a built-in feature.
SnapCI is built to follow best practices like automated builds, testing before integration,
and provides high visibility into who's doing what.
Just connect Snap to your GitHub repo and it automatically builds the first pipeline for you.
It's simple enough for those who are new to continuous integration, yet powerful enough to run
dozens of parallel pipelines.
More reliable and frequent releases.
That's Snap.
For a free, no obligation, 30-day trial, just go to snap.ci slash talkpython.
Well, that's the other beef I've got with, with the, the, a lot of the unit test stuff
with the testing and isolation.
So I don't even get that.
So if, if I want to, so one of the things is if test, the test suite is slow, you're not
going to run it.
So we've got it.
We want to try to speed up test suites.
But one of the ways to do that is to isolate every single function and every single test so
that the test doesn't rely on it.
This function doesn't rely on anything else.
But then if I've got such isolated tests, why am I running the whole suite?
Just run the thing, run the tests over the thing that I'm testing.
Right.
Because if you're not testing the integration, then you're doing like 95% rework that theoretically
doesn't affect you, right?
Right.
If I'm writing code that, is modular and everything, if, like the stock example,
um, if I want to check to see if the buy button works, I don't need to test to make sure that
that functionality that I changed didn't break the printing function.
Yeah.
The about page shouldn't fail when I change the trading engine, right?
Yeah, exactly.
So one thing that you talked about on, I think it was show eight, if I recall my,
my ordering correctly, of your podcast was the theme was like writing software is like
nothing else.
And I found that really interesting and it really resonated with me, not necessarily on a testing
level, but on a software engineering level, right?
Like people say people typically who are not skilled in the art of writing software will
come and say, Hey, look, your title is software engineer.
We have other types of engineers.
They build like bridges.
They can tell us within 10% accuracy of not just the cost of the project, but the duration
of the project and how many people need to be on it.
Why can't you do that with software?
And I think your, your sort of a riff on software is like nothing else.
It was really, I think it was neat.
Well, I, I, I appreciate that.
I like that as well.
The, that notion that it's like engineering or it's like architecture or it's like,
you know, whatever it isn't, it's, it's, it's its own thing.
It's hard to define what, what it's like.
And now as I'm in a management role, I've got to do some of those things.
I've got to come up with estimates and I'm, I'm often the evil guy that says, well, how long
is this going to take?
Are you going to be done next week?
Um, and, and I know the answer is nobody knows, but, but you know, you've got to ask
those questions anyway.
So.
Yeah.
I read a book by somebody and I totally forgot all the details.
So I think it's lost.
It was talking about this and it said, you know, people often refer to software engineering
and I'd actually personally don't really like the term software engineer much.
I call myself a software developer because I think it's, I don't want to put it too near
architecture or engineering in people's mind.
But it was saying, you know, one of the fundamental differences between like a civil engineer that
builds a bridge and somebody that builds a soft piece of rich and interesting software is that
you have to build the bridge over and over and over.
If I'm going to build a bridge across this river, I'm going to build it here.
And then, oh, we need another bridge.
It's about like that bridge, but it goes across this river and it's just this much wider.
Right.
And so you can't, if this was software, you would just like take the bridge and change a
setting and move it over.
Like you would make a copy of it, but you can't copy bridges.
So you rebuild them over and over and over.
And in software, if a thing already exists, you just use it and you copy it and you incorporate
as a library.
If you're writing something often, I mean, I know there's a lot of wasteful reuse and what
are a re rewriting, you know, not made here.
So we're going to do it ourselves.
But generally in software, if you're writing software, it's because it doesn't exist.
It hasn't been done before.
And that really gave me a different perspective.
What do you think about that?
Yeah.
Well, there's a lot of not admitted here that I run into as well.
And it also, there's, it takes a certain kind of person that's willing to dig through libraries
and see if it applies to your problem right now.
But yeah, the thing that I think software is most like actually is probably writing, like
technical writing or just any kind of creative writing.
Because like in, in, in literature and lots of forms of writing, we often talk about the
first draft is, I mean, we talk about it as a draft.
You have a first draft and that's not even usually the first thing.
Usually you start with notes and then you go to a first draft and then, you know, you have
many drafts before you have something that's ready for somebody else to read.
That's probably closer to software because we, in the iterative approach, you, you, except
for there's a lot of software engineers or software developers that, that think they're like awesome
and that their code is perfect all the time.
And that's just ridiculous.
You need to let go of stuff and be willing to throw stuff away and redo it.
Yeah.
Throwing away code that you've worked on is hard to do.
It's fun though.
You should do it more often.
And that's why I like, I like to, I like to put tests around the things that I'm not
willing to throw away.
And those are the interfaces that I have promises to.
So that's, that's really where I like to, the creative freedom of software to be able to,
to take an entire chunk of code, even if, you know, even a week before ship date and say,
no, this stuff's just rotten.
We need to just rewrite it.
Instead of trying to figure out what it does, let's just re, re implement it.
Certainly I've spent hours trying to figure out what a piece of software does and then
more time trying to understand, well, can it be adapted to this situation?
And is it sufficiently generalized?
And, you know, we're not even talking about like, is it thread safe?
And all these other like weird edge cases you might have to care about.
Right.
By the time you're done with that exercise, it was probably like two hours to write that
functionality from scratch, right?
Yeah.
Possibly, you know, I mean, not always, but possibly.
And then other things where I've like, I've spent a week writing something, but, but I think of, I like to try to think of the first time writing a piece of software as learning about what the problem is.
And so you don't have to relearn the problem.
You've already know it.
So if you even like deleted all the files and started over, it would take you a day for the second time.
And then the third time, maybe an hour.
Just don't be afraid to throw things away.
That's interesting because you think I spent a week working on this, but it's understanding the problem, like you say, and like thinking through the trade-offs.
And, and a lot of that probably gets better with time as you understand it better, not worse.
Now, the, the place where people really want to throw a code away is other people's code.
And that's where I think people should like hold off a little bit.
And like the, the Michael Feathers book that you brought up, around that timeframe, there was a lot of talk about what to do with all this horrible legacy code.
And, and I, I never think of legacy code as a bad word.
It was a bad word for a while.
I don't know if it still is, but I think of legacy code as the stuff that's paying my salary.
So I really like legacy code.
Um, so I treat it like that.
I treat it as the thing that's giving me money right now.
Legacy code that's still being used by definition was something that was super valuable and useful.
Right.
Or I guess somebody left some old website running, but generally speaking, it's, if it was not useful, it would have been turned off or somehow outdated.
Right.
Yeah.
Well, I mean, in, we're, we're, I'm thinking more along the lines of the, the, my job right now.
Um, we've got, I mean, a, a test instrument's got thousands of lines of code and the, it goes back.
Like I started on the code base that I'm working on now, maybe five years ago, but, it had 10 years of history before I got there.
So this code is, old, even if the people are still around that made the decisions, they, they don't remember why they made certain decisions.
So if there's some weird switch case statement, you got to try to find out, well, that's one of the hard parts is trying to find out is this, was this intent, an intentional decision or just a whim of a developer?
How many different, types of version control has it gone through?
Like, was it CVS in the beginning or something like this?
Or is it still on the same one?
I'm not, I think it did switch.
I'm not sure what it was initially because there were, there are some like, the time where they would put like the version string and the header of the file.
Those are still around, but they're not filled out anymore.
Um, right now we're, we're actually using clear case, which, I'm not real thrilled about, but it's not terrible.
One of the things that you have going on at python testing.net is you have a book that sort of compares the three major frameworks that people might use to, you know, they're, they're called unit testing frameworks.
But like you sort of point out, you can choose the level of aggregation or isolation you want to get into to sort of run the spectrum, right?
Yeah.
Thanks for bringing that up.
Yeah.
What's the story with your book?
I was around like 2010.
Um, I found myself without a test framework and I looked at those three.
I looked at unit test, nose and pie test, and I had trouble.
I looked at him like what I mean is I searched on the web and tried to read things about him, but I couldn't tell whether they were going to be useful for my job or not.
And I needed something right away.
So I wrote my own, but, and while I'm, while I was maintaining my own, test executive, for work, I started researching these and I, I wanted to,
try to try to play with them and create something so that nobody else had to go through what I did.
If trying to track down what's, what's true information and what's old and what's new.
So I, I went through like, a simple math problem and, and a little, string conversion problem and, used, those three frameworks, on those, this, on the same problem.
So people can see apples to apples, compare the, the three frameworks and, and then extended just, you know, the, the basics of getting, getting a test running, through to how fixtures work.
And it's really the mechanics of the mechanics and syntax of test writing.
And I, I've, I've written other about other things, but the, the book is, basically a collection of those, mechanics posts so that people can come up to the speed really quickly on, on any of those frameworks and compare them as well.
Yeah.
That sounds really helpful if you're, you're getting started and you're not really sure what to start with.
So do you pick a winner in the book?
Um, you know, I, I didn't in the book, but I, I think, I think pytest is a clear winner for me because of the fixture mechanism that's built in.
Plus it's a superset.
Uh, pytest really does everything that the others do and more.
There's definitely applications that I, and I, when I got into it, I expected to, to pick one and like, not like the others.
I'm not there yet.
I think all, all three of those are reasonable.
Uh, the most reasonable is, probably unit test and pytest.
Those are the two.
Yeah.
Unit test is probably the most, what, like straightforward.
I, I don't think it's straightforward.
I think it's, I think it's the most confusing to start with, because it's, it's this X unit style that came from Java that you have to derive from a, you have to derive from a test case class.
And also you can't, I mean, they discourage you from using straight asserts.
You should use these assert helper functions.
And, you know, I, I think there's more to memorize.
If you, if you're just starting out, pytest is a lot easier.
And there, there, I don't, I don't think any, anybody new to this should use nose, because it's not really supported by a very, I don't even know if it is supported anymore.
There, there has been a little bit of effort on it, but not much.
Uh, but there's, I included writing about it because there is, there's quite a few people that still use it.
And if, if you're not, if it's not your decision and it's your job to use it, then I want to, I want to have a reference for people to be able to come up to speed quick.
I think I'm going to, I would like to write a follow-up book.
So the, the book I have now, it's just a, like I said, it's a $5 collection of, of all of the, of a whole bunch of posts.
Um, but I'm, I'm, I'm, I write, I read a lot on a Kindle.
So I wanted to make sure that those sorts of posts were available on, for somebody to be able to read on a, a e-reader or something.
Yeah, nice.
And I'll be sure to put a link to the book and whatnot in the show notes.
But I, I do want to write a follow-up that, instead of just a collection of posts is actually in a, in a kind of a technical book format, and walks through stuff and doesn't repeat things too much.
Uh, and I don't, I don't know if I'm going to include no's.
I, I think that, I think it would be sufficient to just include unit test and pi test in the discussion.
Yeah.
Okay.
So, you know, six years ago, maybe the space looked differently and now you're like, all right, pi test is kind of the clear winner in some ways.
And then, well, unit test is a built in, so people are choosing it because it's built in.
I mean, it's also, I mean, for a lot of like algorithmic things, like in the things I do that are heavy on fixture use, pi test is a clear winner.
If it's, if you've got a whole bunch of tight algorithms and you're in test speed really is a, the, the overhead of the overhead of pi test isn't very much, but the overhead of unit test is less.
So if, if test speed really is a, if you're trying to catch every millisecond out of your test suite, unit tests will be a little faster.
Right.
Okay.
Good to know.
I'll probably get a bunch of hate mail from the pi test people, after, after this, but.
Oh yeah.
I think we've set ourselves up to receive a lot of, feedback on various areas, but.
There's a lot of respect between the people that are developing unit tests and the people that are developing, developing pi tests because they're, they're, they're, it's, there's two ways to solve the same problem.
And, they're learning from each other.
And, and I think having both around is a very good thing.
Yeah.
Yeah, absolutely.
All right.
A few more things I want to talk to you before, before I let you go.
Tell us a little bit about your podcast.
It, it was kind of a follow onto the book, right?
You wrote the book and you've got the website that's, that's doing a lot of good.
And you're like, you know, let's, let's make this more, more of a weekly, semi weekly sort of conversation with the world.
Right.
So the intent was actually to start off weekly and get more than a weekly, like maybe a couple a week, but, it's, I'm really trying to do one a week, but it's, I'm really trying to do one a week.
But it's often once a month.
The, I, I, I want to cover more topics that I can, then I can write blog posts about.
And so that's the real, the real reason why I'm doing the, the podcast is to try to cover more topics.
And also, things that I think somebody wouldn't necessarily read about.
Like, I did an episode on the waterfall model that I think, you know, it'd probably be an interesting thing to listen to.
But you know, pump somebody's probably not going to go read about the history of the waterfall model.
So I've noticed that a lot of my, my audience is coming from developers and from testers.
And I know that from my own experience as a developer that there might, there's huge gaps in my education where it comes to testing.
So a developer usually gets a test.
Uh, the introduction to testing is to talk about test driven development.
And the, writing a test part, we, we get a statement that says first write a failing test, but no information on how to do that or what the test should look like.
And, and then, on the other end, you've got testers that come, you know, maybe come from a different kind of background and they don't have a lot of the skills and education that developers had, but they're expected to write automated tests.
Now I really want to, on both sides, I want to fill the education gaps in both testers and developers to, to fill all those gaps in.
And I know that people are busy.
They've already got a ton of stuff to do.
So I thought an audio format would be a good way to do that.
So people can, you know, get a little bit on their way to work or whatever.
Yeah.
And it's definitely a different type of interaction than a blog or, or a book, right?
Even than it, even different than an audio book.
You know, you can just fire up your podcasts while you're driving, biking, walking, doing the dishes, whatever.
I really liked that format.
So obviously I guess I'm spending a lot of time on it, right?
Yeah.
And I also, I was finding that I wasn't writing as much as I wanted to.
And I thought maybe I could, and I have a less time now as I go into a manager role.
And I thought maybe it'd be easier to do a podcast than it would be to write.
But I've found out that it actually takes more time than writing.
It's a lot of work, but it's, it's also a lot of fun, right?
To hear back from everybody.
So I, I just love it.
And, one of the things I was worried about that my, so I'm, since I'm not a web developer,
I thought that a lot of the audience is from web development community, but the, I thought
maybe that would be a hindrance.
But when I was talking to Harry, I think there's a lot of similarities to how, how web systems
go together and, and complex embedded systems.
So I think, I think it all works out.
Yeah, I would say so.
And I think the diversity of viewpoints, it's super helpful.
Like not everybody's writing straight up web apps.
So plus I've heard, heard from a lot of people, that I would have, would never have heard
from otherwise.
Yeah.
That's, that's really cool.
So I'm really glad to see it going well for you.
That's awesome.
I know we spoke just a little bit before you guys started.
So that's cool.
Good to, good to see it going.
And speaking of that, we are both from Portland and something awesome is happening in Portland
in June, right?
Yeah.
PyCon is here.
Yay.
PyCon comes to our hometown.
I happen to be living in Germany for a year, so I'm flying like 12 hours to get there, but
nonetheless, I'm still going to go.
It's going to be awesome.
Are you going?
Yeah, definitely.
Um, and I, I put, actually I've, I've submitted, four proposals, three talks and one
tutorial.
I don't know if I'll get any, but we'll see.
Oh, very nice.
That's awesome.
So hopefully, hopefully they do get accepted.
That'd be great.
Yeah.
So if people are going, I'm sure a lot of listeners are going to go, feel free to reach
out to me and I'm sure Brian, you'd be interested in meeting people that want to chat as well.
So.
Yeah.
What, one of the things we talked about is giving away some copies of my book.
Yeah.
So if you go to talk python.fm and at the top, it says friends, the show, long as you
are subscribed on that list, all it takes is an email address.
We will, I will, I suppose only one of us will do this randomly choose.
What do you say?
Five copies.
Yeah.
Let's give away five.
Awesome.
So on the week that this show comes out, I will randomly choose five listeners from the
friends of the show and we will be shipping you eBooks of Brian's testing Python testing
book.
Yeah.
Unfortunately, it's got a really long title that I don't even remember.
We'll ship you the book about testing with a really long title.
No, no, it's good.
We'll definitely send you an eBook copy.
So sign up and you'll be in the running.
Thanks for doing that, Brian.
That's awesome.
All right.
Parting thoughts.
I always ask my guests, well, unless we run out of time.
If you're going to write some Python code, what editor do you use?
I use Sublime, but I use it for everything, not just Python code.
Sublime is good.
Very nice.
And PyPI packages.
What one's your favorite or people maybe don't know about they should?
Well, this is probably nobody's going to care about this, but my favorite is PyVisa because
I couldn't do my job without PyVisa.
Nice, nice.
Yeah.
So PyVisa for talking to the machines.
That's cool.
And then maybe I'll throw in pytest as well, right?
Because that's not built in.
Oh, right.
Yeah.
I guess I should have brought that up.
Perhaps.
No, no.
It's all good.
They all go together.
One of the things, because it's not a package, but I'd like to do a shout out to the Anaconda
team or whoever does that because that's the distribution that I encourage people at work to use.
They're doing really amazing stuff.
Yeah.
That's Travis Oliphant.
And the Continuum guys, they were on show 34 and they definitely make Python in general
more accessible, especially on Windows.
So very cool.
Yeah.
It's actually that show that got me to download the Anaconda package and try it out.
Oh, nice.
Very cool.
So final call to action before we say goodbye.
Subscribe to your podcast.
How do they do it?
Oh, yeah.
On the pythontesting.net slash podcast, there's a bunch of information there.
And I've also got a, I send people information.
I've got a little email newsletter that goes out whenever I post anything new.
You can reach me on Twitter at Brian Okken or the podcast is at test podcast.
Awesome.
And all that's going in the show notes.
Brian, this has been really fun and it's interesting to get different opinions on testing.
So thanks so much for sharing yours.
Oh, yeah.
Thanks a lot for having me on.
You bet.
Talk to you later.
This has been another episode of Talk Python to Me.
Today's guest was Brian Okken.
And this episode has been sponsored by Hired and SnapCI.
Thank you guys for supporting the show.
Hired wants to help you find your next big thing.
Visit Hired.com slash Talk Python to Me to get five or more offers with salary and equity presented right up front.
And a special listener signing bonus of $2,000.
SnapCI is modern, continuous integration and delivery.
Build, test, and deploy your code directly from GitHub.
All in your browser with debugging, Docker, and parallelism included.
Try them for free at snap.ci slash Talk Python.
You can find the links from today's show at talkpython.fm/episodes slash show slash 45.
And be sure to subscribe.
Open your favorite podcatcher and search for Python.
We should be right at the top.
You can also find the iTunes and direct RSS feeds in the footer of the website.
Our theme music is Developers, Developers, Developers by Corey Smith, who goes by Smix.
You can hear the entire song on talkpython.fm.
And don't forget to check out the new podcast t-shirt at talkpython.fm/shirt
and share your love for Python with the whole world.
This is your host, Michael Kennedy.
Thanks for listening.
Smix, take us out of here.
Haven't been sleeping.
I've been using lots of rest.
I'll pass the mic back to who rocked it best.
I'm first developers.
First of all, first of all, first of all, first of all.