Email Subscription Form

Friday, May 24, 2019

Merge Conflict Resolution for the Confused

Anyone working with version control software such as Git will eventually come across a merge conflict.  If you are new to working with Git, here is a simple example of a merge conflict:

The master branch contains a file with this text:
Kristin Jackvony was here on May 22, 2019

Prunella and Joe each check out a version of this master branch.  Prunella makes a branch called "Prunella" and Joe makes a branch called "Joe".  

Joe updates the file in his branch to read:
Kristin Jackvony was here on May 22, 2019
Joe Schmoe was here on May 23, 2019

Joe does a pull request for his file changes, and they are approved and merged into the master branch.

Shortly thereafter, Prunella updates the file in her branch to read:
Kristin Jackvony was here on May 22, 2019
Prunella Prunewhip was here on May 23, 2019

She also does a pull request for her file changes, but because she no longer has the latest version of the master branch, there is a merge conflict.  Git sees that she wants to add her name to the second line of the file, but her version of the master branch doesn't have anything on the second line, whereas the new version of the master branch already has Joe's name on it.  Prunella will need to resolve the conflict before her changes can be merged.


I'll be honest; I really wanted to master resolving Git merge conflicts for this post. However, resolving them from the command line still confounds me!  Fortunately, I've found a number of different ways to handle merge conflicts so that they no longer fill me with dread.  Below I'll discuss six steps for handling a conflict.

Step Zero: Avoid Having a Merge Conflict In The First Place

By using the helpful hints in last week's post, especially tips one, two, and six, you can avoid creating a merge conflict.  Doing a pull from master is always a good idea before you do anything code-related.

Step One: Don't Panic

When you have a merge conflict, it's important not to thrash around trying "git this" and "git that".  You might make things more confusing this way.  A merge conflict will eventually be solved, even if you have to resort to asking for help (Step Seven).  And you can't possibly have done anything irreversible; that's the beauty of version control!

Step Two: Resolve the Conflict from Within GitHub 

GitHub has an easy interface that will allow you to resolve merge conflicts.  Simply click the Resolve Conflicts button and observe the conflict.  It will look something like this:

>>>>>HEAD
Joe Schmoe was here on May 23, 2019
=====
Prunella Prunewhip was here on May 23, 2019
<<<<< Prunella

All you need to do is decide which entry you want to go on line 2, and which entry you want to go on line three, and make those edits, deleting the extraneous symbols and branch names along the way.  When you are done, your file will look like this:

Kristin Jackvony was here on May 22, 2019
Joe Schmoe was here on May 23, 2019
Prunella Prunewhip was here on May 23, 2019

Now click the Mark as Resolved button, and your pull request should be ready for merging.

Step Three: Resolve the Conflict from the Command Line

If you are using Git as a version control system, but you are not using GitHub to host your repositories, you may not have a nice UI to work with in order to resolve your conflict.  In this case, you may need to use the command line.  

What I do in this scenario is open the file with the merge conflict in a text editor such as TextEdit or Notepad++, I edit the file so that it looks the way I want it to, removing all the extraneous symbols and branch names, then I do a git add with the filename, and then a git commit.  I do this in accordance with the instructions found here: https://help.github.com/en/articles/resolving-a-merge-conflict-using-the-command-line.  However, I have only had success with this once or twice.  Usually I have to go on to Step Four or Step Five.

Step Four: Forget About Your Existing Branch and Make a New One

In this scenario, I copy the text of the entire file with all my changes, and I paste it somewhere outside the code.  Then I go to the master branch and do a git pull origin master. Now I should have all the latest changes.  Then I create a brand new branch, switch to that branch, and paste in all of my file changes.  Then I do a fresh new pull request, which won't have a merge conflict.

Step Five: The Nuclear Option

If Step Four failed to work, I exercise the nuclear option, which is to delete the entire repository from my machine.  Before I do this, however, I make sure to make a copy of my file with all my changes and paste it somewhere outside the code, as I did in Step Four.  Then I delete the entire repository and clone it again.  Then I continue as I did in Step Four, creating a new branch and switching to it, making my changes, and doing a brand new pull request.

Step Six: Ask For Help

If all else fails, ask someone for help.  There's no shame in asking for help with a particularly thorny merge conflict!  If you followed Step One and didn't panic, your helper will be able to see exactly what you've done so far and can help you arrive at a solution.

Git purists may argue that merge conflicts should be resolved the right way (using Step Two or Step Three), and they are probably right.  But doing Step Four or Step Five can keep you from wasting time trying to resolve the conflict, and they also will keep you from defenestrating your laptop!

Saturday, May 18, 2019

Six Tips for Git Success

Last week, I wrote a Gentle Introduction to Git, which was designed to give testers a general overview of how version control software works, from cloning a repository to submitting a pull request.  Even when you understand how Git works, it can still be a bit mysterious, because there is so much happening that you don't see.  The command line does not offer a visual interface to show you what branch you are on, or when the last time was that you pulled from the master branch.  So in this post I'll be describing six tips that make using Git easier.



Tip One:  Run git status frequently

A common mistake that Git users make is to do a bunch of work and commit while on the wrong branch.  Because I am not a Git expert and I'm never sure how to recover from this mistake, I run git status very frequently.  I always run it as soon as I've opened the command line and navigated to my repository, so I won't be surprised by what branch I'm on. 

Running git status is also a good way to find out what files have been changed in your branch.  Sometimes we make a change to a file for debugging purposes and we forget to change it back.  If you run git status, it will alert you that a file you didn't want to change has been altered.

Tip Two: Pull from the master branch before you do anything

Before you start changing code in your branch, you'll want to make sure that your branch has the very latest code in it.  Otherwise, you may be updating code that doesn't exist any more, or you may be duplicating work that has already been done.  By making sure that you have the latest code, you will also avoid creating a merge conflict, where your branch and the master branch have differences that the version control system doesn't know how to handle. 

Once you have pulled from the master branch, remember to switch to your own branch!  If you are running git status frequently, you'll notice if you've forgotten to make the switch.

Tip Three: Add all of your changed files at once

If you have changed a number of files, you'll find it tedious to type
git add <insert long file name here>  over and over again.  A quick way to add all of your changed files at once is to use git add -A.  Just be sure when using this that you want to add all of your files.  I don't know of a command that will let you add all the files except one or two.  If you know a command for this, please comment on this post and share it with everyone!

Tip Four: Name your commits something helpful

When you commit your files, adding a commit message is optional, but most companies expect their employees to do it.  Make it easier on yourself and everyone else by naming your commits something that will make sense later.  "One line code change" is not a very helpful commit message.  "Adding test for new contact info endpoint" provides much more detail. 

Tip Five: View your git logs in a single line

It can be hard to remember what you've done in Git, because there's no UI to show you.  This is where git log is helpful.  The log in its full version will show you the last several commits made, who made them, and the date and time they were made.  I find it's easier to read the logs when they are condensed to a single line; to do this, type git log --pretty=oneline. To exit the log, type q

Tip Six: View the diff of your files before you do a pull request

If you are running git status frequently, you probably won't commit and push any files that you didn't mean to push.  But it's still possible to accidentally commit code you didn't mean to commit in a file that has the changes you want.  So before you do a pull request and ask someone to review your code, view the "diff" of your files, which simply means looking in GitHub and comparing the files in your branch with the files in the master branch to see which lines were changed.  Make sure that there are no code changes in the file that you didn't want to commit, such as commented-out code or debugging statements.

If you find that you've accidentally pushed something that you didn't mean to, simply change the file to what you want it to be and add, commit, and push it again.

Hopefully you will find these six tips helpful as you work with Git!  In next week's post, I'll talk about how to handle the dreaded merge conflict.




Saturday, May 11, 2019

A Gentle Introduction to Git

For a software tester who has just started writing test automation, using version control software such as Git can seem daunting and confusing.  But being able to pull down the latest code, update it, and submit a pull request is very important for any team project!  In this week's post, I'll provide a gentle introduction to the basics of Git.

What is Git?

Git is a version control system.  A version control system is a system that allows a group of people to collaborate on code without accidentally overwriting each other's work.  It also allows the group to keep track of who changed the code and when it was changed, so it's easy to trace back to the source of a problem.

Why is Git needed?

Consider what file editing is like when you don't use a version control system.  Let's say you have a recipe for brownies.  You send the recipe to your friend, and he decides to change the amount of cocoa in the recipe.  When he makes that change, it is only in his version of the file, not yours.  Your files are now different.  If you make a change to add more vanilla to the recipe, now your versions have diverged even further. 

You can see how this would be unacceptable for software code!  In a version control system, there is one "master version" which is the accepted version of the code.  This master version lives in GitHub (or another version control hosting service), and can be "pulled" down by any user.  When someone wants to make a change to the code, they pull down the master version of the code, create a "branch" that is a copy of the master version, make their changes to the branch, push the branch up to GitHub, and then do a "pull request", which is asking for someone to review their code and merge it into the master branch.

Confused?  Don't worry, this will look much simpler with an example.  Let's imagine that we have a source code repository called "The Thinking Tester Guestbook".  We'll take a look at what would happen if Prunella Prunewhip wanted to add her name to the guestbook.

These instructions assume that Prunella has already installed Git on her computer, and has already created a GitHub account.)


Step One: Prunella clones the source code repository

This is often called "cloning the repo" or "pulling down the repo".  Prunella does this by going to the URL in GitHub that has the source code, and clicking the green "Clone or download" button.  A dropdown appears with the URL she will need to clone the source code.  She clicks the little clipboard button to the right of the URL to copy the URL text.

Prunella opens up a command window and navigates to the folder where she would like put the source code.  Once she's there, she types git clone and then pastes the URL text next to those words.  The repository is copied from GitHub into a new folder.

Now that the repository is in a folder on her computer, she can open the folder up in her file browser and take a look at what's in there.  She sees that there is one text file, called "guestBook.txt".  The text file reads:

Kristin Jackvony was here on May 11, 2019

Step Two: Prunella makes a new branch and adds her changes to that branch

Before Prunella makes any changes to guestBook.txt, she should create a new branch and switch to it.  So in the command line, she navigates to the new folder that was cloned earlier by typing
cd ThinkingTesterGuestBook.

She can verify that she's in the master branch by typing git status, and she will get a response like this: On branch master.

Now she can create a new branch and switch to it by typing git checkout -b NewEntry.  The command "-b" tells Git to create a new branch.  "NewEntry" is what Prunella has chosen to name her branch.  And the command "checkout" is what causes Git to switch to the new branch.

If Prunella types git status at this point, she will get On branch NewEntry as a response.

Now that Prunella is in the correct branch, she's going to make a change to the guestBook.txt file, by adding one line, so that the file now reads:

Kristin Jackvony was here on May 11, 2019
Prunella Prunewhip was here on May 13, 2019

Step Three: Prunella commits her changes and pushes them to GitHub

Now that Prunella has made the change she wanted, she needs to commit and push her change.  First, she can run git status and she'll get this response: 

On branch NewEntry
modified: guestBook.txt

This shows that the guestBook.txt file has been modified. Next, Prunella needs to add the file to the commit, by typing git add guestBook.txt.  Now if she types git status, she'll see this response:

On branch NewEntry
Changes to be committed:
     modified: guestBook.txt

Next, Prunella commits her change by typing git commit -m "Adding a new entry".  The "-m" in this command stands for "message".  The "Adding a new entry" text is the message that she is adding to explain what she is committing.  The command line will respond with how many files and lines were changed.

Once the change has been committed, Prunella can push the change up to the GitHub repository by typing git push origin NewEntry.  The "NewEntry" value explains that the code should go up to the NewEntry branch, which doesn't exist yet in the GitHub repository, but it will be created with this command.  "Origin" refers to the GitHub repository (this is also referred to as "remote").  The command line will respond with several lines, the final line of which will be
* [new branch] NewEntry -> NewEntry, which shows that a new branch called NewEntry has been created in the origin, and that it was copied from the local branch Prunella created, which was also called NewEntry.

Step Four: Prunella creates a pull request in GitHub

Now that her new branch has been pushed up to GitHub, Prunella can submit a pull request to ask that her changes are merged with the master branch.  She does this by going to the GitHub repository and clicking the "New Pull Request" button.  This takes her to the "Compare" page.  She makes sure that the left side of the comparison is the master branch, and then she chooses the NewEntry branch from the branch dropdown.  She can see how the guestBook.txt file has changed; the new line she added is highlighted in green, illustrating the difference between the two files.  (If she had deleted a line, the line she removed would be highlighted in red.)  Finally, she clicks the "Create Pull Request" button.

Step Five: Prunella's pull request is approved and merged

The final step in the file change process is that the owner of the repository (or any teammates who have approval permissions) will review the change, approve it, and merge it.  Now if Prunella changes to the master branch by doing git checkout master, pulls down the changes by doing git pull origin master, and takes a look at guestBook.txt file, she will see that her entry has been added:

Kristin Jackvony was here on May 11, 2019
Prunella Prunewhip was here on May 13, 2019

And that's all there is to it!  In my next post, I'll add a few more Git tips and tricks, but these steps should be enough to get you started with committing your own code to your team's repository.

Saturday, May 4, 2019

Seven Excuses Software Testers Need to Stop Making

Last summer, I read an interesting book called Extreme Ownership.  Written by two Navy SEAL officers, it describes the concept of taking responsibility for every facet of your job, even those things that you feel that you have no control over.  If one of their soldiers made a mistake, the officers would take responsibility, because they could have trained the soldier better.  If their commander made a poor decision, the officers would take responsibility for that as well, because they could have "managed up" and provided information that would have led to a better decision.  When everyone exercises Extreme Ownership, a culture of excellence and achievement is the result.

Extreme Ownership can be applied to any career, including software testing!  Yet, there are a number of excuses that I often hear software testers make.  Excuses keep us from taking full ownership over our work, and keep us from being taken seriously.  Below are eight excuses that software testers need to stop making.


Excuse #1: I don't know how the feature works

All too often, testers simply follow the meager directions left for them by the developer in the software story, without have any idea what they are doing.  For example, "Run this SQL query and verify the result is 1".  Why?  What information is this query obtaining?  How do you know that this answer is the right one?  If it turns out there is a bug related to this feature, how can you possibly say that you've tested it?

When you are presented with a story to test that you don't understand, start asking questions.  If the developer can't explain the feature to you, find someone who can.  Restate the information that you are given to make absolutely sure that you understand it correctly.  Ask for the information to be presented in a way that makes sense to you.  I am a visual learner, and the developers on my team know that if I don't understand what they are trying to explain to me, it's time for them to draw me a diagram.

There have been many times where I have uncovered bugs in a feature even before I've started testing, simply by asking questions about how the feature works!

Excuse #2: There's no way to test the feature

Really?  There's NO way to test the feature?  How does the developer know that the feature is working then?  Are they just sending it to you and hoping for the best?  There must be SOME way for your developer to know that their code is working.  What is that way?  Can they show it to you?

There have been some features that I was unable to test myself because I didn't have access to the back-end system that was being used in the feature.  When this is the case, I make sure to work with the developer and have them show me that the feature is working.  Then I can ask them to try various test cases while I watch, so we are effectively pair testing the feature.  In this way, we can uncover any bugs that may exist.

Excuse #3: The developer coded it wrong

I have sometimes seen instances where a developer misunderstood the requirements of the feature to be built and created it incorrectly.  This is why it's important for everyone on the team to understand the requirements and to see to it that acceptance criteria are included in the story.  If you test the story based solely on what the developer tells you, and don't verify exactly what was supposed to be built, then the fault lies with you.  You are the tester- usually the last line of defense before the product goes to the customer.  Make sure the customer is getting the right thing!

Excuse #4: The other tester on my team missed the bug

Even the best of software testers misses a bug now and then.  That's why it's important to have at least two sets of eyes on every feature.  It's the policy on my team that when one tester is finished testing a feature, another tester tests the feature in the next environment.  The week after I instituted this policy, one of my co-workers found two bugs I missed!

If you are the only tester in your company, set up a "bug hunt" where everyone in the company looks for bugs.  Don't be embarrassed if someone finds something you missed; when we test the same thing over and over again, we can sometimes develop inattentional blindness.

Excuse #5: There wasn't enough time to test

Let's face it: there will never be enough time to test everything that you want.  Software developers have time constraints too; they would probably really like to refactor their code a few more times before they hand it over to you, but they are working with a deadline just as you are.  So instead of making excuses, test the most important things, and manage your time wisely.

Excuse #6: If I log the bug I found in Production, I'll be asked why I didn't find it sooner

This was a new one to me when I heard it a couple of months ago.  There may be some managers who blame testers for finding bugs, but these managers are misguided.  It's up to us to educate our team about what testers do.  We simply can't find every bug; there are just too many ways that software can go wrong.  What we can do is report what we find as soon as we find it, and keep an eye out for similar bugs next time. If you don't report that bug in Production, it will go unfixed, and the next person to find it will be a customer, or the CEO of your company!

Excuse #7: I don't know how to code

Software development has changed significantly over the last two decades.  Companies used to release software every six months, so testers had tons of time to do regression testing.  Now software is released every week or two.  It's simply not possible to manually test an entire application during that time frame.  This is why automation is necessary, and why you need to learn how to automate!

You don't have to take a college course in Java to learn how to code.  All coding languages run on some very simple logical principles that are easy to understand.  The only tricky thing is the syntax of whatever language is being used, and the more you expose yourself to the code, the more you will understand.

If there's no test automation at your company, see if you can get one of your developers to write some tests.  If you have software testers who are already writing automation at your company, ask them to walk you through their tests.  Learn how to make a simple change to an automated test, such as changing an assertion that says "true" to one that says "false".  Copy a test that verifies the value of a text field, and see if you can change it so it verifies the value of a different text field.  Learn how your company's version control system works, and see if you can submit a code change for your team's approval.

Take small steps!  You don't have to learn it all at once.  Think of learning code as learning a new language.  When you learn a new language, no one expects you to be fluent right away.  You learn a few phrases and keep using them, and you gradually add more.

Software testing is such a valuable profession, but too often companies take testers for granted.  By applying the principles of Extreme Ownership and eliminating excuses from your vocabulary, you will come to be seen as an indispensable asset to your company.

Why You Should Be Testing in Production

This is a true story; I'm keeping the details vague to protect those involved.  Once there was a software team that was implementing new...