Lecture 4 - The Software Development Life Cycle -> Quick Intro -> Idea -> Product Design -> Coding: Part 1 -> Coding: Part 2 -> Testing And Bug Fixes
Let’s proceed with “Coding” stage and talk about the two main things done by the programmer:
1. Programming.
2. Bug fixing.
Here is simplified version:
1. PROGRAMMING
A developer writes
child_value = parent_value + 3
2. BUG FIXING
According to the spec, the child value must be equal to the parent_value minus 3:
child_value = parent_value – 3
So, a tester files a bug about “+” instead of “-” and the programmer does the bug fixing.
Most of the PROGRAMMING takes place during the Coding stage. But PROGRAMMING can also take place anytime when there is a need in code creation/modification/deletion.
Most of BUG FIXING takes place during
– the Coding stage (developer finds his bugs) and
– the Testing and bug fixes stage (bugs are found by a tester).
But BUG FIXING can also take place anytime when new bug is found and deemed to be worth fixing.
BTW
What does a developer do when the programming for the coming release (e.g. 1.0) is finished? He writes the code for the next release after coming release (2.0)! So, when testers find bugs during stage “Testing and bug fixes” developers have to interrupt their work on 2.0 and fix bugs for 1.0.
The important thing to understand here is that after the developer has done his work for the current Cycle, he moves to the “Coding” stage of the next Cycle.
Now, let’s learn about three classic* types of bugs associated with coding:
1. Syntax bugs
2. User Interface (UI) bugs
3. Logical bugs
* We are not going to cover highly specialized and advanced topics like performance testing.
1. SYNTAX BUGS
The beauty of syntax bugs is that they are detected and even explained (sort of) by a language compiler (e.g., if the programming language is C++) or a language interpreter (e.g., if the programming language is Python) once you try to compile or execute the program.
BTW
Compilers and interpreters are special programs that translate code typed by humans (a=2+3) into the language understood by computers (0110000100111101001100100010101100110011). The difference between a compiler and an interpreter is that:
– a compiler produces an executable file but doesn’t execute our code. Thus, text files written in C++ must be compiled to become executable (launchable) programs.
– an interpreter doesn’t produce an executable file but immediately executes our code. Thus, text files written in Python are already executable.
Example
Let’s look at the example of a syntax bug in C++ program. C++ uses compiler.
Here is first program of any student learning C++ (line numbers are not part of software code):
1.#include <iostream.h> 2. 3.void main() 4.{ 5.cout << "Hello, World! << endl; 6.}
This code is saved in the file hello_world.cpp. Let’s try to compile this program:
~> gcc hello_world.cpp
hello_world.cpp:5: unterminated string or character constant
hello_world.cpp:5: possible real start of unterminated constant
The last two lines are the compiler’s description of the bug in this code. What happened was that the compiler found a problem and exited after giving us information about the bug. The bug happened because we didn’t close with double quotes after World!. How would we describe this bug in one sentence? “hello_world.cpp: closing double quote is missing after World!”
If we fix the problem, our hello_world.cpp will compile just fine, and we will get an executable file that prints “Hello, World!” when we launch it.
Example
Let’s look at the example of a syntax bug in Python program. Python uses interpreter.
ShareLane -> Go to this URL: https://www.sharelane.com/cgi-bin/register_with_error.py (you can also launch this file from here: Test Portal>More Stuff>Python Errors>register_with_error.py). As you can see, there is a syntax error in this line of code:
body_html = get_firstpage(zip_code)
Programmer made mistake by giving wrong name of function:
Expected: get_first_page
Actual: get_firstpage
Here is a bug summary: “register_with_error.py: wrong name of the function get_first_page()“
Brain positioning
ShareLane -> The only difference between
– perfectly working file register.py (Test Portal>Application>Source Code>register.py) and
– not working at all file register_with_error.py (Test Portal>Application>Source Code>register_with_error.py)
is a single underscore character (“_”). So, even smallest modification to existing code can break the whole system. That’s why regression testing, i.e., re-testing of old functionalities, has immense importance.
2. USER INTERFACE (UI) BUGS
A UI bug is a bug in how the software presents the information. UI bugs range
from visual problems like
– a link on the Web page has a wrong color
to interactive problems like
– it’s hard for a user to figure out how to use certain functions.
So remember that UI bugs cause presentation problems.
3. LOGICAL BUGS
A logical bug is a bug in how the software processes information.
Example
ShareLane -> Do steps below:
1. Create new user account on main.sharelane.com and login.
2. Add any book to the Shopping cart.
3. Set number of book inside Shopping cart to 30 and click button “Update”.
4. Check value in column “total”.
We have logical bug inside functionality “Shopping cart”, because total amount got calculated incorrectly:
Expected result: 294 (discount must be subtracted).
Actual result: 306 (discount is added).
BTW
ShareLane -> Let’s see buggy line of code. Go to Test Portal>Application>Source Code>shopping_cart.py and click link “BUG #6” under sub-section “View bugs.”
Expected statement: total = total – discount_amount
Actual statement: total = total + discount_amount
Logical bugs are the primary focus of software testers because
– As a rule, it’s much harder to find logical bugs than UI bugs;
– As a rule, the consequences of releasing logical bugs are much more severe than the consequences of releasing UI bugs.
But keep in mind that even UI bugs can be really nasty: if users cannot figure out how to put a book into the shopping cart, then the perfectly working code of the application core doesn’t really matter.
Here is another stage-by-stage illustration of a logical bug:
Example
<Product design>
Spec #9877: “7.2. User must enter two integers from 1 to 12 and press enter. Program must print on screen arithmetical mean between entered values.”
<Coding>
Here is the code written in C++. That code, also called a source code, is in text file get_average.cpp.
01.#include <iostream.h> 02. 03.void main() 04.{ 05.int first_number = 0; 06.int second_number = 0; 07.float average = 0.0; 08. 09.// get first number 10.cout << "Enter first number: "; 11.cin >> first_number; 12. 13.// get second number 14.cout << "Enter second number: "; 15.cin >> second_number; 16. 17.//calculate average 18.average = first_number+second_number/2.0; 19. 20.//output result 21.cout << "Average = " << average << endl; 22. 23.}
Now, after the code is written, the programmer uses the C++ compiler gcc to compile the text file get_average.cpp into executable file get_average.
<Testing and bug fixes>
~>get_average
Enter first number: 9
Enter second number: 2
Average = 10
According to the spec, our expected result is 5.5 if we use 9 and 2 as inputs. But our actual result is 10, so we have a logical bug. What will you do now?
– You will file a bug against the responsible programmer. Bug summary: “Spec9877: get_average: wrong calculation of arithmetical mean“.
– Then the programmer should look into the problem, fix it, and reassign the bug to you (soon we’ll cover all the technicalities related to bug tracking).
– Then you must retest the code and
– if the bug is fixed, you close it;
– if the bug is NOT fixed, you reassign it back to the developer.
BTW
The problem with the code was in line 18 where our programmer didn’t put a parenthesis. Here is the correct expression:
average = (first_number+second_number)/2.0.
BTW
We should file another bug against the PM who didn’t specify the precise range of inputs. If the max valid input is 12, than the first sentence of item 7.2 must have this wording: “User must enter two integers from 1 to 12 inclusively and press enter.” Why do we need “inclusively“? Because without it:
Some folks will be confident that “integers 1 to 12” means that the max value is 12.
Some folks will be confident that “integers 1 to 12” means that the max value is 11.
Some folks will be plainly confused.
So, while writing specs the PM must make sure that everyone in the spec audience will understand the spec the same way.
BTW
That spec has another problem: it’s not specified how the program should react to invalid input, e.g., 0, 13, “A”, “#” or Null input (the user simply presses Enter without any data typed).
Let’s proceed and talk about code freeze. Why do we need it? It only makes sense to test code if the code is in a stable state – i.e., the developers don’t change it while it’s being tested.
Example
Imagine the following situation:
1. The programmer has finished coding functionality A.
2. The tester checks functionality A and gives green light for release.
3. Ten minutes before the release, the programmer remembers something and makes a tiny change in the code of functionality A.
Theoretically, that “tiny change” should NOT affect anything, BUT in reality, functionality A stops working completely.
So we have a situation where
– the tester just wasted his time testing a not yet final version of the code
– the users got a buggy Web site
Remember this for the rest of your testing career:
Before you start testing, make sure that
1. The code is frozen (release engineers usually send an email stating this).
2. The test environment* has the correct version of the code to test.
*The test environment is the software/hardware combo where the software is tested before releasing it to users. Usually, when referring to the test environment we just mention the name of an internal Web site for testing. If the URL of the test environment is https://main.sharelane.com, then I can say: “I found a bug on main.”
Remember to check these two things EVERY time prior to testing.
Let’s illustrate the second point.
Example
We have two test environments on the Intranet:
https://everest.sharelane.com
https://elbrus.sharelane.com
These two Web sites are used for internal testing only and are not available to users.
Let’s assume that
https://everest.sharelane.com has code version 1.0.
https://elbrus.sharelane.com has code version 2.0.
There is often a situation when the same functionality (let’s say “Checkout”) in the old (1.0) and new (2.0) versions has
– an absolutely identical front end and
– an absolutely different back end
Therefore, if a tester doesn’t specifically check to see if the test environment has the correct version, he can end up testing the wrong version, because the front end looks the same. This mistake is often made by both beginning and experienced testers. That’s why it’s very important to always check to see if the test environment has the correct version, i.e., the exact version that needs to be tested.
So what happens if a tester needs to test version 2.0, but erroneously uses https://everest.sharelane.com for testing? Two things:
1. A waste of that tester’s time – if we are going to release version 2.0, but erroneously test version 1.0, it doesn’t make much sense.
2. The risk of releasing untested code to our users, because version 2.0 (which was supposed to be tested) wasn’t tested.
As you can see, negligence in checking the version of the code to be tested can have very negative consequences.
My advice to you is this: If you screw up and test version 1.0 instead of version 2.0, immediately acknowledge your fault. Everyone makes mistakes. It’s life. Just forget about your plans for the evening, weekend, or holiday, and stay in the office until you finish testing version 2.0.
BTW
It’s a good idea for a start-up employee to have a sleeping bag, a change of clothes, a towel, and some personal hygiene items ready in the office – there is always the chance for some wild overtime, and you don’t want to drive after fifteen hours of work.
Sad things, like testing of wrong version, take place because of a tester’s negligence, but sometimes other factors, like illogical names of test environments, contribute to the situation. Here’s how to prevent this:
1. Ask your release engineer how to find out the current code version in the test environment and apply this knowledge EVERY time before testing.
2. Ask your IT engineer about choosing logical names for test environments. An IT person can enjoy whatever he likes (for instance, mountain climbing), but it’s difficult to understand the difference between Everest and Elbrus when talking about a version of software. Let’s create two test environments instead:
https://old.sharelane.com for the application version which is currently on our live site: https://www.sharelane.com. So, if a bug is released to our users, we have https://old.sharelane.com to test a bug fix before releasing that bug fix to the live site. Between ourselves we can call this test environment “Old”.
https://main.sharelane.com for the application version of the coming release; the testers do testing on https://main.sharelane.com, and when we are ready for the release, the live site, https://www.sharelane.com, will get the version of the software accepted for release on https://main.sharelane.com. Between ourselves we can call this test environment “Main”.
3. If the current way of finding out the version of the code and the DB is not convenient (e.g., you always have to go and ask the release engineer about those versions), suggest that he implements one of the following:
a. Add a Web page with information about
– the release version
– the build number (more about this in a minute)
– the DB schema version (more about this in a minute);
ShareLane -> For example, if this is implemented, you can go to the page: https://main.sharelane.com/version.txt and see something like this:
Release version: 1.0
Build number:23
DB schema version:34
Important: the “version of the code” or the “version of test environment” consists of the three components above. Remember to check for these three things every time before you start testing. We’ll elaborate more about each of the components soon.
b. Another good approach is to include information about the current version as a comment written into the html code of each Web page.
Example
ShareLane -> Do this:
1. Go to main.sharelane.com
2. Point your cursor on an object-free spot of the Web page; an “object-free spot” is any spot on the Web page without a Web object (such as an image, link, etc.).
3. Do a single right click.
4. Select the “View Source” (IE) or “View Page Source” (Firefox) option
5. Find the version number.
For example:
<!– application version 1.0-23/34 — >
You can find out application version of ShareLane looking into HTML of any Web page on https://main.sharelane.com (exception is Test Portal pages).
BTW
From now on, let’s call the full version of our code the “application version“.
At ShareLane, we specify application version in this format:
<major release number*>.<minor release number>–<build number>/<DB version number>
* we’ll talk about release types later.
Three last things about “Coding” stage:
First: During the “Coding” stage, programmers write code for the coming release and testers write test cases to test that code. I recommend that files with test suites, just like files with specs, should be
– stored in CVS (or other version control system);
– available to anyone inside the company.
The main advantages of storing files with test suites in CVS (or other version control system) are:
– it eliminates the risk of an accidental deletion of a file;
– it allows access to old editions of the file and its history;
– the file is stored on the shared server, and everyone who needs to (and who has a right to do so) can take that file to
> execute, modify, or delete existing test cases;
> append new test cases.
Second: It’s very good idea to have a tradition of test case review meetings. Test case review meetings take place before the stage “Testing and bug fixes” and right after the tester has finished writing test cases. What happens is that the following people:
– the PM who wrote the spec,
– the programmer who is responsible for coding that spec and
– the tester who has finished test cases to test that code
get together, and the tester makes a mini presentation about the way he is going to do testing.
Before the meeting I usually make hard copy of the test suite for everyone who accepted my meeting invitation. During the meeting I give a short overview of each test case, and everyone can see what I’m talking about.
The great value of this kind of meeting is that in many cases PMs and programmers
– give testers new IDEAs for testing and/or
– find omissions and/or errors in test cases.
BTW
After the test case review meeting, send out an email to every participant and to those who were invited but couldn’t come to the meeting. In this email, list all improvements that you’ve talked about during your meeting. This email is very useful because
– you’ll refresh the suggested ideas in your brain;
– you’ll give others an opportunity to see that you understood them correctly.
In many large Internet companies, the test case review meeting is an obligatory thing.
Third: After my wife read about UI and logical bugs, she asked me a simple question: If an HTML link leads to the wrong page, is it a UI or a logical bug?
Interesting question:
– on the one hand, it’s about presentation;
– on the other hand, sometimes links are dynamically generated by our code (e.g., the link “log out” is generated only if user is logged in).
So, my response was:
– “If the misleading link is hard-coded into the HTML code of the Web page, then it’s a UI bug, because there is no problem with processing here and the presentation is wrong.”
– “If the misleading link is dynamically generated by our code, then it’s both a logical and a UI bug, because there is a definite issue with processing and there is definite issue with presentation.”
Does this make sense? What do you think?
That’s all for the “Coding” stage, my friends. I hope that you’ve learned some valuable stuff that you will be able to use in your companies. Next ->
Lecture 4 - The Software Development Life Cycle -> Quick Intro -> Idea -> Product Design -> Coding: Part 1 -> Coding: Part 2 -> Testing And Bug Fixes