How we used Please to conduct testing of systems written in different languages

Given the current pandemic I find myself in the position of being one of the lucky ones. At the end of last summer I started a new role as a backend QA. It is my first foray into full backend testing and it’s in a completely new domain. It’s fair to say that I’ve already learnt a lot.

In yet more firsts I discover that my new company also relies on a build system which I had never come across before called Please. Please has had some great success as of late in that it was number one on Hacker News, however; like me I imagine that many of you may never have come across it. I have therefore added a synopsis of the problems which it aims to solve below:

If you have an ecosystem of multiple languages (which company doesn’t?) it is challenging to manage all of the various intricacies across multiple build systems and CI pipelines. To keep things sustained different parts of projects use different technologies and tools. It solves the immediate issues but it is very hard for teams because they struggle to grapple with different sections of the repository (if you’ve adopted a mono repository) or projects. This is typically a case in point for me as a QA who has had to cross between Java and Javascript in one role, and Python, Java, Kotlin and Swift in another as I’ve been switched between teams and projects.

With Please the idea is that you can have that multiple language cake and eat it. It allows you to combine the pieces of puzzles from different languages into something called a BUILD file which you can then execute at your leisure. You can either execute it locally or in a CI through a uniformed developer experience . You can also add your own custom rules so it effectively allows you to build and shape your software execution around the needs of your business.

The above sounds great but what happens when you need to do some extensive testing? A few weeks into the role I was placed into a team who were building a test automation framework for their new features, the framework wasn’t ready and the features had a tight deadline. To assure confidence I was asked to manually check and verify data across the several endpoints which the incomplete framework would later go on to check. Given the number of endpoints and our need to generate some test reports to satisfy all requirements for our stakeholders, I set about trying to learn Please in the best way. This is the way of getting stuck in and see if it was custom enough to handle this use case, and answer that extensive testing question. Suffice to say that it was and this is how I did it.

  1. I understood the constraints for our scenario

The endpoints in question are written in Go and for security reasons they could only be accessed internally via a Go client. The reports had to be published in Confluence and each report had to be updated with values from the endpoints every day. This was so that we could determine if the endpoints were healthy. We either had to update the content in the Confluence pages by hand, or we could automate this with web scraping. Web scraping is Go is rather difficult due to it’s no-bells type system. The Go generics proposal ( has just been accepted so this may change in the future. Given this difficulty I spoke to the developers on my team, and we all agreed to use Python’s Beautiful Soup package for the web scraping piece.

2. I created a dedicated area for this task in our project

Please works on the concept of folder structures. A folder contains a BUILD file which details all files in the folder and what you would like to do with them. To that end I did the basics of setting up a new folder complete with a blank BUILD file.

3. I created a Go package to pull the data from the various endpoints into a csv file

Another first for me in that I had never previously used or worked with Golang. Given that 2 languages were in play there needed to be a bridge in between for the Python side to grab the data. I felt the simplest thing for the task in question was to use a csv file thus the data from the endpoints was decorated and written to csv.

An additional plus was was that I didn’t have to update any shell scripts or run any go build commands as I changed the files, Please auto detects any source file changes so it does all the rebuilding on your behalf.

4. I added a Go binary to my BUILD file

With the basics from step 2 in place, Please uses the BUILD file as a pointer to which files it should create binaries for and execute at runtime. To that end I added a Go binary which linked to my files, and it looked something like the one below:

name = "generate_endpoint_data_csv",
srcs = [
deps = [

The deps block is where you list your binary’s dependencies. Here we’re importing a go library that’s specified in our dedicated third party store which also uses Please.

5. I created the Python hookup

The content within the reports which needed updating were stored as HTML tables. I wrote a Python script which took the contents of the generated csv file from step 4, and converted each row into a table row complete with cell contents.

I then used the atlassian-python-api package to pull the contents of the Confluence pages, and I parsed them using beautiful soup to grab the tables in question. I then appended the converted csv contents to the table and uploaded the changes Confluence with a page update request.

There are a few third party packages in play here, so I made further use of the dependencies block which was mentioned in step 4 inside of a python binary.

name = "push_test_data_to_confluence",
main = "",
srcs = [""],
deps = ["//third_party/python3:atlassian",

6. I created the over arching Shell command to run this all as one Please command

I had 2 binaries which I could now run as separate commands but I wanted this test execution to be a one liner. Please supports Shell command execution so I added a command in to my BUILD file similar to the example below:

name = "upload_test_data_to_confluence",
cmd = "$(out_exe :generate_endpoint_data_csv) \\\\${@} && $(out_exe :push_test_data_to_confluence) \\\\${@}",
data = [

The one thing which caught me out was the additional escaping to allow parameters to be passed to the underlying scripts. Thankfully a little bit of trial and error and asking people very nicely for some help solved the problem :)

7. Time to run it and see if it worked

I ran the relevant Please run command below and all worked as expected

plz run //data_generation_test:upload_test_data_to_confluence -- --environment=test

We’ve use the double dash to indicate that the rest of the arguments are for my sh_cmd() rather than for Please.

Having never used Please before I was most certainly impressed with its speed. I also like how it glues tools together very easily, and I certainly see myself using it more in the future.

There were times when it took a while longer to work out how to use it, and this was probably owing to 2 things. The first being that as of yet, it is not as widely used as the likes of Gradle etc so simply Googling didn’t find the answers. The second reason is that I have come from a Java background, so I needed to take the time to learn its Python-esque build language. That was not dissimilar to learning Groovy and Kotlin for Gradle projects, or XML for Maven when I first started out.

Many thanks for taking the time to read this article. If you would like to know more about Please then I recommend that you start by checking out the website

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store