System Delphi

Title: Testing and Debugging Windows Services and Web Services in .NET Framework
Question: Testing and debugging is an important factor in the application development life cycle. Various tools provided by the .NET Framework are implemented in an application in order to test and debug the application so that its efficiency can be measured before deploying it.
Answer:
Various tracing techniques have also been implemented to trace errors or defects in the program code and debug them so that the cause of errors can be easily detected and the application can be defect free.
When an application is developed, it is required to ensure that the application is free from defects and it fulfills the requirements for which it has been developed. Therefore, developers perform various levels of testing on an application. Testing also measures the quality of an application. It reduces the cost of developing an application by eliminating the cost of rectifying errors after the application has been deployed. So, the process of testing is an important phase in the software development life cycle. An application can be subjected to the following levels of testing:
Requirements Testing:Requirements testing is performed before any other levels of testing. In the process of Requirements testing, it is verified whether or not the application fulfills all the requirements as specified in the software specification.Usability Testing:Usability testing is performed on the application to test whether the user is able to use the application without any problems. During the process of Usability testing, various checks are performed to verify that the application meets the requirements.Unit Testing:Unit testing is the lowest level of testing. At this level, each elementary unit of the application is tested separately before integrating it into modules. Unit testing requires basic tests at the component level to determine whether it behaves exactly as it was expected. This testing requires small, special programs known as test drivers and stubs to be written. These programs use the component or the class being tested and are used throughout the testing process. The following are some of the advantages of Unit testing:Unit testing is cost effective, as the test drivers and stubs can be reused during the testing process, and the cost of retesting can be controlled in a much better way.It enhances the process of testing, as each elementary unit of the application is tested separately.It has been proven that during the process of Unit testing a large percentage of defects are identified and can be removed at the initial level.It also simplifies the process of debugging, as it limits the search for errors to a small unit of the application instead of having to find out errors in the whole of the application.Integration Testing: Integration testing is the integration or combination of two or more units (already being tested) into one component. It also tests the interfaces between those units. In this level of testing, each component is tested before being integrated into a module, and each of the modules is tested before being integrated into an application. Integration testing identifies those errors that can occur while combining two or more elementary units of the application. Integration testing can be performed in a variety of ways, but the following are the three common approaches that are adopted during this level of testing:Top-down approach: The top-down approach to Integration testing starts with the high-level modules that are integrated first, and then it gradually proceeds toward the low-level subsystems. In this approach, high-level logic and data flow are tested before writing stubs for the utility modules in the development process. But the stubs complicate the testing process, as the low-level utilities are tested much later in the development cycle.Bottom-up approach:The bottom-up approach to Integration testing starts with the low-level units that are integrated first, and then it gradually proceeds toward the high-level subsystems. In this approach, smaller units or utility modules are tested much earlier than the high-level logic and data flow in the development process. This approach requires writing test drivers, instead of stubs, for testing the integration between the subsystems. But the test drivers also create complications in the testing process. Like the top-down approach, this approach, too, has a weak support for early release of limited functionality.Umbrella approach:The umbrella approach to Integration testing combines the two approaches that are the top-down approach and the bottom-up approach. This approach focuses mainly upon testing the modules that contain high degree of user interaction. In this approach, the input modules are integrated in the bottom-up pattern, and the output modules are integrated in the top-down manner. This approach is beneficial in the sense that it enables early release of a GUI-based application that enhances its functionality. But this approach is less systematic than the other two approaches.Regression Testing:Regression testing can be performed any time when a program needs to be modified either to add a feature or to fix an error. It is the process of repeating Unit testing and Integration testing along with the new tests. It ensures that no existing errors have reappeared and no new errors are introduced.
Implementing Tracing and Debugging
Tracing is the process of recording information about program execution. The execution of a program can easily be traced by generating messages about code execution while it is running. Tracing is an important part in the process of testing. It tracks events in each line of program code and reveals the presence of errors in the application. On the other hand, debugging is the process of finding and correcting the logic errors that were found during the tracing process. Hence, debugging is significant in the testing process in the sense that it debugs and troubleshoots the application and determines that the application is defect free and should execute properly.
While developing an application, tracing and debugging instrumentation can be added to the .NET application by using the Trace and Debug classes derived from the System.Diagnostics namespace. Placing trace statements at various strategic locations in the program code can instrument a distributed application. By using the Trace and Debug classes, developers can obtain useful information whenever the program gives erroneous results and monitor the performance of the application. Therefore, tracing and debugging help the developer to closely examine how well the program code is executing and how well the application fulfills the requirements defined in the software specification.
Various methods and properties of the Trace and Debug classes can be useful when they are placed within the program in order to track errors in the code at runtime, and to debug and monitor the efficiency of the application. The following are the methods and properties of the Trace and Debug classes:
MemberNameTypeDescriptionAssert()MethodChecks for a particular condition and evaluates to true at runtime. It displays a message if the condition is false.Close()MethodFlushes the output buffer and then closes the connection with the Listeners collection.Fail()MethodExhibits an error message.Flush()MethodWrites all the buffered data to the Listeners collection and then flushes the output buffer.Indent()MethodIncrements the current IndentLevel property by one.Unindent()MethodDecrements the current IndentLevel property by one.Write()MethodWrites information to the trace listeners in the Listeners collection.WriteIf()MethodWrites information to the trace listeners only if the condition is true.WriteLine()MethodWrites appended information with a new line character to the trace listeners in the Listeners collection.WriteLineIf()MethodWrites appended information with a new line character to the trace listeners in the Listeners collection if the condition is true.AutoFlushPropertySets the value to true indicating whether the Flush method should be called on Listeners after every write.IndentLevelPropertyIdentifies the indent level. Its default property value is zero.IndentSizePropertySpecifies the number of spaces in an indent. Its default indent size is four.ListenersPropertySpecifies the collections of listeners that monitor the debug output.