AgileData #23 -Agile Data Testing Techniques, a magical list of testing TLA's
1 Dec 2020 · 27 min
Shane Gibson and Nigel Vining compare data testing approaches: TDD, ATDD, and BDD, then explain reconciliation (left/right comparisons) versus validation (trend and anomaly checks). They cover sensors that monitor data between pipeline stages, linting tools like black and flake, and why analysts using Jupyter notebooks for early tests beats detached spreadsheet-based testers.
Chapters
Welcome to the Agile Data Podcast, where Shane and Nigel discuss the techniques they use to bring an agile way of working to the data world in a simply magical way.
Welcome to the Agile Data Podcast. I'm Shane Gibson.
And I'm Nigel Vining.
And in today's session, we thought we might kick off a bit of a series of podcasts around testing. So testing for us in the data domain is the bane of our existence. It's. We used to joke in the old days that when you had a waterfall project, no matter how much time you plan for testing, it always ended up being one day, and that was the day before you went live. And then our users would go and test in production for us.
There's been a lot of work done and testing in the data space, but in my view, it is still a very immature part of our domain, both in terms of tools that we can use and repeatable techniques and patterns that we should adopt. So Nigel and I thought what we'd do today is we would do a whirlwind tour of all the testing terminology and techniques we've heard of with a little bit of a micro description on each one. And then in future podcasts, we'll take each one of those and break them out into their own dedicated podcast. We talk them about them in more detail. So what do you reckon, Nigel? Is that what we should do?
It sounds pretty good to me and it's actually topical because this week I have been working on.
Daily data validation checks for a customer. So it's sort of top of mind for me at the moment.
Excellent. So validation, not reconciliation, but we'll get onto that. So let's kick off with some of the agile words that we use. One of the key things that people are doing when they do agile delivery now is TDD test driven. So for me, that is where we write the test first, then we write some code and we iterate the code until the code passes the tests.
I agree that is an approach that may be actually how I do do it. By default, I know the outcome I want to achieve. I iterate until I get that outcome. So I guess that's probably the one I naturally follow.
Right. So the second version is what we call acceptance test driven development. And for me that's where we focus less on the data and more on the features. And the reason for that is it is unusual for business user to be able to tell us what the acceptance test repeated. That piece of data is for them to say. On the 23rd of March at 11am, there were 1,329,251 customers. So what they tended to give us is acceptance criteria, which we tend to want to get as part of our user stories. And so those are things like, you know, as a user, I want to be able to. So that. And so for acceptance driven development, for me, that's where we are comparing that we've delivered what we need to deliver to pass those acceptance tests. The last one is behavioral driven development.
For me, that is understanding the way the data behaves. We tend to use rule based paradigm, a technique based out of Gherkin and cucumber, where we would write a test that something like given blah blah blah and blah blah blah and blah blah blah. Then.
Given a load of customer data comes in and the customer data is from the Salesforce system, then we would expect the customer ID to be in a format of blah blah blah. And so we are writing natural rules language type tests to make sure the data behaves that way. Or given we're loading some data and the data has regions, we expect to see five regions. And therefore when that changes, when the behavior of that data changes.
We get.
An alert or we do it. So for me, that's how I describe applying tdd, ATDD and bdd. And in a data world, I think the other thing that we use in terms of terminology a lot is the difference between reconciliation and validation of data.
So people often talk about reconciliation, but for us, reconciliation is where we can compare two things and they should equal each other. What's your view on that one, Nigel? Is that your definition of reconciliation?
Yeah, reconciliation. I automatically go to the, what we call the left right pattern. That's where we have something on the left which is generally a source, and we have something on the right which is generally a target or a report or an output. And if the numbers on the left match the numbers on the right, we say that's reconciled.
And so that gives us challenges, right, because does that mean we have to go and hit the data factory, that source system that's generating those numbers or that data for us to reconcile it?
That's a good question.
Sometimes. Or the alternative is, as we.
Build in some form of extract into our process, that at a point in time we have a record from that source system and it says at this point in time, which might be midnight, there were X number of customers or Y number of dollars or Z number of something. So we effectively pick a point in time and we draw a line in the sand and we say the source system said this was the state of play at that time. And then we can use that record to reconcile our right hand side to make sure everything's flowed through correctly.
And we'll talk about it more in the podcast dedicated to reconciliation. But we have other lighter techniques. Right. Where we can say, count rows on both sides of the left. Right. And see if they equal. So we have some heavy reconciliation processes and some lighter reconciliation processes. And we may want to mix the use of those reconciliation techniques depending on the risk of mutation of data between the left and the right.
Yeah, yeah, yep. Generally we start at a very high level. We just look at a summary of what's on the left compared to a summary of what's on the right. And if that's generally green, we don't always go to a more granular level. We say, hey, the topmost numbers match. You know, we're pretty happy with that. We don't go down to the next level.
And then when we compare that to validation. So within a data platform, we are constantly changing data. We are changing what it means, we're changing how it's stored, we are filtering and subsetting. So we might start off with a million rows and for a particular reason we'll end up with 100,000. That means we can't reconcile because the left never matches the right. But we still need to validate it. We talk about techniques we can use to validate that. When we're doing something bad to the data, we can validate that that expected result is consistent and doesn't mutate over time.
Yeah, and that's the, that's one I've been concentrating on this week. Actually, you're right. We can't directly compare left to right. But what we can do in this case in point, it was basically tracking sales per day.
For organization. Now the thing of sales per day is they change constantly. So actually the validation checks became.
To check that the averages weren't moving too fast. So today's sales were in line with what yesterday's were what they were last week and last month. So we're basically, over time, we're checking a trend that the dollars are moving where we expect, and they weren't suddenly halving between one day to the next or doubling between one day to the next, because we know that it should progress in a reasonably linear fashion. So we're using actually a moving average by day over a trailing period to validate data. So that's slightly different but reasonable approximation for that.
Yeah, so you're effectively, you're applying some anomaly detection to Validate the data's fit for purpose. Another example is when we talk about data quality metrics or data profiling of the data, we often want to validate that the data has no nulls in a table that we're receiving or a table that we're creating. So we write tests to validate it. Right. We use data quality profiling to tell us we've got a problem, but we should really be writing tests to tell us when that behavior happens. So again, data quality and validation testing for me kind of goes hands in hands, right? Because it's identifying the data is not valid. It's not fit for purpose for what we expect it to look like.
I think one of the other things that we need to talk about in one of the podcasts is this idea of testing techniques we can use when we lightly couple our data platform or lightly decouple it. So we talked a while ago in one of the podcasts about this idea of Pac Man. Pac man achieves a task. Some data comes into Pac Man. Pac man does some stuff to it. The data exits Pac Man. What that means is we can use some techniques that are likened to sensors. So between each of the Pacman, we can write sensors that sniff the data as it goes past, and those sensors can have a set of rules or tests that are related to them. So imagine if we had a sensor that sniffed data and said, identified where that data had nulls and a record. So rather than writing that test every time we have a table to say, is there a null? Or writing a test and applying it, we could have a sensor that says whenever data moves between moving parts and they're like slightly coupled or decoupled, sniff it and where you see nulls raise an alert. Right. So it's a technique we can use to write the test once and apply it many as part of our data pipeline or our data supply chain, rather than having to remember to apply that test. So I think, you know, let's talk about that in one of the podcasts about that emerging practice and, and how hard it is and whether it's a good idea or not.
Yeah, I agree. I actually, that one resonates with me. That's quite a nice one because you're right. We write it once. We effectively just mark it as something we want to do every time we run a process, and it just happens magically.
You know, it's a. It's a nice pattern and it's a common sense one.
So one of the other challenges we have is once the data has been made fit for purpose within a data platform. We then have a bunch of reporting or visualization or analytical tools that consume that data and typically do something with it. And those, those tools are typically decoupled. They're either doing, you know, some form of direct query where they're grabbing the data out of the data platform on demand, or they're grabbing the data on a repeatable basis and storing it within, within the tool itself. But regardless of those techniques, that data is persisted either in memory, on disk within that BI tool or that visualization tool. And those tools have a lot of capability.
To change that data after the fact as well. But if we just look at that first thing around consumption, if I have a report that's pulling data out of a table on the data platform, how do I know that that tool is actually bringing the data back properly? How do I know it's not got something in that query to bring it back that's restricting the number of rows? How do I know that I have a million and one customers in my final consumable table and that when it going back into my tableau dashboard, tableau is actually seeing a million and one customers? That's a bit of a problem for testing, isn't it?
Yeah. What actually also came to mind, something I've seen recently, is if the underlying data layers or the consumer layer that the tools are plugging into haven't been thought out for safety of use. And what immediately springs to mind is non additive measures turning up in your consumer layer. You end up with a situation where the tool applies an average on an average or an average of a field that can't be averaged. And it's all very easy, but straight away you've let the user do something wrong because you haven't protected them in some way.
That's what always worries me, presenting something in the consumer layer that the tool can get wrong without any real warning or consequence.
And with a lot of the tools that we use in the data space, they're starting to adopt this idea of being able to embed or call tests within, within those tools. But the BI tool is not so much still, right? It's, you know, I don't know of many tools, if any really, where I can write a test that when a dashboard's been rendered I can validate that the numbers on the dashboard are correct, that they meet my, they're valid, they meet my expectation. So I think, you know, tooling wise, that's a pretty light area. And maybe before we do a deep dive on that podcast, we might need to go and do some research on the, on the market to see whether actually any of the new breed of VIS tools are dealing with that for us. I think another one that I hear a lot and I don't write code, so I don't really know a lot about it, is this concept of linting.
What do you understand linting as?
Sure. So we under the covers of Agile Data IO, we use.
Linters and formatters effectively to keep our code clean, readable and syntactically correct. So we use a formatter. In this case we use black for Python, which whenever we commit code we run the black library over it and all it does is it checks that all the indentation is correct, spacing is correct, and the code's laid out nicely to a a standard template. This has benefits for people coming along downstream reading the code. The code is presented in a pretty format, I guess, and it also identifies any formatting issues. The other one is we make light use of Flake, which is a linter. A linter is effectively a library that we run over our code and it looks for syntactical or construct errors. So the code may be formatted correctly, but but it may have errors that are unforeseen. You might be adding two things that on the surface it looks like you're adding them, but you're actually concatenating them together. So it can help find syntax and construct errors that maybe aren't obvious and would pass tests, but possibly shouldn't. So they help keep us safe and keep our code readable.
So it's not testing that the data is valid or reconciled, but it's.
Testing that our code meets our standards and it has a chance of running and executing successfully.
Anything obvious that is correct.
Yep.
Cool. Wish I had that in words. That would be great. So let's talk before we finish off about some anti patterns. So where we see testing behavior being less than desirable. So I remember a project that we both worked on before we started agiledata IO where.
There was a testing team of eight people that weren't part of the delivery team. They sat in their own part of the floor and they read the requirements that were written, which was a bit of an issue because we were following an Agile way of working. So our requirements were light specific for the tasks that we're going to achieve in that iteration and constantly evolving and changing as we learn new things. Then they would create these massive Excel spreadsheets of the tests, a list of tests they were creating. Each of those tests were Written in code. So that was impressive. So they were code based tests rather than clicky, clicky, gooey point and human testing. But that code base had to be run manually.
Unfortunately for the testers, it tends to have to be run outside of standard working hours when the delivery team were doing all their hardcore work and then every time something major changed, all those tests had to be completely rewritten and completely re executed. So those, those eight testers were very, very busy. But I'm not sure that they were really that efficient or effective. So for me that was an anti pattern on how we do testing where we have a separate team. They're working off documents rather than conversations, they're out of sync, they're always late to the party and every change is massive and kills them. So for me that's probably an anti pattern that I see time and time again.
Yeah, the Excel one's interesting. Funnily enough, that's something else I've had experience with this very week.
I find a lot of testers naturally gravitate to Excel because it's a known quantity and it's the first place they cut and paste data and then they put a if column A equals column B, put a tick, otherwise put across and format it read. And they tend to automatically adopt that because it's a nice easy way that they paste data and they get all the red rows and then they pass them back. But you're right, for all the reasons you expressed, it's a very manual, non repeatable process and you have to keep doing it over and over. So I tend to take the approach that.
If they come up with all the logic to get their test data, I would then generally drop that into a repeatable scheduled tool or process to actually run it for them automatically every time maybe code's released or every day to check the overnight numbers to try and take it out of the spreadsheet realm and put into something a little bit more enterprise level, I guess. Yeah.
And so automation helps, right? It helps reduce the cost of rerunning tests, which means we feel more comfortable running them earlier, running them more regularly, more often.
Yep.
I remember again there was a pattern I saw in one project and it wasn't an anti pattern because it had some of the tenants of automated testing, some of the tenants of being able to adapt to change. But this one was one of the team members, was the tester. He was a very experienced tester and what he'd done is he'd built a testing toolkit effectively. We talked a while ago about the Old days where you had your diskette in your top pocket with your sample code. So he had one of those. What he would do is he would take the design documents and he would write all the ETL code. Again, the delivery team, the data engineers would write the code and he would write the same code but write it differently. And his tool and then he would schedule their code to run through the scheduler overnight and his code to run through his scheduler overnight. And then he would automate the comparison, the reconciliation of the left right of both those runs. So you could quickly, when you walked in the morning, get a view of where it matched, where it reconciled and where it didn't Challenge then was who's right? Was it purely a coding error on his part or the data engineer? Or again, was it because we were running an agile way of working? Was it the fact that the engineer had discovered some issues with the data as they applied the rules, they had gone and had a conversation with the team and the stakeholder and the product owner would make a call and therefore they changed the code and the documentation was out of sync. So again, you spend a lot of time going down the rabbit hole of, for the ones that flagged red, why were they red? But you know, one of the patterns or techniques out of that was it was automated, which was great, right? It did save time from that point of view.
I see. I do remember, I do remember that pattern and I do remember that guy. And it was a work of beauty. It was slightly misplaced, but it was a pattern. But the fact it was based on documentation that quick was always becoming stale because of evolving things. It was its only downfall. But yeah, I know credit to that person, it was a pattern.
But also there was twice as much effort, right, because we weren't writing tests, we were writing code and the tests were automated.
It was a very elaborate test approach. And you're right, most of the rabbit holes were due to requirements that have moved on between the time that the test was created and run.
I think the last one is an interesting one that I thought was a good pattern actually. So what happened was as the team revolved their agile way of working, the BA type skills within the team, the data analyst type skills started doing more and more of the data modeling. So as part of the early exploration of data and understanding the information product that needed to be delivered, they started doing some exploratory work on the data and some exploratory work on what a light work on what a data model might look like to support the outcome that was required.
As they got those skills, they started writing tests in Jupyter notebooks. They would take the data and quickly model in Jupyter notebooks to figure out where it fitted. And then as part of that, they started to see where the data was mutating against or wasn't valid for what they were doing. So they then started writing tests for that. And then when that light version got handed across to the engineer because it was still a semi pipeline process, the engineers would go through and write their code and harden it and do all the good stuff. And then the analyst type people would then come back in and effectively repoint their jupyter notebooks at the new data source. I mean, it wasn't a one for one point. Right. Because the model had morphed slightly as they went through. As always, as you know, the expectation of the model hits the real data. But that mutation of requirements didn't or change requirements didn't happen as often as it used to because the requirements have been developed in line with the data. So they would repoint the Jupyter notebooks at them with a little bit of rework and then rerun them. And so again, it was a form of testing early. Right. And then reapplying those tests. So I thought that was a good way of working for the maturity of the team. I thought it was creative and added value. Right. Reduce their time, help them adapt to change and gave them a better quality data outcome.
Yeah, I think that's probably a nice example of I guess a mixture of test driven development and requirements. Test driven development or sort of iteratively smashed together. Yeah.
So we would call that a combination of TDD and bdd. So test driven development and behavioral driven development, because that's the one.
Applying a couple of the concepts from both of those wasn't really acceptance driven because it wasn't based on the user stories or the acceptance from the product owner of what good look like. But that's okay. So I think that was a whirlwind tour. So we talked about TDD versus ADTDD versus bdd. So we might deep dive on that. In another podcast we talked on the difference between reconciliation and validation and how we use a technique of left right for reconciliation and how we use gherkin and rules type frameworks for validation. We talked about some of the ways we could be really innovative and decouple through the concept of sensors to write, ability to test for certain or validate certain things. Repeatedly we talked about some of the things like linting that help us have better quality code. And we talked about the challenge of BI visualization and analytical tools being decoupled or lightly coupled to the data and how hard that makes it for us with those types of tools to to reconcile and validate end to end from the data factory out to the consumer. So I think we'll, we'll pick one of those next and spend another half hour deep diving into one of those on the next podcast.
Sounds fantastic. Thank you.
Excellent. All right, well catch everybody later.
And that Data Magicians was another agile data podcast from Nigel and Shane.
If you want to learn more about.
How you can apply agile ways of working to your data, head over to agiledata IO.
More from Shagility


Listen now | Recording of AURA - Tim Frazer & Shane Gibson on 2nd September 2026








