9 posts tagged “quality assurance”
I'm going to take a break from the Audio-Visual tutorials and talk a little bit about game development, specifically the teams that make it up. While game development can be a dawning task, I have come up with a few helpful hints on putting together a team that should help keep you on track.
- Artists - Sketching
You don't need much if you're just starting out, but it's always good to be able to sketch up a concept, if not at least have someone on the team who can. Sketching can be anywhere detailed as it needs to be. Concepts shouldn't take very long to sketch depending on it's scope. A concept artist should be able to take what the game designer(s) create(s) and sketch that into a visual. Often times a sketch artist will need to go into more detail by using actual rendering tools like Photoshop or something similar. - Artists - Modeling
If you are going to be working with 3D games it is a necessity to have someone on the team with enough experience in 3d modeling. This artist should be able to take what the sketch artist has come up with into a realistic 3d visual. Unless there is a texture artist available, texturing will often be performed by this artist as well. - Artists - Texturing/Shading
When resources are available, a game development team may also include texture artists. In this role, the person should be able to combine the efforts of the sketch artists with the modelers in order to create the final visual in the title. Texturing itself is usually done in layers depending on the amount of detail necessary. It is not uncommon for these artists to also perform shading techniques on top of their normal tasks. - Artists/Musicians - Sound
Sound, because no game is complete without the necessary audio-visual aspects. This artist should be in charge of providing all the necessary sound effects, music and fonts needed for a given game title. This role may be played by a developer but it is usually filled by ones with musical and artistic skills. - Designers - Game Design
For the most part game design is a collaborative effort, but it is best to have someone who concludes the final design on game concepts. The game designer should be able to explain what to include as well as exclude from a game title. Often times this designer will perform consulting on visual aspects of the gameplay as well as general environmental factors that make up the game. - Developers - Game Development
The core of the team who's role is to put the pieces of the puzzle together. This role can vary in many scenarios depending on the requirements of the game. The job may include writing networking code, artificial intelligence, camera angling, character movement and interaction among other tasks that the game may require. Be sure to understand the necessities of the game and the availability of tools before choosing this role and the skills.
While it's not entirely necessary to have the above people on your team, you or the people on your team may fill one of the above roles at some point in your game development cycle. As you progress, it will be necessary to also have testers on the team, but I've always approached this issue with test-driven development.
Aside from roles on a game team, there are a few things to keep in mind about creating a game. The first is the concepts included or excluded in a game. When in doubt, prototype your concepts as quickly as possible. Quick designs or sketches for a prototype shouldn't take more than an hour or two and if it does then it needs to be simplified. Building on concepts isn't necessary bad though; the larger and more complex a concept gets, ideally, the more prototypes you should already have. By then end of your game designing phase you should be able to present each aspect of the game with prototypes.
That's all for now :)
As a quality assurance developer for NORMA (Neumont ORM Architect for Visual Studio) this quarter I get the priveledge of working in many, many... many different orm models for test cases. So I thought I'd share some of the humorous models that have come up over time.
Chuck Norris has no reference scheme.
T-Rex eats Person in Game
Alright, this time I'm going to get right to the gut of quality assurance and talk about the ideal kind of testing environment when it comes to software, big or small.
Firstly, what kind of project are you planning on building? Is it a website? A desktop application? A mobile phone application? Realistically, it can be any project so long as you follow these 12 guidelines.
- Do you have source control?
It's always good to have source control and especially for the type of test driven environment you're looking for it will be even better for running all of those tests. - Can you build your solution in 1 Step
Most of us are using Visual Studio to build our projects but nevertheless you should be able to build your solution in 1 step whether it be building it for debug or compile and/or including deployment. It's a pretty common scenario where you want to deploy your solution immediately when you're done. - Do you perform daily builds?
If you're working on a project that goes day in and day out of work you should ensure that you at least build once a day or at night to follow up tests and issues in the program. - Do you have a bug database?
Bug databases are used for instant tracking of all of your bugs, whether automatically reported by the system or typed in by a user or developer on the team. It's very good to have one of these if you're working in a larger team. But even in a small team (like yourself) it can be pretty handy to organize everything into a simple database of bugs. Makes it easier to clean things off. - Do you fix bugs before writing new code?
This one is tough if you're not working directly off test driven code. What test-driven code means is that for every feature or series of implementations you have written tests to ensure that all logic and implementations are valid or work according to a standard. Think of test-driven development as writing the model that you want your project to become and the code that you are writing to be tested against are the drafts to the sculpture. - Do you have an up-to-date schedule?
What are you working on? What needs to be done? Who's working on what? Try not to think of schedules as some mundane constraint who's only use to keep the manager out of your hair. Schedules are incredibly valuable tools for time management. They teach you to manage your time wisely and keep you from working day in and day out on a silly problem that may mean nothing in the long run. In our industry we are too often thinking about the how and the what-if scenarios of software development but we rarely take a step back and ask whether or not we should do something rather than if it's possible. - Do you a specification?
If you're working on something that other people are going to be either working on or integrating with, please please please for the sake of all time and humanity, write healthy comments and anything else that will help people understand how to work with said system. Tutorials, samples, anything that relates to your system is really helpful for others to use their time just as wisely and timely. - Does your team have quiet working environments?
I know, you're thinking, "Wait a minute. What does quiet working environments have to do with software quality assurance." Well believe it or not, but a quiet working environment is basically a large white board to the mind of a developer and a tester. It ensures that not only can someone hear their own thoughts, but as a team it makes it easier to discuss and collaborate without disturbance. - Do you own or use the best tools money can buy?
Better tools, newer technologies anything that can aid you and speed up your time in development or your goals is far more useful than ever, especially to your users who are so eager to see what you've come up with. - Do you have a group of people or person who's sole purpose is to write tests?
This is more so for larger groups, in small groups you will be the tester and as a developer it's best practice to get in the habit of testing your own code before hand. - When you have new people on the project, do you have them write code before joining the team?
Usually it's a great idea to have the person you're interviewing actually write code related to what you're working with or what you plan to have them working with. Sometimes it doesn't really have to be a test of knowledge but to allow the person to get a feel for the code that he/she will be working with and it allows you to adapt to whatever practices or standards he/she may already go by. - Do you perform hallway usability testing?
Hallway usability tests are done by simply taking your laptop out into the hallway and showing what you've made. It's a great way to get suggestions and get other people excited about your creations. It's a great motivator if the people you test give back constructive criticism. And if you've followed the above guidelines this step should be no problem because you'll never run into a situation of a useless feature or a bug. You can explain it with confidence and passion!
What do I use for my test-driven quality assurance setup?
- Subversion Web: I try to always have a subversion setup that I can access via the web. These are useful for the fact that most of them have wikis for documentation and logs that come from subversion. It makes it especially easier for deployment since I can just create a release from the website.
I've been using: unfuddle lately. I think it's great!

Leadership is -
"the ability of an individual to influence, motivate, and enable others to contribute towards the effectiveness and success of the organizations of which they are members."
- R.J. House
Over time I have written quite a few posts on project dynamics, software development, methodologies and even tutorials on code. I have tried to evolve the concept of working in teams from a simple schedule put together with a series of methodologies that may help the team in one way or another. I think it's important to understand the major difference between a manager and a leader."Leadership does not involve changing the mindset of the group, but the cultivation of an environment that brings out the best (inspires) the individuals in that group..."
- Arthur F. Carmazzi
- Managers administer
- Leaders innovate
- Managers ask how and when
- Leaders ask what and why
- Managers focus on systems
- Leaders focus on people
- Managers do things right
- Leaders do the right things
- Managers maintain
- Leaders develop
- Managers rely on control
- Leaders inspire trust
- Managers have a short-term perspective
- Leaders have a longer term perspective
- Managers accept the status-quo
- Leaders challenge the status-quo
- Managers have an eye on the bottom line
- Leaders have an eye on the horizon
- Managers emulate the classic good soldier
- Leaders are their own person
- Managers copy
- Leaders show originality
It's also a good point to understand that within teams, with leaders, we can have two different types of leadership paths. One of them is called transformational leadership. (idealized influence - charisma, inspirational motivation, individualized consideration, intellectual stimulation). Transformational leaders develop a vision, sell it, find the way forward and usually leading the charge.
On the other hand there are transactional leaders (contingent rewards, management by exception). It's important to note that there are certainly times where you have to be able to change from either transformational to transactional with people. Some members of the team simply 'get it' and thus you can approach them with a sense of transformation and evolution within the vision. However, with other members you must approach with transaction, steps, processes that require the members to complete things in line. Even if it's not about approaching the members with the perspectives it's really about the balance in timing when it comes to the types of leadership within a team.
Let's face it, our industry has its problems in the completion of quality software products. Deadlines have been missed, projects have been thrown away, people have been fired, hired with a bundle of project developments that have either been redesigned or re-engineered to meet project expectations; keyword being expectations. With all the issues of software and its complexity has anyone thought to ensure the quality of our teams? There are plenty of people who have; in fact, any project manager will select a group of qualified people to complete a project. However, basic skill sets and aptitudes are far different then the understanding of how each attributes to the team's collaboration and cooperation. There are several approaches to figuring this out however:
- Assessments
- Have each member of the supposed team to take a test that addresses a person's thought process and emotional stator when functioning both alone and in a team environment.
- There are plenty of assessments that can be used to determine where a person stands in a team setting.
- Color Code - developed in the 1980s by Taylor Hartman, Ph.D. Both the Color Code and the Character Code (the two famous Hartman personality tests) have become the preferred method of self-awareness discovery for numerous colleges and universities, researchers, Fortune 500 businesses, professionals, small business owners, parents, married couples, students and more.
- Once you can identify where a person stands before the project is months in development, you can effectively account for the dynamics of communication in a team setting.
- Identify Capabilities vs Personal Goals
- Commonly in a team setting you will have people who want to work on certain parts of a product while people who have the skills necessary will work on other things. The problem usually originates from a perceived plan for the project or the lack thereof. This is why when you approach any project there should already be a general guideline to the goals and vision of the product at hand. Unless, of course, the team is brainstorming what exactly that vision really is.
- Brainstorming works really well in team settings. The type of collaboration it takes to brainstorm is really quite powerful and enriching to a team. This, of course, does mean that everyone should try to participate in the brainstorm, making sure that ideas are not left unheard or analyzed.
- Know what you want and what you can to do in the team!
- To
many times I have seen people go into a team and generally say that
they don't care what they work on. You should already know what you're
good at and what you aren't good at. What you are willing to take on
and what you're not. This will be mostly based on how you see the plan
in line with your abilities and aptitude to complete your part.
- For
instance: I'm fairly aware of structure of C++, however I have never
coded an entire piece in C++. Weighing this against the schedule and
the abilities of others, I may choose to devote more time here or more
time elsewhere depending on what needs to get done and who can already get it done.
- I could work with someone else if I'm certain that I know what this portion is about.
Think Architects and Specialists
Once a vision is formulated, there should a plan for building the components that make up the product itself. This plan should allow the team to form a variance of collaboration and cooperation to complete each piece.
- Collaboration: To work together, especially in a joint intellectual effort.
- Cooperation: To work in parallel, so that work can be divided and put together in a joint effort.
Note: plans need to have milestones in scheduling. Schedules are a necessity, even if loosely created, it gives a general means of product devotion from the team. Whether the team works slow or fast, there can be a bar set to which the team can evaluate their progress against..
It's been quite a while since my last software qa post, so I'll put more knowledge into this one. If you remember from my last post I talked about identifying features. Where we identify features is also an issue that will come up in our testing, and the goal is to be able to properly report these things so fixing problems can be much easier in our software.
The first of our notes is about identifying goals, classification fields, and lifetimes of reports. But to start, what is a problem? Given a state of the product, a problem is anything a customer:
- has that doesn't work
- has that they don't like
- has that annoys or distracts them
- needs
- wants
- doesn't know they need or want
The tester acts as a proxy for the customer in many of these scenarios. If the tester has an issue with either the program specification or officially completed code, they should enter the issue. Any omissions from the specification are problems (especially those not handled in the program). In many cases, a feature will have no problems until the development has allowed it to be testable. Of course there will be problems when the feature is not complete or can be tested. The same goes for any time of feature, whether interaction related, algorithmic... etc. (Read identifying features for more).
Once you run into a problem there obviously needs to be a description of some sort or a name. Classifying problems need to be flexible however. Is a problem is a bug, suggestion, work item, or document?
- Often difficult to classify
- A suggestion may be a disguised bug, or an existing feature that was not discovered. (lack of discoverability is a problem)
- Beta testers will not generally have the work item list, but their suggestion may be a duplicate of a work item.
- Lots of duplicates of a problem increase the chances of its being fixed
- The documentation may be right and the code wrong
Some companies, however, avoid these loaded legal terms. Meaning, shipping with documented flaws or defects is much more inflammatory to a jury than ignoring a suggestion. Call it what you will, just allow a suggestion to become a work item without entering a new bug.
Reporting Goals
- All issues should be formally tracked. Remember, many projects will outlive individual programmers and testers.
- A clear standard should be in place for closing the issue.
- A customer scenario should be included.
- Clear steps to reproduce the bug must be included
- Always include a build number
- Number steps for easy reference
- Include obvious steps
- If a bug is a framework or environment issue, assume the framework developer is not familiar with your product.
- Tester should spend the time to reduce the scenario
Reporting Fields (Title)
- Extremely important field (this is most commonly searched)
- Use keywords to match feature
- Use common keywords to emphasize issue (crash, assert, data loss, etc)
- Avoid abbreviations ('Readings Window', not 'read win')
- Make sure they're spelt correctly (common source of duplicate bugs)
Reporting Fields (Description)
Remember to describe the customer scenario and why it's important. Along side the scenario and its importance, is justification for problem severity, priority, and classification. This field is often 'append-only' (since we should only add information, but not remove it).
- Reproducing steps often need editing, these can go in a seperate field.
Avoid anything computer generated such as stack traces, or exception messages. It is typically best practice to have full call stacks from crashes or asserts as attachments. It's best practice to add anything less than five.
- Reports are viewed by all disciplines, not just developers; it is very hard for a program or test manager to get a feel for the bug from two pages of stack trace
Other than that, discussions on whether or not to fix the bug is recorded here in addition to any alternative use cases.
Reporting Fields (Version)
Record versions for:
- First entry
- Latest verification
- Fix date
- Reproduce step modifications
Some of these are informal notes in description ('re-verified on build 8.0.0.1057')
- Initial entry and latest fix build are generally formal fields.
Build number
- aka drop number
- The numbered (or dated) drop released for testing (most companies will do at most 1 per day)
Build type
- Debug, Release, Optimized, etc
Reporting Fields (Type or Classification)
Be sure to include the type of the problem report.
Coding Error (completed feature with errors)
Design Issue (specification bug)
Suggestion (not in specification or product)
Documentation (documentation bug)
Hardware (program fails on ABC video card)
Query (formal question explaining behavior).
You could also use the non-formal approach with:
- Eliminate Query:
a recommended course of action should be provided, which makes it a Design Issue or Suggestion. - Add Work Item
if a suggestion is non-trivial to implement and should be scheduled and/or re-architected then it's a work item.
Reporting Fields (Severity)
How severe are the consequences of the bug? Do identify this we use severity scales.
1-3: fairly common (Microsoft uses 1-3)
1: Fatal
- the program crashes or destabilizes the system
- usually avoids data loss (crash before saving)
2: Serious
- a customer is unable to perform a specified feature
- the problem is frequently hit
3: Minor
- annoyance bugs (spelling, tab order, etc)
- these provide the overall fit and finish
- i.e. You won't stay long in the most scenic spot on Earth if you're surrounded by mosquitoes
Reporting Fields (Priority)
This is where we indicate how important it is that a bug is fixed.
- Fix immediately, blocking other work
- Fix as soon as possible
- Fix before next milestone (major release)
- Fix before final release
- Fix if possible
- Fix by your own judgement
Microsoft used 0-4, seperates milestone into a seperate field.
0: Blocking build or test automation. Run, don't walk.
1: High impact on customer, major inconvenience, difficult or no workaround
2: Customer will see this often and may need to workaround the issue
3: Fit-and-finish
4: Suggestion
Well that's it for problem reports. Remember, these are reports so even if you haven't gathered all this information, you can easily come back to edit and append to the report until it is closed. I'll be sure to get Unit Testing in my next post quicker than I got this one in.
It's been a while since my last Software QA post when we talked a little bit about equivalence classes. In this post, I'll be discussing how to properly identify features within a program.
During the software development lifecycle, normally early during specification and development, test planning occurs. This is where all of the identification of the program falls into scope and frameworks are built to support the application for a certain level of resiliance and sustenance. It is best practice to plan this out before you finish specifications or code. During our test planning stage we may identify the following paths for testing:
- Bug tracking database features
- Used across disciplines (development, testing, etc)
- Agree of severity, priority, feature are, and other fields - Test tracking framework
- Record results of tests across different test builds
- Allows for manual and automated tests
- Generally used exclusively by test team - Test automation framework
- Testing requires development, too
- Plan with development early on to schedule testing hooks - Feature Identification
- We'll look at this one today.
What exactly is a feature?
When identifying features the following categories will come up with each feature identified. You must be careful to properly place the feature in the appropriate area so you can handle how to test for it throughout the testing stage.
- Is it something you could market to the customer?
- This is generally very broad (i.e. built in code generation) - Is it a specific UI element?
- 3D Window Manager (Window + Tab)
- Aero glass interfaces - Implements an algorithm?
- Spell-checking
- Matrix inversion
- Model consistency checks - Piece of code in the product?
- Public classes and methods
- Extensibility points
- Internal classes
Classify your features
In order to properly classify the features of a program, a lot of questions need to be asked. Some questions provide natural dependency information between components. Since all features naturally nest (i.e. the what of one feature is part of the how of another) the question-based approach works for all feature types:
- Box, UI, Algorithm, Implementation.
Here's what you can ask:
- What is the task that needs to be performed?
- Box: built-in code generation
- UI: choose the Generate Code menu item
- Algorithm: Perform object-mapping to group objects
- Implementation: Save temporary file and apply transform to generate code
- Who is expected to perform the task?
- Identify customer roles (example, extensibility programmer)
- Box: Full extensibility
- UI: Add plug-in dialog
- Algorithm: Service-oriented architecture for external use
- Implementation: Requires extra testing at public API level
- Why do they want to perform the task?
- Usually the best question for large functional grouping
- This is why the customer buys the product.
- How do they do perform the task?
- An answer to how will often identify sub features.
- Box: Rarely mentioned (beyond the vague 'automatic')
- UI: Focus on UI elements (menus, tool windows, dialogs, etc)
- When is the task available?
- Identify the context of the task
- UI: Properties Windows items populate when a control is selected
- Provides a natural grouping for test design
Identify Context
As expected, all features run in a given context. This means, that there is a given state in the program where the feature exists. This context is usually static (yes or no, true or false) but can indeed be dynamic given any number of constraints to the feature. You will find that dynamic context occurs in ongoing actions such as playing a video, generating code, or analyzing live data feeds.
However there are plenty of cases, and this works well with test design, where features require more than one context. In other words, code generation isn't available unless I have valid XML. If feature B is code generation, and xml validation is feature A, we know that feature B is available within the context of feature A. You can almost always test B along with A, but not vice-versa.
Proper Plans
In the early stages you will need to do the following:
- Identify large why areas
- Areas correspond to single or multi stage user actions
- The how should be left until last
- A feature test should use a utility layer to do the how
Examples:
- Delete the BlogPostComment is an appropriate action for test planning.
- Click the Delete Comment link (one of the many How features) is not appropriate for functional test planning.
- Add a Video is appropriate
- Open the 'Compose Page', click the 'videos' button, tab to next page, click last video link... etc is not
- Your test should be able to say 'Add a video'
- The automation layer (later on) will do the rest.
Risks and Side-Effects
Every action of a test will have its risks and side-effects. Although, the manifestation of the side-effects is not important in early stages, it is increasingly important to note the risks involved and any possible consequences to occur when running a given test.
- Good examples
- Renaming your username should fail if the name is in use by another user.
- Deleting a user group should throw {x,y,z} errors.
- Bad examples (the how should be hidden from high-level feature tests)
- Renaming a blogger's username to a used name will display a message box.
- The task list will change when an error is added.
I hope this has helped identify features a little easier for those of you who seek quality assurance in your software. In my next post I'll talk about how we can make the testing part of development a little less hectic with creating proper problem reports.
In my previous post I discussed some of the common testing basics when developing a product. In this post I will be going over equivalence classes; that is, identifying characteristics within a feature and classifying them based on a given set of conditions.
An Equivalence class is a set of data that has equivalent characteristics. When you decide on a feature in a program, you must first gather what is important based on the domain knowledge. Equivalence classes can be combined into sets with each value in a class (yes/no answer). However, we can have a value in multiple classes. Let's take the following example, what equivalence classes can you come up with from the data?
3, 099, 127, 003, 128, +05, -3, -128, 0A1\
- Positive/Negative
- Leading Zeros/Non-Leading Zeros
- Leading Sign/No Leading Sign
- Single Digit/Non Single Digit
- Single-digit parsed value (ignore sign and leading zeros)/Not single digit value
- Numbers that can be stored in a signed byte/Not
- Decimal Number/Not a Number
In a rectangle, there are the four edges, the corners, and all the area inside. Similar to test scenarios, prime candidates for testing a point would be on the edge or the corners. With a rectangle we may have the equivalence classes: Left-Boundary, Right-Boundary, Top-Boundary, Bottom-Boundary, Top-Left-Corner... etc.
We can see that there are far more useful scenarios for testing these boundaries than testing the middle of the range. This is simply because we are more likely to run into defects and bugs while testing the boundaries of equivalence classes than the middle. Now let's try this with an exercise (a common test scenario by Myers in 1969).
- Triangle problem
- Program to identify triangles given three numbers
- Scalene, Equilateral, Isosceles, Invalid
- Exercise:
- Identify input classes for individual values (ensure that each value is valid before moving on in the steps)
- Identify equivalence classes and sets of equivalence classes for 3-valued sets of individual numbers that fit
- Use representative values to identify power tests sufficient to test all of your equivalence classes.
- Ensure that you cover the boundary, borderline, and mid-range of each value of each equivalence class.
public enum TriangleType
{
// The three do not form a triangle
Invalid,
// The three sides form an equilateral triangle
Equilateral,
// The three sides form a right isosceles triangle
RightIsosceles,
// The three sides form an isosceles triangle
Isosceles,
// The tree sides form a right scalene triangle
RightScalene,
// The three sides form a scalene triangle
Scalene,
}
The above enumeration TriangleType will give us the possible equivalence classes. We obviously know the four types Isosceles, Scalene, Equilateral and Invalid. But there is also the different types of Scalene and Isosceles. Take care to include these in your equivalence classes.After we have specified all the different types of equivalence classes we can now construct our Triangle structure.
public struct Triangle
{
private TriangleType myType;
private double myLongestSide;
private double myLeg1;
private double myLeg2;
private const double Tolerance = 1E-09;
.........
I have taken care to add the TriangleType and the different sides. When you construct a Triangle you will want to have the three sides of course set. I also have set a Tolerance level which I will discuss later in the initialization part.
public Triangle(double side1, double side2, double side3)
{
myType = TriangleType.Invalid;
myLongestSide = myLeg1 = myLeg2 = 0;
if (side1 > 0 && side2 > 0 && side3 > 0)
{
if (side1 < side2)
{
if (side2 < side3)
{
Initialize(side3, side1, side2);
}
else
{
Initialize(side2, side1, side3);
}
}
else if (side1 < side3)
{
Initialize(side3, side1, side2);
}
else
{
Initialize(side1, side2, side3);
}
}
}
When we actually create the triangle we need to analyze different equivalence classes based on characteristics that we measure. The common approach will be to determine what values or characteristics define a given equivalence class and even still what other cases will default a case.
I'll make the note that our Initialize method is taking in the following parameters:
private void Initialize(double longestSide, double leg1, double leg2)
The first parameter is the longest side on the triangle, with the other two legs passed in after.
If we look at the first condition: if (side1 > 0 && side2 > 0 && side3 > 0)
We will notice that it the condition is true, then the equivalence class is Invalid. Otherwise we'll move on the other conditions.
In the next condition:
if (side1 < side2) there's one of two scenarios that we can look at for initializing (if it is true).- side1 is smaller than side2
- Is side2 smaller than side3?
- Side2 is the largest side
- Initialize(side2, side3, side1)
- Side3 is the largest side
- Initialize(side3, side2, side1)
- Is side1 smaller than side3?
- Initialize(side3, side1, side2)
- Otherwise
- Initialize(side1, side2, side3)
if (((leg1 + leg2) - longestSide) > Tolerance)
{
TriangleType type = TriangleType.Scalene;
myLongestSide = longestSide;
double scaledLeg1 = leg1 / longestSide;
double scaledLeg2 = leg2 / longestSide;
if (Math.Abs(scaledLeg1 - scaledLeg2) < Tolerance)
{
leg1 = leg2;
scaledLeg1 = scaledLeg2;
type = TriangleType.Isosceles;
if (Math.Abs(1d - scaledLeg1) < Tolerance)
{
type = TriangleType.Equilateral;
}
else if (Math.Abs(scaledLeg1 * scaledLeg1 - .5d) < Tolerance)
{
type = TriangleType.RightIsosceles;
}
}
else if (Math.Abs(1d - scaledLeg1) < Tolerance || Math.Abs(1d - scaledLeg2) < Tolerance)
{
// Note: no need to check for RightIsosceles if the longest side is one of
// the sides with equal length
type = TriangleType.Isosceles;
}
else if (Math.Abs((scaledLeg1 * scaledLeg1 + scaledLeg2 * scaledLeg2) - 1d) < Tolerance)
{
type = TriangleType.RightScalene;
}
myType = type;
myLeg1 = leg1;
myLeg2 = leg2;
}
In our first condition we use the old is it a triangle formula. Side A + Side B - Longest Side Greater Than 0 or at least the tolerance in this case. If it is then we can start with a Scalene type.
Scalene:



double scaledLeg1 = leg1 / longestSide;
double scaledLeg2 = leg2 / longestSide;
if (Math.Abs(scaledLeg1 - scaledLeg2) < Tolerance)
We can determine if the triangle is an equilateral if the 1d - scaledLeg1 is less than our Tolerance level. Otherwise, if the scaledLeg1 squared - .5d is less than our Tolerance level then it's a Right Isosceles triangle.
if (Math.Abs(1d - scaledLeg1) < Tolerance)
{
type = TriangleType.Equilateral;
}
else if (Math.Abs(scaledLeg1 * scaledLeg1 - .5d) < Tolerance)
{
type = TriangleType.RightIsosceles;
}
We know that it's an Isosceles if two sides equal each other so the next condition handles as opposed to the first condition.
else if (Math.Abs(1d - scaledLeg1) < Tolerance || Math.Abs(1d - scaledLeg2) < Tolerance)
Other than this, if all three sides are not equal, then it's a Scalene triangle, handled by the next condition.
else if (Math.Abs((scaledLeg1 * scaledLeg1 + scaledLeg2 * scaledLeg2) - 1d) < Tolerance)
To sum this all up we will simply test a few cases, I won't go into detail about utilizing our testing principles since this tutorial is for learning the concept of equivalence classes but you get the idea. However, I hope this has helped you understand some of the basics to identifying characteristics into classes. In the next post I'll discuss how to properly identify features.
Software is complex, in fact it can be infinitely complex depending on how the product is developed if extensibility is a factor. There are literally millions of scenarios that can occur not only the development of a product but even after a product has been deployed. Many times after a product is deployed (after getting customer feedback) developers will run into many issues that they did not foresee originally. When software is deployed and run on a client machine there are scenarios that may work for one user but not for another; like settings and runtime environments.
Because of these vast differences in environments, developers use common test utilities to cover their code and test against common scenarios that may break working code. Surely you should test to see if you code works, of course it should work you wrote it. There are, however, many scenarios that haven't been tested even after coverage is 100%. As such, after developing an application, there needs to be a standard for finding out possible failures in the code. I've noted some of the principles involved in testing basics for developing software.
- Find problems before customers do
- Find problems customers care about
- Ensure all features of the product are acceptable by the customer.
- Provide timely feedback on functionality of new features.
- Provide timely feedback on stability of old features.
- Role is not to prove the program works
- No way to fully test all possible program paths
- All software ships with some problems
- A problem is anything the customer doesn't like.
Some testing approaches have been known to include:
- White Box Testing (aka Glass Box Testing)
- Full access to the source code
- Static analysis
- Code reviews
- Static analysis tools (FxCop, etc)
- Dynamic Analysis
- Step through code in a debugger, examine program state
- Profiling (line coverage, branch coverage, performance)
- Black Box Testing
- No assumptions on implementation
- Two approaches
- Automate user interactions
- Use public API provided by the program
- Both techniques have value
- An UNDONE comment in code may reveal a subtle bug
- But customers don't read or profile code
Let's take a step back from testing and think about the psychology of testing itself.
- Testing is inherently adversial
- Programmers are trying to ship and you're telling them they can't.
- Product managers are losing money in development costs and lost revenue and you're telling them they'll lose more if they ship now.
- Never make it personal
- Issues always outlast programmers, especially bad ones. When you write a test scenario, the code could be re-written and re-written over and over but the test scenario lives through all the code rewrites.
- Issues always outlast programmers, especially bad ones. When you write a test scenario, the code could be re-written and re-written over and over but the test scenario lives through all the code rewrites.
- You have to carefully sell the things you really care about.
- Clear expectations in bug reports
- You can't simply put "X Doesn't Work." in a bug report. That doesn't explain anything to anyone reading this. A developer won't have your test code, you have to be able to explain enough to allow anyone to go right to where they need to be to fix code.