c# mvc website pdf file in stored in byte array display in browser : Delete pages of pdf reader control Library system azure .net windows console The%20Art%20of%20Unit%20Testing%20with%20Examples%20in%20.NET%20(Manning%202009)26-part1058

Tough questions and answers
235
them. Some empirical evidence can be gleaned from the web, of com-
panies  and  colleagues  having  great  results  and  never  wanting to  go 
back to a code base without tests. 
A few studies on TDD can be found at http://biblio.gdinwiddie.com/
biblio/StudiesOfTestDrivenDevelopment.
8.4.5 Why is the QA department still finding bugs?
The  job  of  a  QA  engineer  is  to  find  bugs  at  many  different  levels, 
attacking  the  application from many  different  approaches. Usually  a 
QA  engineer  will  perform  integration-style  testing,  which  can  find 
problems that unit tests can’t. For example, the way different compo-
nents work together in production may point out bugs even though the 
individual components pass unit tests (which work well in isolation). 
In addition, a QA engineer may test things in terms of use cases or full 
scenarios that unit tests usually won’t cover. That approach can dis-
cover  logical bugs or  acceptance-related  bugs and is a great help to 
ensuring better project quality.
A study by Glenford Myre showed that developers writing tests were 
not really looking for bugs, and so found only half to two-thirds of the 
bugs in an application. Broadly, that means there will always be jobs 
for QA engineers, no matter what. Although that study is 30 years old, 
I think the same mentality holds today, which makes the results still 
relevant today, at least for me.
NOTE
Glenford Myre’s study is discussed in “A controlled experiment in 
program testing and code walkthroughs/inspections,” in 
Communica-
tions of the ACM
21, no. 9 (September 1978), 760–68.
8.4.6 We have lots of code without tests: where do we start?
Studies conducted in the 1970s and 1980s showed that, typically, 80 
percent of the bugs are found in 20 percent of the code. The trick is to 
find  the code that  has the most problems. More often than not, any 
team can tell you which components are the most problematic. Start 
there. You can always add some metrics, as discussed in section 8.2.5, 
relating to the number of bugs per class.
Delete pages of pdf reader - remove PDF pages in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Provides Users with Mature Document Manipulating Function for Deleting PDF Pages
copy pages from pdf to word; delete pages pdf
Delete pages of pdf reader - VB.NET PDF Page Delete Library: remove PDF pages in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
Visual Basic Sample Codes to Delete PDF Document Page in .NET
delete page from pdf file online; delete pages out of a pdf file
236
CHAPTER 8    Integrating unit testing into the organization
NOTE
Studies that show 80 percent of the bugs being in 20 percent of the 
code  include  the  following:  Albert  Endres,  “An analysis  of errors 
and their causes in system programs,” 
IEEE Transactions on Software 
Engineering
2  (June  1975), 140–49;  Lee  L.  Gremillion,  “Determi-
nants of program repair maintenance requirements,” 
Communications 
of  the  ACM
27,  no.  8  (August  1984),  826–32;  Barry  W.  Boehm, 
“Industrial software metrics top 10 list,” 
IEEE Software
4, no. 9 (Sep-
tember 1987), 84–85; and Shull and others, “What we have learned 
about fighting defects,” 
Proceedings of the 8th International Symposium 
on Software Metrics
(2002), 249–58.
Testing legacy code requires a different approach than when writing 
new code with tests. See chapter 9 for more details.
8.4.7 We work in several languages: is unit testing feasible?
Sometimes tests written in one language can test code written in other 
languages, especially if it’s a .NET mix of languages. You can write tests 
in C# to test code written in VB.NET, for example. Sometimes each 
team writes tests in the language they develop in: C# developers can 
write tests in C# using NUnit or MbUnit, and C++ developers can write 
tests using one of the C++ oriented frameworks, such as CppUnit. I’ve 
also seen solutions where people who wrote C++ code would write man-
aged C++ wrappers around it and write tests in C# against those man-
aged C++ wrappers, which made things easier to write and maintain.
8.4.8 What if we develop a combination of software and hardware?
If your application is made of a combination of software and hardware, 
you need to write tests for the software. Chances are, you already have 
some  sort  of  hardware  simulator,  and  the  tests  you  write  can  take 
advantage of this. It may take a little more work, but it’s definitely pos-
sible, and companies do this all the time.
8.4.9 How can we know we don’t have bugs in our tests?
You need to make sure your tests fail when they should and pass when 
they should. Test-driven development is a great way to make sure you 
don’t  forget  to  check  those  things.  See  chapter  1  for  a  short  walk-
through of TDD.
C# PDF File & Page Process Library SDK for C#.net, ASP.NET, MVC
VB.NET Page: Insert PDF pages; VB.NET Page: Delete PDF pages; VB.NET Annotate: PDF Markup & Drawing. XDoc.Word for XImage.OCR for C#; XImage.Barcode Reader for C#
delete page from pdf preview; delete pages on pdf
C# PDF Page Insert Library: insert pages into PDF file in C#.net
how to merge PDF document files by C# code, how to rotate PDF document page, how to delete PDF page using C# .NET, how to reorganize PDF document pages and how
delete pages from pdf document; delete pages from pdf acrobat
Tough questions and answers
237
8.4.10 My debugger shows that my code works: why do I need tests?
You may be sure your code works fine, but what about other people’s 
code?  How  do  you  know  it  works? How do  they  know your  code 
works  and  that  they  haven’t  broken  anything  when  they  make 
changes? Remember that coding is just the first step in the life of the 
code. Most of its life, the code will be in maintenance mode. You need 
to make sure it will tell people when it breaks, using unit tests.
A study held by Curtis, Krasner, and Iscoe showed that most defects 
don’t  come  from  the  code  itself,  but  result  from  miscommunication 
between people, requirements that keep changing, and a lack of appli-
cation domain knowledge. Even if you’re the world’s greatest coder, 
chances are that, if someone tells you to code the wrong thing, you’ll do 
it. And when you need to change it, you’ll be glad you have tests for 
everything else to make sure you don’t break it.
NOTE
The study by Bill Curtis, H. Krasner, and N. Iscoe is “A field study 
of the software design process for large systems,” 
Communications of 
the ACM
31, no. 11 (November 1988), 1268–1287.
8.4.11 Must we do TDD-style coding?
TDD is a style choice. I personally see a lot of value in TDD, and many 
people find it productive and beneficial, but others find that writing the 
tests after the code is good enough for them. You can make your own 
choice.
If this  question arises from  a fear of  too much change happening  at 
once, the learning can be broken up into several intermediate steps:
Learn unit  testing from books such as this, and use  tools  such as 
Typemock  Isolator  or  JMockit  so  that  you  don’t  have  to  worry 
about design aspects while testing.
Learn good design techniques, such as SOLID (which is discussed 
at the end of section 3.6 in chapter 3).
Learn  to  do  test-driven  development.  (A  good  book  is 
Test-Driven 
Development in Microsoft .NET
by James Newkirk.)
This way, the learning is easier and you can get started more quickly 
with less loss of time to the project.
VB.NET PDF Page Insert Library: insert pages into PDF file in vb.
Page: Insert PDF Pages. |. Home ›› XDoc.PDF ›› VB.NET PDF: Insert PDF Page. Add and Insert Multiple PDF Pages to PDF Document Using VB.
delete page from pdf acrobat; delete pages pdf files
VB.NET PDF delete text library: delete, remove text from PDF file
Visual Studio .NET application. Delete text from PDF file in preview without adobe PDF reader component installed. Able to pull text
cut pages from pdf preview; reader extract pages from pdf
238
CHAPTER 8    Integrating unit testing into the organization
Implementing unit testing in the organization is something that many 
readers of this book will have to face at one time or another. Be pre-
pared. Make sure you have good answers to the questions you’re likely 
to be asked. Make sure that you don’t alienate the people who can help 
you. Make sure you’re ready for what could be an uphill battle.
In the next chapter, we’ll take a look at legacy code and examine some 
tools for working with it. 
8.5 Summary
C# PDF Page Rotate Library: rotate PDF page permanently in C#.net
batch changing PDF page orientation without other PDF reader control. NET, add new PDF page, delete certain PDF page, reorder existing PDF pages and split
delete a page from a pdf without acrobat; delete blank pages in pdf online
C# PDF delete text Library: delete, remove text from PDF file in
Delete text from PDF file in preview without adobe PDF reader component installed in ASP.NET. C#.NET PDF: Delete Text from Consecutive PDF Pages.
delete page on pdf document; add and delete pages from pdf
239
Working with legacy code
This chapter covers
•Examining common problems with legacy code
•Deciding where to begin writing tests
•Surveying helpful tools for working with legacy code
once  consulted  for  a  large  development  shop  that  produced  billing 
software. They had over 10,000 developers and mixed .NET, Java, and 
C++  in  products,  subproducts,  and  intertwined  projects.  The  software 
had existed in one form or another for over five years, and most of the 
developers were tasked with maintaining and building on top of existing 
functionality. 
My  job  was  to  help  several  divisions  (using  all  languages)  learn  test-
driven development techniques. For about 90 percent of the developers I 
worked  with, this  never  became a reality  for  several  reasons,  some  of 
which were a result of legacy code:
It was difficult to write tests against existing code.
It was next to impossible to refactor the existing code (or there was not 
enough time to do it).
Some people didn’t want to change their designs.
Tooling (or lack of tooling) was getting in the way.
It was difficult to determine where to begin.
I
VB.NET PDF Page Extract Library: copy, paste, cut PDF pages in vb.
C:\test1.pdf") Dim pdf2 As PDFDocument = New PDFDocument("C:\test2.pdf") Dim pageindexes = New Integer() {1, 2, 4} Dim pages = pdf.DuplicatePage(pageindexes
delete page in pdf online; acrobat remove pages from pdf
C# PDF Page Extract Library: copy, paste, cut PDF pages in C#.net
C#.NET PDF Library - Copy and Paste PDF Pages in C#.NET. Easy to C#.NET Sample Code: Copy and Paste PDF Pages Using C#.NET. C# programming
delete blank page in pdf; add or remove pages from pdf
240
CHAPTER 9    Working with legacy code
Anyone who’s ever tried to add tests to an existing system knows that 
most such systems are almost impossible to write tests for. They were 
usually written without proper places in the software (seams) to allow 
extensions or replacements to existing components.
There  are several  problems that  need  to be addressed when dealing 
with legacy code:
There’s  so  much  work, where  should  I start  to  add  tests?  Where 
should I focus my efforts?
How can I safely refactor my code if it has no tests to begin with?
What tools can I use with legacy code?
This  chapter  will  tackle  these  tough  questions  associated  with 
approaching legacy code bases, by listing techniques, references, and 
tools that can help.
Assuming  you  have  existing  code  inside  components,  you’ll  need  to 
create a priority list of components for which testing makes the most 
sense. There are several factors to consider that can affect each compo-
nent’s priority:
Logical complexity—
This refers to the amount of logic in the component, 
such as nested ifs, switch cases, or recursion. Tools for checking cyc-
lomatic complexity can also be used to determine this.
Dependency  level—
This  refers  to  the  number  of  dependencies  in  the 
component. How many dependencies do you have to break in order 
to bring this class under test? Does it communicate with an outside 
email component, perhaps, or does it call a static log method some-
where?
Priority—
This is the component’s general priority in the project.
You can give each component a rating for these factors, from 1 (low 
priority) to 10 (high priority).
Table 9.1 shows a short list of classes with ratings for these factors. I 
call this a 
test-feasibility table
.
9.1 Where do you start adding tests?
Where do you start adding tests?
241
Table 9.1 A simple test-feasibility table 
From the data in table 9.1, we can create the diagram shown in figure 
9.1, which graphs our components by the amount of value to the proj-
ect and number of dependencies.
We can safely ignore items that are below our designated threshold of 
logic (which I usually set at 2 or 3), so 
Person
and 
ConfigManager
can be
Component
Logical 
complexity
Dependency 
level
Priority
Notes
Utils
6
1
5
This utility class has few depen-
dencies but contains a lot of 
logic. It will be easy to test, and it 
provides lots of value.
Person
2
1
1
This is a data-holder class with 
little logic and no dependencies. 
There’s some (small) real value 
in testing this.
TextParser
8
4
6
This class has lots of logic and 
lots of dependencies. To top it 
off, it’s part of a high priority task 
in the project. Testing this will 
provide lots of value but will also 
be hard and time-consuming.
ConfigManager
1
6
1
This class holds configuration 
data and reads files from disk.  
It has little logic but many  
dependencies. Testing it will  
provide little value to the project 
and will also be hard and  
time-consuming.
Figure 9.1 Mapping components for 
test feasibility
242
CHAPTER 9    Working with legacy code
ignored. We’re left with only the top two components from figure 9.1. 
There are two basic ways to look at the graph and decide what you’d 
like to test first (see figure 9.2):
Choose the one that’s more complex and easier to test (top left).
Choose the one that’s more complex and harder to test (top right).
The question now is what path you should take. Should you start with 
the easy stuff or the hard stuff?
As the previous section explained, you can start with the components 
that are easy to test or the ones that are hard to test (because they have 
many dependencies). Each strategy presents different challenges. 
9.2.1 Pros and cons of the easy-first strategy
Starting out with the components that have fewer dependencies will 
make writing the tests initially much quicker and easier. But there’s a 
catch, as figure 9.3 demonstrates.
Figure  9.3 shows  how long  it takes to  bring  components  under  test 
during the lifetime of the project. Initially it’s easy to write tests, but as 
time goes by, we’re left with components that are increasingly harder 
and harder to test, with the particularly tough ones waiting for us at the 
end of the project cycle, just when everyone is stressed about pushing a 
product out the door.
9.2 Choosing a selection strategy 
Figure 9.2 Easy, hard, and irrelevant 
component mapping based on logic 
and dependencies
Choosing a selection strategy 
243
If  your  team  is  relatively  new  to  unit-testing  techniques,  it’s  worth 
starting with the easy components. As time goes by, the team will learn 
the techniques needed to deal with the more complex components and 
dependencies. 
For such a team, it may be wise to initially avoid all components over a 
specific number of dependencies (with 4 being a good place to start).
9.2.2 Pros and cons of the hard-first strategy
Starting  with  the more  difficult components  may seem  like  a  losing 
proposition to begin with, but it has an upside, as long as your team has 
experience with unit-testing techniques.
Figure 9.4 shows the average time to write a test for a single compo-
nent over the lifetime of the project, if you start testing the components 
with the most dependencies first.
Figure 9.3 When starting with the 
easy components, the time to test 
gets longer and longer until the 
hardest components are done. 
Figure 9.4  When you use a hard-
first strategy, the time to test is 
long for the first few components, 
and then it gets shorter as more 
dependencies are refactored away.
244
CHAPTER 9    Working with legacy code
With this strategy, you could be spending a day or more to get even the 
simplest tests going on the more complex components. But notice the 
quick decline in the time required to write the test relative to the slow 
incline in figure 9.3. Every time you bring a component under test and 
refactor it to make it more testable, you may also be solving testability
issues for the dependencies it uses, or for other components. Specifi-
cally because that component has lots of dependencies, refactoring it 
can improve things for other parts of the system. That’s why the quick 
decline appears. 
The hard-first strategy is only possible if your team has experience in 
unit-testing techniques, because it’s harder to implement. If your team 
does have experience, use the priority aspect of components to choose 
whether  to start with the  hard  or easy components first. You  might 
want to choose a mix, but it’s important that you know in advance how 
much effort will be involved and what the possible consequences are.
If you do plan to refactor your code for testability (so you can write 
unit tests), a practical way to make sure you don’t break anything dur-
ing the refactoring phase is to write integration-style tests against your 
production system. 
I consulted on a large legacy project, working with a developer who 
needed to work on an XML configuration manager. The project had no 
tests and was hardly testable. It was also a C++ project, so we couldn’t 
use a tool like Typemock Isolator to isolate components without refac-
toring the code.
The developer needed to add another value attribute into the XML file 
and be able to read and change it through the existing configuration 
component. We ended up writing a couple of integration tests that used 
the real system to save and load configuration data, and that asserted 
on the values the configuration component was retrieving and writing 
to the file. Those tests set the “original” working behavior of the config-
uration manager as our base of work. 
9.3 Writing integration tests before refactoring
Documents you may be interested
Documents you may be interested