Domain: automatedqa.com
Stories and comments across the archive that link to automatedqa.com.
Comments · 8
-
Memory Checker
We also found BoundsChecker to be too slow to be very useful. AQTime (AutomatedQA), on the other hand, is relatively cheap and fast. There's a full featured (time limited) trial version that you can download.
-
AutomatedQA's AQTime
Check out AQTime.
I use it for profiling big multi-threaded client/server applications and it usually comes in handy at spotting memory leaks and the bottlenecks in the code.
I use it with Delphi's native win32 compiler, but it supports a wide array of platforms. I believe it supports everything you need on
.NET and the price tag is quite affordable. -
Re:Delphi (ObjectPascal) rules.
Still use it every day here as well. I've always found it the best compromise between speed of development, type safety, power, and ease of finding easy-to-grab components for everything from GIS to on-screen gauges to internet suites. Thumbing around Torry's or efg's Computer Lab provides a nifty, but very small, sampling of what's out there.
I'm actually pretty glad to see it's catching on again. We just attended the Delphi Diamondback/2005 roadshow, and I was impressed at the number of folks there compared to what I've seen in past years. Things are starting to pick up at the user group as well. I'll be demoing AQTime from Automated QA, a freakishly fantastic product for the price (from a corporate view, anyhow
;)I've been actually not been terribly compelled to upgrade from Delphi 5 as a development platform. Not that later versions haven't been good, but the upgrades have been mostly in areas I'm not doing anything in, like the n-tier and web pieces.
We always upgrade one copy, though, and I attend conventions as I can. When Delphi for
.NET came out, I was pretty seriously impressed. They put a lot of care and attention into making sure that ports from Win32 would be as painless as possible, but to let you go off and start off with native .NET and the FCL. Took less than a week to port my framework, and most of that was learning .NET idioms (like Finalize, strings being copy-on-modify, creating weak references).You're often at the mercy of your component vendors, though, so if you were one of those that thought that the quality of the component code didn't matter as long as it worked... the pointer-trick and copy-and-paste coder segment will fall on tough times
:)Quite frankly, porting code, the trouble spots are basically:
- Third party components
- String tricks (given that
.NET's strings are almost over-protected, and that they are WideStrings by default - API calls
Delphi 9, or Delphi 2005, as they're calling it, is the first compelling upgrade I've seen for folks like me, who spend a lot of time in the class interface design, source code and unit testing arena.
Delphi 2005 hosts three environments, Delphi/Win32, Delphi for
.NET and C#. A lot of Delphi 8's language enhancements have made it into the Delphi/Win32 side, such as enumerator syntax (for MyString in MyStringList do...). The editor, at last, does a number of the refactorings that the JBuilder crew has had access to, such as Extract Method and a smart Declare Variable (e.g. X := MyControl.Parent will suggest TWinControl). The folding editor has a number of tricks up its sleeve, and a number of file backups are maintained which you can diff inside the environment, helpful if you run into troubles more granular than your version control system's checked-in versions. Nice to see some of the integrated tools and projects as well. New->Unit Test will give you DUnit (for Win32) or NUnit (for .NET) shells, and there are a ton more bits 'n' pieces I haven't had the opportunity to play with (the ASP.NET projects are pretty smooth).Kylix was a bit before its time, really. Linux is such a freakishly fast-changing environment (as I sit here in my Fedora Core partition in utter awe of what yum says I must also update to update some of the major package around - gah!), and there isn't enough corporate-level interest in easy GUI programming for Linux to fund keeping up with it.
I got Kylix 2, and personally found it pretty good for porting, and a fairly decent environment (it used WINE, although apps made with it did not), although seamless it
-
Testing's Many Layers
The best defense against a client-side blowup is to have as many layers as possible helping out, because they all have their various strengths and vulnerabilities.
In development:
- Good design: The larger the project, the more cowboy coding and migrated-to-production prototype code can hurt the process. Many bugs come in the form of workarounds, repeated code, or unclear code responsibilities, all of which can be mitigated by good design.
- Unit test: Developers have a better idea of the contract the rest of a program has with various classes than any other department. Unit testing is all about proving that contract still holds, and can not only protect you against breaking that contract with other code changes, but provide a spot to add tests for newly-discovered failures (we can't necessarily account for all failures in advance). Remember: before fixing a bug, write a test that fails with the bug but should succeed, run the test and ensure it fails, THEN fix the bug.
- Assert
... or whatever equivalent to assertions you have that you don't turn off. So many bugs come from things that are deemed to be "impossible". If they're so "impossible", prove it. They may not be impossible in the future - most come from bad input, or changed assumptions about the code or the environment. You don't need to code in Eiffel in order to assert/complain that the input was out of range, or null, or blank, or that the lengths of two lists you're keeping in the same class should be the same. COROLLARY: If you have an assertion on bad data, you should make a unit test case with bad data, and tell the unit test case that you expect it to fail. - Reduce combinations: If you can simplify your path through the code, do it. If you have trouble tracing through the code (especially in a long method), or identical code appears throughout, extract the common pieces into something sensibly named. Many bugs crop up due to 'not remembering to update everything', or just plain not being able to keep track of the logic flow through the code in the first place, or when making changes.
QA:
- Good people: Wow, does this make a difference! I thank the circumstances-that-be for our QA head Scott. Any replacement will have big shoes to fill
:) - Good communication: Often, QA ends up being a liaison in many ways between support, deployers, and R&D - to ask/verify how problems happen, how things are supposed to work, and what new features and bug fixes are and imply.
- Automation tools: For the tedious parts, and for regression testing. We use TestComplete for things like stress-testing, overnight testing, ensuring problems don't come up for any items in a set (good for when you have many items to load and test in any solution), and testing expectations in different environments. It also includes a slightly more white-box feature for writing test scripts that can verify exposed internal values.
- Good backbone and support: QA itself needs to have the temerity to put their foot down and say "it's not ready", and it's the responsibility of others to throw their hat into the ring in support whenever this is the case, because it can be an unpopular stance. Not standing your ground on this can end up blowing up. That doesn't mean there's no ground for negotiation (e.g. we can release this to THIS specific client IF we test only for one database back-end with office-only deployment and a roll-back plan), but it's a strong starting stance.
Support and IT
- Believe them: They're not making up software problems, at the very least the ones they're seeing with their own eyes. Something "impossible" just happened. It could be that there's another piece of software that munches your PDF-printing DLL, it could be a firewall setting, it cou
-
Postmature optimization
After years of developing, I really take to heart two things:
- Premature optimization often makes better optimizations down the line much more difficult
- It's 90% guaranteed that the slowdown isn't where or what you thought it was
Profilers are the best thing to happen to performance since compilers - really. I encounter a number of truths, but many myths about what degrades performance. A few examples of each:
Performance degraders
- Mass object construction
- Searching sequentially through large arrays
- Repeated string concatenation (there are techniques to mitigate this)
- Staying inside critical sections for too long
Not performance degraders
- Lots of object indirection
- Lots of critical sections
The "lots of object indirection" myth is one I encounter frequently. Object A calls Object B calls Object C, and it "intuitively" looks like it must be slow (Computer A calling Computer B, etc. would be slow), but even with stack frame generation, these are lightning fast compared with even the likes of "date to string" functions, never mind line-drawing commands or notification-sending.
The reason that particular myth is dangerous is that it's the single most pervasive myth (IMHO) that leads to premature optimization. People take out layers of object indirection and make it harder to put in better solutions later. I had an object that recorded object IDs in a list and let you look them up later. If I had "flattened" that into the routine that needed it, I might have effected a 0.1% speed increase (typical range for many premature optimizations). As it stood, because it hid behind an interface (equivalent to an ABC for C++ folks), when I had finally implemented a unit-tested red/black tree, it was trivial (~5 minutes) to drop in the new functionality. That's not an isolated case, either.
Mind you, I profiled the program to determine the slowdown first. Searching on the list, because so many were misses (therefore full scans), the search was taking up 98.6% of the entire operation. Switching to the red/black tree dropped the search down to 2.1%.
All in all, if you have a slow program, profile it. There is no substitute for a well-written profiler. Stepping through and "feeling" how long it takes in a debugger, while it can point you in rough directions, will miss those things that take 50 ms out of the middle of each call to the operation you're checking. Manually inserting timing calls can be frustrating enough to maintain or slow down your program enough that you can't narrow down the performance hit.
gprof works well with gcc and its relatives (make sure to add -pg to your flags), but I'm not sure if there's a good open source option out there for people using other tools that doesn't require you to alter your source.
In the Windows world, we recently got in the professional version of AQTime 3. It's an astounding package, allowing you numerous reports, pie charts and call graphs, saving the last few runs, calculating differences in performance between runs, allowing attachment to running processes, on top of a pretty nice way to define areas of the program to profile. The single nicest thing about it, though, is the performance. We turned on full profiling (that is, profiling all methods in all modules, including all class library and third party components) on the largest project we had, and it ran with perhaps a 30% slowdown. If you've used profilers before, you know how astounding that is
;)Profiling applications always surprises me. In one case, a space-making algorithm I was running on controls seemed a little pokey; I found out more than 50% of the time spent was on constantly verifying that the lists were sorted. Today, I was investigating a dialog that looked like it must hav
-
Unit testing as quality control
Unit testing does not require eXtreme Programming. On the other hand, eXtreme programming does require unit testing. We've studied XP's practices, and they seem to be roughly broken into two groups: programming for ever-changing requirements, and quality assurances (refactoring, unit testing) to make sure the code doesn't fall apart.
As many anti-XP pundits will point out, unit testing is worth applying to any project that you can apply it to, and there are precious few that can't.
I do a lot of framework-level programming, and I must say that stability, as well as my confidence in the code, has increased substantially from putting unit testing into the mix. Some folks advocate TDD (Test-Driven Development) in the canonical sense (test first), but I find that the completely up-front test creation works in practice only when you have rock-solid easy-to-translate-into-source-code checklisted requirements. I compromise, and build the tests after the interfaces, rough algorithm and rough support objects have been put together.
Here are a few things I've learned over my unit testing experiences:
- If the individual test methods start to get beefy, spin off the pieces you can into English-sounding methods on their own, especially if it's something you find yourself using in multiple test methods. Methods for creating test objects and comparing the test results are usually prime candidates.
- If you have a facility to use generics in your programming, use it for anything you've had to do exactly the same 3+ times over - you can cover off the generic with a single unit test module
- Classes are easier to test if you make liberal use of interfaces or abstract base classes - this lets you create classes for use by the test that implement extremely rudimentary functionality (instead of asking a web service for a value, it returns "1", or gives back an error) and/or that can be used as counters/loggers for the number of times and with what parameters the services are requested.
- Negative testing is important - if you don't explicitly test what out of bounds, null or otherwise invalid input parameters and states do to your object, you're leaving yourself open to a host of "undefined behaviors" which can cause bugs.
- For unit testing lower-level classes, you'll often find that a unit-test-per-method works well. For unit testing higher-level classes, you'll find yourself keeping the class the same, but the test methods will vary the data that gets fed into it.
I haven't figured out a good means to unit test concurrent code, but you can often stack the deck for fast-running processes by adding in delays in key spots to extend the exposure to weak spots.
Unit testing isn't for everything. It coughs and sputters a bit when you don't have full control over the environment (databases, sockets, network configuration, user interaction). You can shoehorn it in, but it's usually better left for the likes of regression testing and functional integrated testing.
For a quick start to functional testing, we've started test-driving TestComplete at our office; it's proven itself to be a capable tool (our lead QA man has put up a sign on the computer entitled, "I am Q-Tron; I Test Software While Mere Mortals Sleep" - it has been testing out communications while he sleeps
:) -
Re:What exactly does this do?SC Test aims to produce regression testing software. This basically means that when software has new features added, regression testing tests to make sure it hasn't taken a step backwards (regressed). In plain english, regression testing tries to prevent new features from introducing bugs. A good introduction to regression testing is at AutomatedQA, although the software there is commerical their few words on regression testing are well worth reading.
This is what Webopedia has to say on the subject:
The selective retesting of a software system that has been modified to ensure that any bugs have been fixed and that no other previously-working functions have failed as a result of the reparations and that newly added features have not created problems with previous versions of the software. Also referred to as verification testing, regression testing is initiated after a programmer has attempted to fix a recognized problem or has added source code to a program that may have inadvertently introduced errors. It is a quality control measure to ensure that the newly-modified code still complies with its specified requirements and that unmodified code has not been affected by the maintenance activity. -
Re:GUI is not mutually exclusive to automation!I suggest you take a look at Automated QA's website. Their program, AQtest, allows you to write things like this:
Sys.Process("myprogram").Form1.Button1.Click
Not that I like M$ or anything, but I do think X sucks.