asp.net mvc display pdf : Change page size pdf acrobat control Library platform web page .net asp.net web browser Manning%20-%20Code%20Generation%20in%20Action18-part1337

152
CHAPTER 7
G
ENERATING
UNIT
TESTS
7.4.3
Processing flow 
Here is the process flow for the ordered generator:
Reads the test data input file and stores it locally.
Creates a buffer that will hold the test code.
Iterates through each test in order and follows these steps:
Inspects the return value to see if you are going to check against the return 
value or store the return value. If you are storing the return value, it runs the 
template to create the variable and selects the proper template to handle the 
invocation. It stores the variable creation code, if you created it, in the test code 
buffer.
Runs the invocation handler that builds the call to the function with the right 
arguments and either stores or inspects the output.
Stores the result of the template in the test code buffer.
Uses a template that provides a framework for the test code and adds the test code
to the framework.
Stores the final product in the output file.
At the end of the process, you will have test code that allows for sequential API access.
7.5
T
ECHNIQUE
THE
TEST
DATA
GENERATOR
Testing a function or class well means running a lot of tests on it with a variety of data.
Ideally you would use data that stresses the target code in a number of directions. The
data would test the positive function of the API by sending in valid data. In addition, it
would test negative conditions by sending in bad data or by calling the API out of
sequence. The mechanism should also test the API under load by sending in large
amounts of data.
The test data generator randomly generates test data that can then be used to test
against the target class or function. Ideally, you would create the random output once
and store it so that it could be predictably used over and over again against the same
target. Randomly generating data for each test is troublesome for two reasons. First,
you will not get the same coverage of test cases each time. Second, you will get unpre-
dictable errors as a result of differing test data each time the test is run.
7.5.1
Roles of the generator
In order to define the physical architecture of the test data generator, you have to start
by defining the role of the generator and declaring with certainty what the generator is
responsible for—and what it is not responsible for. It has one main responsibility:
creating test data sets for the application.
Ordered test generator
Change page size pdf acrobat - Compress reduce PDF size in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
C# Code & .NET API to Compress & Decompress PDF Document
change font size in pdf text box; compress pdf
Change page size pdf acrobat - VB.NET PDF File Compress Library: Compress reduce PDF size in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
VB.NET PDF Document Compression and Decompression Control SDK
pdf font size change; reader shrink pdf
T
ECHNIQUE
THE
TEST
DATA
GENERATOR
153
And here are the tasks this generator is not responsible for:
• Building the test data loader.
• Building I/O functions or libraries to read the test data.
• Validating test data.
With these guidelines in mind, you can now design the architecture of the generator.
7.5.2
Laying out the generator architecture
You can define the test data generator as a tier generator because it uses an abstract
model of the test data and the test definition, along with some data and data templates
to create the finished test data. 
The generator takes as input a test definition file. This file contains information
about how much test data should be created, how many test data types there are, and
what each test data type looks like.
To create the data, the generator uses a set of data pools, from which it randomly
selects data elements. The generator then merges the input data with data templates,
which are used to format the data for output.
The data pools can be sets of names or addresses, or just different types of strings
or numeric values—any set of data from which you could derive some interesting
tests. The block I/O flow for the test data generator is shown in Figure 7.5.
The next section shows how this generator works.
7.5.3
Processing flow 
Here are the process steps for the test generator:
Reads the test definition and stores it locally
For each test data type:
Builds enough data for the amount of tests specified by selecting data 
randomly from the data pools for each of the fields
Sends the data to the data templates for output formatting
Stores the output in the test data file
Random
Generator
Data
Templates
TestData
Data
Pool
TestDefinition
Figure 7.5
The I/O flow for the generator, 
which builds data for test sets
Test data generator
VB.NET PowerPoint: VB Code to Draw and Create Annotation on PPT
other documents are compatible, including PDF, TIFF, MS a callout annoation on the first page of a obj As New RectangleAnnotation() ' set annotation size obj.X
acrobat compress pdf; change page size pdf
VB.NET PDF: How to Create Watermark on PDF Document within
or image (such as business's logo) on any desired PDF page. Via our PDF Watermark Creator, users are capable of to customize the text font style, size and color
pdf text box font size; pdf compress
154
CHAPTER 7
G
ENERATING
UNIT
TESTS
7.5.4
Using the test data generator and the sequential 
test generator together
Figure 7.6 shows how the test data generator can be used in conjunction with the
sequential test generator. The test data generator builds test data sets, which are then
fed to the sequential test generator to create test code within the test framework.
You could argue that the generators should be merged, but by separating the data
generation system from the test implementation system you extend the value of both
systems. The test data generator can be used to build data for other systems, such as
database loaders, while the sequential test generator can be used to find particular edge
cases in either random data sets or test sets that are hand-coded.
7.6
T
ECHNIQUE
THE
TEST
ROBOT
GENERATOR
When it comes to user interfaces, web applications are easier to test than desktop appli-
cations. To test a desktop application through the user interface, you need a framework
that can shield your test code from the system-level keyboard and mouse event genera-
tion used to implement the test. To test a web application through the user interface, all
you need is an HTTP access library.
Applications that walk through a web user interface are called robots. An example
robot for an online auction system may follow these steps:
• Fetches the main page and checks for the login form.
• Sends the login information via a POST.
• Gets and stores the session cookie.
• Requests the main page and parses the HTML to find the available items.
• Iterates through each item and fetches its page. It checks each page for the proper
data values against the database.
Generator
Invocation
Templates
TestCode
TestFramework
Random
Generator
Data
Templates
TestData
Data
Pool
TestDefinition
Figure 7.6 6 How the test data generator feeds the sequential test generator
T
ECHNIQUE
THE
TEST
ROBOT
GENERATOR
155
Each of these is a complete system test that makes use of the entire technology
stack, from the database access layer through the persistence layer and the user interface.
If a robot says your system is responding properly, then you are likely in good shape.
Robots have other uses as well:
• Stress-testing an application by sending lots of requests in a short period of time
• Random “monkey-testing” an application by fetching pages out of order
• Argument-testing an application by sending invalid or missing arguments from
the POST or GET
When building robots you should insulate your test code from the HTTP transit code
required to get the page, post requests, or parse responses. The generator in section 7.5.1
builds interface wrappers that can be used by robots to post data to the web application
or to fetch pages and parse their data.
7.6.1
Roles of the generator
Test systems become a source of infinite features once engineers understand that they
no longer need to tediously hand-test their code. To keep that from happening, it’s
ideal to lay down a set of responsibilities for the test system and its generator. The test
robot generator has one main responsibility: building automated tests for the pages
built to the predictable standards of the web user interface for the target application.
Here we’ve listed those tasks the generator does not take responsibility for:
• Documenting the tests.
• Testing interfaces that extensively use client-side functionality, such as JavaScript
or Flash; the automated testing agents cannot access or test that code because the
test agent is not a complete web browser.
With these guidelines in hand, you can continue on to designing the architecture of
the generator.
7.6.2
Laying out the generator architecture
The web generator in Figure 7.7 builds interface wrappers for your robots. The wrapper
hides the web transit logic from the robot, leaving the robot free to simply specify
which pages are to be called, with what arguments, and in what order. Multiple robots,
serving different purposes, can use these wrappers. The robots may load data, stress test,
or bridge between the application and other technologies, such as instant messaging.
Using page definitions, the generator builds wrappers that handle posting argu-
ments and then parsing the returned HTML from the server. The page definition file
must have this data about each page:
• The page URL
• The names and types GET or POST arguments
• The structure of the data returned on the page
156
CHAPTER 7
G
ENERATING
UNIT
TESTS
You can make it easy for the robots to find what they need by adding comments to the
pages they will read. You can also bracket the important data on the page in DIV or
SPAN tags, which are invisible to the user but are easily found using regular expres-
sions. By targeting the page parser on specific DIV or SPAN tags within the page, you
ensure that the robot will not break if the page structure changes for aesthetic reasons.
Let’s go back to the online auction system we discussed earlier. The first thing the
robot does after logging in is to see what is on sale. Here is some example HTML for
the “What is on sale?” page:
<html><head><title>What is on sale</title><head>
<body>
Here is what is on sale today (<div id="today">1/23/03</div>):<br><br>
<table>
<tr><td>Name</td><td>Price</td></tr>
<tr>
<td><a href="item.cgi?id=2601"><div id="name_2601">Java In A Nutshell</
div></a></td>
<td><div id=”price_2601">$26.95</div></td></tr>
<tr>
<tr>
<td><a href="item.cgi?id=2602"><div id="name_2602">Perl In A Nutshell</
div></a></td>
<td><div id="price_2602">$35.00</div></td></tr>
<tr>
<td>
If we use a regular expression that reads the DIV tags and gets the ID and contents, we
get the following ordered pairs of information:
today   1/23/02
name_2601   Java In A Nutshell
cost_2601   $26.95
name_2602   Perl In A Nutshell
cost_2602   $35.00
Generator
POST
Template
Page
Definitions
GETTemplate
PageData
ParserTemplate
Interface
Wrappers
Robots
UserInterface
Business
Logic
DB
Figure 7.7 7 A generator that builds robots for testing 
F
INDING
A
TOOL
TO
DO
IT
FOR
YOU
157
This is the data that is important to the robot. The rest of the page is aesthetic
information, which is important but not for this type of testing. The DIV tags insulate
our robot from any changes to the aesthetic look of the page. The graphic designers
can make any changes they like, so long as the 
DIV
tags remain.
Next we’ll look at how the robot goes about its work.
7.6.3
Processing flow 
The web robot page wrapper generator follows these steps:
Reads in the page definitions and stores them locally.
Goes through each page and follows these steps:
For a form page, builds a POST or GET wrapper to fill in the form variables.
For a report page, builds a page-parsing wrapper that reads and returns the 
contents of the SPAN or DIV tags.
Once this process is completed, you will have a set of wrappers that your robot can use
to walk the site and that provides a level of abstraction between your robot logic and
the layout of your site.
7.6.4
Generators for robots
Our wrapper generator merely built the interface wrappers for web pages that allows
robots to walk our application with ease. Another type of generator can generate the
robots themselves, using a dictionary of user actions. Here are two open source genera-
tors that build web robots:
• Sight is a toolkit for generating robots (http://jsight.sourceforge.net/index_SF.htm).
• Roboweb is a toolkit for building web robots (http://sourceforge.net/projects/
roboweb/).
7.7
F
INDING
A
TOOL
TO
DO
IT
FOR
YOU
Unit tests fit within test harnesses. These harnesses provide reporting capabilities, test
data generation capabilities, as well as other utilities useful in building unit tests. The
following list shows some off-the-shelf testing tools for unit tests:
• Segue (www.segue.com) provides a set of programmable testing tools that can
test Windows desktop and web application software.
• JUnit (www.junit.org/) is a unit test framework for Java.
• CppUnit (http://cppunit.sourceforge.net/) is a unit test framework for C++.
• HttpUnit (http://httpunit.sourceforge.net/) tests web applications through the
user interface using HTTP. 
• LWP::UserAgent (www.perldoc.com/perl5.6.1/lib/LWP/UserAgent.html) is a Perl
library for writing HTTP robots. 
Test robot generator
158
CHAPTER 7
G
ENERATING
UNIT
TESTS
• CsUnit (www.csunit.org) is a unit test framework for Microsoft’s .NET tech-
nology stack.
• PHPUnit (http://wiki.berlios.de/index.php?PhpUnit) is a framework for testing
PHP applications.
• PyUnit (http://pyunit.sourceforge.net/pyunit.html) is a unit testing framework
for Python.
• DataFactory (www.quest.com/datafactory/) from Quest Software connects directly
to a database to populate it with test data. 
7.8
D
ESIGN
TIPS
Here are some suggestions for designing your code so that you can build testing tools
using generators:
• For interface code, consistency is king. Preferably all of your pages will be gener-
ated to make sure that GET and POST arguments are named consistently and
processed the same way across the interface.
• For APIs, make sure your accessors and instance variables all use the same naming
conventions. Also, your return types should be standardized across the interface.
• Use JavaDoc or special comments that the test case builder can use to configure
itself to handle special API cases such as Singletons.
7.9
S
UMMARY
The code base of any application is a valuable asset to the individual or company who
owns or maintains the application. To maintain the code base long-term, software engi-
neers have started to refactor code continuously. The term refactoring refers to the disci-
pline of reworking the architecture of the application to match the current needs. As
applications progress, you often find that the design decisions made in the beginning of
the project are no longer valid, which means you have to refactor the code so that it will
elegantly solve the current problem. 
Unit tests are central to refactoring.  If you have unit tests that test your component
using test data and responses that match the current requirements, you can change the
implementation of the component at will. As long as the output of the component still
passes the unit tests, you can be reasonably sure the code is correct.
The key is having the unit tests in the first place. Having unit tests means that you
can refactor. Refactoring means that you can keep the code base fresh with constant
maintenance.
Using code generation for unit tests makes it easy to maintain and extend your unit
tests. In this way, you avoid the common pitfall of not maintaining the unit tests or
even failing to create them in the first place.
In the next chapter, we’ll tackle a generator that embeds SQL into another language.
159
C
H
A
P
T E R
8
Embedding SQL 
with generators 
8.1 PerlSQL 160
8.2 Preparing for common concerns s 161
8.3 Workflow comparison n 162
8.4 A case study: PerlSQL L 162
8.5 Finding SQL tools s 171
8.6 Summary y 171
Code that implements SQL queries can often lose intent of the original SQL state-
ments in the minutiae of the infrastructure requirements, such as managing the con-
nection, creating input buffers, or handling error conditions. To solve this problem,
vendors have created hybrid languages that embed SQL into an existing popular lan-
guage. Pro*C is an implementation of this technique. SQL is written directly into the
C code. During the compilation process, the Pro*C is turned into standard C by
expanding the SQL code into pure C code that sets up the database connection and
does the data marshalling and error checking.
We use the phrase embedding SQL to describe this process of building a domain-
specific language by extending a language syntax with a syntax where SQL commands
can be placed directly into the source without the infrastructure required to run the
SQL. You then build a generator (or compiler) that translates this new domain-
specific language into production code for deployment by implementing the code
required to run the SQL.
In this chapter, we present a case study generator that specifies a new language
called PerlSQL—Perl with embedded SQL. The PerlSQL is run through a generator
that builds the production Perl with the embedded SQL converted into executable
database interface (DBI) code.
160
CHAPTER 8
E
MBEDDING
SQL 
WITH
GENERATORS
8.1
P
ERL
SQL
Code simplification is the primary advantage of embedding SQL into a language. SQL
access requires creating infrastructure code that hides the intent of the author. The two
code samples that follow show the before and after pictures of a PerlSQL sample. 
This first fragment of PerlSQL runs a SELECT against the database:
use PerlSQL::PerlSQL;
use Data::Dumper;
use DB;
my $dbh = DB::get();
my $id = 10;
my $data = eval {                                                   
my $ps_sth0 = $dbh->prepare( "SELECT * FROM user_data WHERE id=:repvar1" );
$ps_sth0->bind_param( "repvar1", $id );
$ps_sth0->execute();
my $ps_out = ();                                                       
while( my $ps_row_ref = $ps_sth0->fetchrow_hashref() ) {               
push @$ps_out, $ps_row_ref;                                          
                                                                     
$ps_row_ref;                                                           
}
print Dumper( $data ); 
As you can see, the SQL query is obscured by the infrastructure code required to
implement the query. Here is the same code implemented as PerlSQL to simplify the
use of the SQL:
use PerlSQL::PerlSQL;
use Data::Dumper;
use DB;
my $dbh = DB::get();
my $id = 10;
my $data = <select>                                            
SELECT * FROM user_data WHERE id=<<$id>>                       
</select>                                                      
print Dumper( $data 
);
The <select> syntax reduces the visual clutter and emphasizes the point of the
code. It’s obvious that the intent of the code is to run the SELECT statement with the
$id value provided and to put the output into the $data variable.
The select tag tells PerlSQL to build the infrastructure to run the SELECT at
that point in the code. The <<$id>> syntax lets the generator know that the local
$id variable is to be used in the execute statement. With the exception of the
<select>…</select> tag, this is valid Perl.
The infra-
structure
code around
the SQL
The SELECT 
statement that 
we want to run
P
REPARING
FOR
COMMON
CONCERNS
161
In the next section, we discuss the issues that you’re likely to hear from your team
about implementing this type of generator.
8.2
P
REPARING
FOR
COMMON
CONCERNS
There are some well-founded concerns involved with building a new language such as
PerlSQL. We address these concerns in the sections that follow.
8.2.1
We are creating a new language
That is true: along with creating a language, you are taking responsibility for maintain-
ing the language long-term and educating engineers in its use.
You should base the decision to implement something like PerlSQL on an assess-
ment of your return on investment (ROI). Here are some advantages and disadvan-
tages to the technique, which will aid in your ROI assessment:
Advantages:
• Reduced code complexity
• Embedded elements that stand out within the code
• Embedded elements that provide an obvious indication of purpose
Disadvantages:
• The ability to debug the code directly is lost.
• New engineers will need training on the syntax.
• The engineering team is responsible for the long-term maintenance of the language.
Consider these factors carefully when deciding whether to build this type of domain-
specific language.
8.2.2
Debugging will be a pain
Because the PerlSQL code must be translated into Perl that resides in another file,
debugging against the PerlSQL code will be difficult. Changes made to the production
Perl code will have to be ported back into the PerlSQL code once the fix has been found.
As an alternative to the inline-code expander model, you could build PerlSQL
using a mixed-code generation scheme. That would allow you to debug the code
directly. You should consider this option when developing your generator.
8.2.3
With Perl you could do this within the language
Perl is an extremely flexible and powerful language. You could implement PerlSQL as a
syntax extension, just as Damian Conway did with the Lingua::Romana::Per-
ligata module, which allows you to write Perl in Latin.
This book focuses on the theory and implementation of generators. This chapter
is intended to provide an example that you can use to understand the construction of
inline-code expansion generators.
Documents you may be interested
Documents you may be interested