This is part of the supporting material from our first book, Applied Software Project Management, which was published by O’Reilly in 2005. You can see all of the material here: https://www.stellman-greene.com/applied-software-project-management/
Contents
Software Requirements Specification
It seems obvious that we need to know what software is supposed to do before we build it. Nevertheless, many projects are delayed (or fail completely) because development begins before anyone on the project team really understands how the software should behave. The solution to this problem is to take the time to gather and verify the software requirements—documentation that completely describes the behavior that is required of the software—before the software is designed, built, and tested.
A software requirements specification (SRS) is a complete description of the behavior of the software to be developed. It includes a set of use cases that describe all of the interactions that the users will have with the software. In addition to use cases, the SRS contains functional requirements, which define the internal workings of the software: that is, the calculations, technical details, data manipulation and processing, and other specific functionality that shows how the use cases are to be satisfied. It also contains nonfunctional requirements, which impose constraints on the design or implementation (such as performance requirements, quality standards or design constraints).
SRS Outline
The following document contains the outline for a software requirements specification. It includes templates for use cases, functional requirements and nonfunctional requirements.
SRS Development Script
Like use cases, the SRS should be developed iteratively. The goal of the SRS Development Script is to remove as many defects as possible from the SRS. Many people have trouble figuring out what constitutes a defect. In this case, a defect is any planned software behavior which a project team member, user, stakeholder or decision-maker does not agree with. This means that defects could be caused by any number of problems:
- Somebody does not believe that the planned behavior will satisfy the users’ or stakeholders’ needs
- Somebody believes that those needs may be better satisfied with different behavior
- An inspector does not understand what’s written, or feels that it is ambiguous or confusing
- A project team member does not believe that the behavior can be implemented as written
- Two or more requirements contradict each other—an implementation that satisfies one cannot satisfy the others
If there is a requirement in the SRS that has one of these problems, it must be identified and fixed so that everyone agrees on everything in the document. There will almost certainly be defects that slip through—no inspection team is perfect—and each of these will cost much more time to fix after they have been designed, coded and tested than it would have if it had been caught using the SRS development script. The goal is to find as many defects as possible, in order to reduce the amount of time that the team must spend later on in the project undoing the few that slipped past.
The following table contains the SRS development script:
Name | Software Requirements Specification Development Script |
Purpose | To elicit software requirements, document them in a software requirements specification, and verify that it is correct. |
 Summary | The development of the software requirements specification should be the most iterative part of the entire project. This is the point where the behavior of the software to be developed is at its most malleable—it has only been described in words, and has not yet been realized in design, architecture, code, test plans or any other work product. The goal of this script is to ensure that as many defects are found as possible, because each defect missed at this stage will be much more costly to detect and fix later on in the project. |
 Work Products | Output Software Requirements Specification (SRS) |
Entry Criteria | A requirements analyst has a vision and scope document for a project and has identified a set of users, stakeholders, and other people who will participate in the elicitation process. |
Basic Course of Events |
|
Exit Criteria | The script ends after the draft was inspected in step 3 and no defects were found. If defects were found or there was only a deskcheck performed in step 3 then the script returns to step 1 for the next iteration. |
Use Cases
A use case is a description of a specific interaction that a user may have with the software. Use cases are deceptively simple tools for describing the behavior of the software. A use case contains a textual description of all of the ways that the intended users could work with the software through its interface. Use cases do not describe any internal workings of the software, nor do they explain how that software will be implemented. They simply show the steps that the user follows to use the software to do his work. All of the ways that the users interact with the software can be described in this manner.
Use Case Template
A typical use case includes these sections, usually laid out in a table:
Name | Use case number and name |
Summary | Brief description of the use case |
Rationale | Description of the reason that the use case is needed |
Users | A list of all categories of users that interact with this use case |
Preconditions | The state of the software before the use case begins |
Basic Course of Events | A numbered list of interactions between the system and one or more users |
Alternative Paths | Conditions under which the basic course of events could change |
Postconditions | The state of the software after the use case ends |
This example shows a final use case for a search-and-replace function (which is numbered UC-8):
Name | UC-8: Search |
Summary | All occurrences of a search term are replaced with replacement text. |
Rationale | While editing a document, many users find that there is text somewhere in the file being edited that needs to be replaced, but searching for it manually by looking through the entire document is time-consuming and ineffective. The search-and-replace function allows the user to find it automatically and replace it with specified text. Sometimes this term is repeated in many places and needs to be replaced. At other times, only the first occurrence should be replaced. The user may also wish to simply find the location of that text without replacing it. |
Users | All users |
Preconditions | A document is loaded and being edited. |
Basic Course of Events |
|
Alternative Paths |
|
Postconditions | All occurrences of the search term have been replaced with the replacement text. |
Use Case Development Script
As the use cases are developed, additional information about how the software should behave will become clear. Exploring and writing down the behavior of the software will lead a requirements analyst to understand various aspects of the users’ needs in a new light, and additional use cases and functional requirements will start to become clear as well. As this happens, they should be written down with a name, number and summary—once they are in this form, the analyst can apply the four-step process to complete them.
The first step in developing use cases is identifying the basic ones that will be developed. The list of features in the vision and scope document is a good starting point, as there will usually be at least one use case per feature (usually more than one). This will probably not be the final set of use cases—additional ones will probably be discovered during the development of the use cases.
Many requirements analysts have found that a four-step approach is effective in developing use cases. The following script describes this approach.
Name | Use Case Development Script |
Purpose | Â A four-step approach to use case development |
 Summary |  This approach to developing use cases allows the information to be gathered and documented naturally, in a way that lends itself to an iterative approach of alternating iteration, documentation and verification of use cases. |
 Work Products | Output Use cases |
Entry Criteria | A requirements analyst has received feedback from elicitation and is ready to develop use cases. |
Basic Course of Events |
|
Exit Criteria | The use cases are complete, and no additional information has been uncovered which may lead to additional use cases being developed. If additional use cases have been discovered, return to step 1 to fill them in. |
Functional requirements define the internal workings of the software: that is, the calculations,technical details, data manipulation and processing, and other specific functionality that shows how the use cases are to be satisfied. It also contains nonfunctional requirements, which impose constraints on the design or implementation (such as performance requirements, quality standards, or design constraints).
Functional requirements
Once an initial set of use cases has been created and filled in, the requirements analyst begins documenting the functional requirements. The following table shows the template for a functional requirement.
Name | Name and number of the functional requirement |
Summary | Brief description of the requirement |
Rationale | Description of the reason that the requirement is needed |
Requirements | The behavior required of the software |
References | Use cases or other functional or nonfunctional requirements that are relevant to understanding this one |
The name, summary, and rationale of each functional requirement are used in the same way as those of the use cases. The behavior that is to be implemented should be described in plain English in the “Requirements†section. Most requirements are only relevant to a small number of use cases—these should be listed by name and number in the “References†section. (Some requirements are not associated with use cases.)
The core of the requirement is the description of the required behavior. It is very important to make this clear and readable. This behavior may come from organizational or business rules, or it may be discovered through elicitation sessions with users, stakeholders, and other experts within the organization. Many requirements will be uncovered during the use case development. When this happens, the requirements analyst should create a placeholder requirement with a name and summary, and research the details later, to be filled in when they are better known.
The following table shows an example of a requirement that might be discovered during the development of the search-and-replace use case below.
Name | FR-4: Case insensitivity in search-and-replace |
Summary | The search-and-replace feature must have case sensitivity in both the search and the replacement. |
Rationale | A user will often search for a word that is part of a sentence, title, heading, or other kind of text that is not all lowercase. The search-and-replace function needs to be aware of that, and give the user the option to ignore it. |
Requirements | When a user invokes the search-and-replace function, the software must give the option to do a case sensitive search.By default, the search will match any text that has the same letters as the search term, even if the case is different. If the user indicates that the search is to be done with case-sensitivity turned on, then the software will only match text in the document where the case is identical to that of the search term.During a search and replace, when the software replaces original text in the document with the replacement text specified by the user, the software retains the case of the original text as follows:
|
References | UC-8: Search |
Requirements vs. Design
This handout illustrates the differences between needs, requirements and design.
Requirements vs. Design (PDF)
Requirements vs. Design (MS Word)
Design and Programming Tools
There are many tasks over the course of a software project which can be automated. Unit tests are a good example of automation—before programmers started using automated unit tests, they had to manually verify each function and user interface element before delivering a build. By automating unit tests, the programmers were able to make them much less time-consuming task, and as a result many more programmers take the time to build unit tests.
But unit tests are not the only manual programming task that can be automated. Automation can ensure that the software is built the same way each time, that the team sees every change made to the software, and that the software is tested and reviewed in the same way every day so that no defects slip through or are introduced through human error. A project manager can help the programmers avoid chronic quality problems by adopting some of these tools.
Version Control
Unit Testing
The most common (and effective) way for programmers to do unit testing is to use a framework, a piece of software that automatically runs the tests and reports the results. A framework typically allows a programmer to write a set of test cases for each unit. Most frameworks provide an automated system for executing a suite of unit tests and reporting the results. This allows a full battery of unit tests to be executed automatically at any time with little or no effort. Unit testing frameworks are available for most modern programming languages.
 Language | Framework Name (URL) |
Java | Â JUnit (http://www.junit.org) |
Visual Studio .NET | Â NUnit (http://www.nunit.org) |
C | Â CUnit (http://cunit.sourceforge.net) |
 C++ |  CppUnit (http://cppunit.sourceforge.net) |
 SmallTalk |  SUnit (http://sunit.sourceforge.net) |
 Perl |  Test (http://search.cpan.org/~sburke/Test) |
 Python |  PyUnit (http://pyunit.sourceforge.net) |
 Borland Delphi |  DUnit (http://dunit.sourceforge.net) |
Automated Build Tools
When projects become complex and require many steps to build, it’s easy for programmers to forget a step. A programmer may build a version of the software which is missing a library, or is compiled with incorrect options. What’s more, some programming teams have discovered that, as their build process becomes more and more complex, they have to dedicate more of a senior team member’s time generating new builds on a regular basis, which can cause delays in the project. Eventually it becomes difficult for the team to even generate a reproducible build. When the build is delivered to users, are often defects which can be traced back to missing libraries, or to required files which should have been included.
There are many automated build tools that address all of the problems caused by an unpredictable and difficult-to-reproduce build process. Popular ones include:
- Make (which ships with most Unix-like operating systems, and some IDEs)
- GNU Make
- Apache Ant
- Jam
Automated Project Monitoring
One of the most important ways a software project can be automated is with a development monitoring system. Two of the most popular ones are CruiseControl (http://cruisecontrol.sourceforge.net) and TinderBox (http://www.mozilla.org/projects/tinderbox), both of which are free and open source. These tools allow a project team to set up a set of tasks to be run automatically on a schedule. These tasks include:
- Retrieving the latest build from the version control system, building it, copying it to a folder, and reporting any build warnings or errors
- Running automated unit tests, generating a test report and reporting critical failures
- Running automated code review tools and reporting any warnings or rule violations
- Listing any changes which have been committed and by whom, including links to code listings for the changes
- E-mailing results as text or visual reports (or sent via SMS text messages or some other communications system)
Refactoring and Unit Testing
This handout gives examples of refactoring and unit testing in Java.
Refactoring and Unit Testing (PDF)
Refactoring and Unit Testing (MS Word)
Test Plans and Test Cases
Throughout the entire software project, the team does many things to find and prevent defects. Once the software has been built, it’s time to look back and make sure that it meets the requirements. The goal of software testing is to make sure that the product does what the users and stakeholders need it to do. Software testers review the final product to make sure that the initial requirements have been met.
In software testing, quality is defined as “conformance to requirements.†Every use case, functional requirement, and other software requirement defines a specific behavior that the software must exhibit. When the software does not behave the way that the requirements say it must behave, that is a defect. This means that software testers are responsible for figuring out whether the software that was produced by the team behaves in the way that the requirements it was built from say that it should.
The goal of test planning is to establish the list of tasks that, if performed, will identify all of the requirements that have not been met in the software. The main work product is the test plan. There are many standards that can be used for developing test plans. The following table shows the outline of a typical test plan. (This outline was adapted from IEEE 829, the most common standard for software test plans.)
Purpose
Features to be tested
Features not to be tested
Approach
Suspension criteria and resumption requirements
Environmental Needs
Schedule
Acceptance criteria
Roles and responsibilities
|
The test plan represents the overall approach to the test. In many ways, the test plan serves as a summary of the test activities that will be performed. It shows how the tests will be organized, and outlines all of the testers’ needs that must be met in order to properly carry out the test. The test plan is especially valuable because it is not a difficult document to review, so the members of the engineering team and senior managers can inspect it. The bulk of the test planning effort is focused on creating the test cases. A test case is a description of a specific interaction that a tester will have, in order to test a single behavior of the software. Test cases are very similar to use cases, in that they are step-by-step narratives that define a specific interaction between the user and the software. However, unlike use cases, they contain references to specific features of the user interface. The test case contains actual data that must be entered into the software and the expected result that the software must generate.
A typical test case includes these sections, usually laid out in a table:
- A unique name and number
- A requirement that this test case is exercising
- Preconditions that describe the state of the software before the test case (which is often a previous test case that must always be run before the current test case)
- Steps that describe the specific steps that make up the interaction
- Expected results that describe the expected state of the software after the test case is executed
The following table shows an example of a test case that would exercise one specific behavior in the search and replace requirement. This requirement specified how a search-and-replace function must deal with case sensitivity. One part of that requirement said, “If the original text was all lowercase, then the replacement text must be inserted in all lowercase.â€
Name | TC-47: Verify that lowercase data entry results in lowercase insert |
Requirement | FR-4 (Case sensitivity in search-and-replace), bullet 2 |
Preconditions | The test document TESTDOC.DOC is loaded (base state BS-12). |
Steps |
|
 Expected Results |
|