General question: Adding new test code to embedded system - testing

this maybe will be off topic, but I am preparing for an exam in real time. And I have been browsing the book and Internet for an answer for a problem.
Basically I wonder if by adding additional test code if it may change the real time behavior for an embedded system, and or also if it will introduce new errors.
Anyone who might know the answer for this, or refer me to some reading material for it?

Your question is too general.. So I guess the default answer would be it depends.. But considering the possibilities as an exercise of logic and thought, yes it surely can!
There are many schemes available to guarantee the 'real-timeness' of an embedded system. For example, one can have a pre-emptive timer based ISR to service the real-time task.. In such a case, your test code could possibly not affect the 'real-timeness'.. But if the testing takes too long, and the context switches are not pre-emptive, you could get into trouble..
But again it depends on what you're testing and how you're testing. Your test code can possible mess with the timers, interrupts or the memory of system. The possibilities to mess up stuff if you're not careful are endless..
Having an OS underneath will prevent some errors, but again depending on how it works, you may be saved from bad 'test code'..

Yes, when you add code (test, diagnostic, statistic) it may change the real time behavior. It depends on the design, the implementation and the CPU power if it will actually change the behavior. You also have more lines of code and the probability for errors may increase. But I wouldn't say, "it will introduce errors", since it can introduce errors.

Yes it can. See How can adding data to a segment in flash memory screw up a program's timing? for an example of how even adding non-executable code can adjust timing enough to screw up a system.

Yea, changing your code base could totally change its timing. Consider if you dumped some debug output to a serial port, it takes time to call that function, format the data, and if the function is synchronous, then for it to wait for data to go out. This kinda stuff definitely changes system timing behavior.

Related

Should I use test cases if my project requirement keeps changing?

Requirements in my project keeps changing too frequently. It has become very inconvenient to maintain test cases. Is it still advisable to use test cases? Or is there any good way to handle this problem?
This is part of the pain of having unit tests. You should stick with it.
You will be in a much better place when requirements settle down.
Without tests, you will more vulnerable -- when rapid change occurs, things are very likely to be broken accidentally.
If you abandon testing now is you are likely to not pick it back up again....
If you have to change the code, then I think it is more important than ever to maintain the test harness. The test harness is a form of documentation.
One more argument I will be saying to whoever tries to convince me 100% test coverage is the holy grail.
Project requirements do not change, like, altogether (unless this is very small project). There are always some assumptions, assertions, limits dictated by law of physics after all :)
I propose to go through requirements and to split them between tiers. Requirements of tier 1 are less likely to change than those of tier 2. This way you could focus on less volatile parts. Eventually requirements producer will get tired (replaced, bored).
Developers must be in poorer shape. Rapid requirement changes will get spaghetti code. Test harness can be spaghetti to some extent, but it is really a life saver to them. It is very important to keep it fit with such project organization.
Since you've tagged this question "TDD", think about how to implement a changed requirement via test-driven development. In the case of a new requirement, you would write a failing test that demonstrates the absence of the new feature. In the case of a changed requirement, you probably already have tests that show (by passing) that the feature is in its original state. So, test-drive your development. Change your passing tests so that they now require the new behavior - and fail - and now make them pass by implementing the changed behavior.
You should take the opportunities to review your designs to see if there are parts that often change with changing requirements. You can even make changes to the current design to move parts into two partitions: One that mostly stays the same and one that mostly changes.
You might be able to isolate the changing parts so that when requirements change you only need to add new code/classes.

When you write your code, do you deal with errors proactively or reactively?

In other words, do you spend time anticipating errors and writing code to get around these potential issues, or do you write the code as you see fit and then work through any errors on an issue by issue basis?
I've been thinking a lot about this lately and I'm very much a reactive person. I write my code, give it a whirl, go back correct error and repeat until application works as expected. However a friend of mine offered that he spends time thinking how each line is interpreted and fixes errors before they occur.
I must point out that re-active is pure PRE-live. I definitely make sure my application is working before it goes live.
There should always be a balance.
Too many error checking is slow and leads to garbage code. Not enough error checking makes your program crash on edge cases which is not very good to discover after having it shipped.
So you decide how reliable some piece of code should be and implement error checking accordingly. Some test utility can be not very reliable - less error checking. A COM server meant to be used by a third party search service in deep background should be super reliable - much more error checking.
I think asking this in isolation is kinda weird, and very subjective, however there are obviously a bunch of techniques that permit you to do each. I tend to use these two:
Test-driven development (this would seem to be proactive)
Strong, static typing (reactive, but part of a tight iterative development cycle, as in, it's enforced by my ML compiler, and I compile a lot)
Very occasionally I swerve into the world of formal verification of programs. That's definitely "reactive", but if you think a little more up-front, it tends to make the verification easier.
I must also say that I value a lot of up-front thought in programming. The easiest way to avoid bugs is to not write them in the first place. Sometimes it's inevitable, but often a little more time spent thinking about the problem can lead to better-quality solutions, and then the rest can be taken care of using the kinds of automated methods I talked about above.
I usually ask myself a bunch of what-ifs when coding, like
The user clicks the button, what if they didn't select a date?
The user is typing in the search box, what if they try to type html in there?
My label text depends on a value from a shared drive, what if it's not mapped?
and so on. By doing this I've found that when the application does go live, there are a ton fewer errors and I can focus on fixing more obscure bugs instead of correcting conditions that should have been in place to begin with.
I live by a simple principle when considering error-handling: garbage in, garbage out. If you don't want any garbage (e.g. invalid input) messing up your software, you have to find all the points in your software where it can get in and handle it. Of course, the more complicated your software is, the harder it is to find every point of entry, but I feel that the more you do up front the less reactive you will need to be later on.
I advocate the proactive approach.
I try to write the code in that style which results in maintainable and reliable code
I use the defensive programming techniques to prevent stupid errors in code due to my loss of attention and similar
I design the database model according to the fortress principle, SQL code checking for results after each singular operation
I think of potential problems that can happen with that part of the code and I account for that. Not for every possibility but for major ones I can think of right now.
This usually results in software operating rather smoothly. At times it even surprises me but that was the intended goal, so here we are.
IMHO, the word "Error" (or its loose synonym "bug") itself means that it is a program behavior that was not foreseen.
I usually try to design with all possible scenarios in mind. Of course, it is usually not possible to think of all possible cases. But thinking through and allowing for as many scenarios as possible is usually better than just getting something working as soon as possible. This saves a lot of time and effort debugging and redesigning the code. I often sit down with pen and paper for even the smallest of programing tasks before actually typing any code into my editor.
As I said, this will not eliminate all errors. For me it pays off many times over in terms of time spent debugging. Another benefit is that it results in a more solid and maintainable design with fewer bugfixing hacks and special cases added on later. But in any case, you will have to do a lot of debugging after the code is done.
This does not apply when all you want is a mockup or rapid prototype. Also practical constraints such as deadlines often makes a thorough evaluation difficult or impossible.
What kind of programming? It's impossible to answer this in any general way. (It's like asking "do you wear a helmet when playing?" -- well, playing what?)
At work, I'm working on a database-backed website. The requirements are strict, and if I don't anticipate how users will screw it up, I'm going to get a call at some odd hour of the day to fix it.
At home, I'm working on a program ... I don't even know what it'll do yet. I can't deal with 'errors' because I don't know what 'an error' is in this context, because I don't know what correct behavior is going to be. The entire purpose of the program can and frequently does change on a timescale of minutes to hours, so even a couple minutes spent thinking about errors this early is a complete waste of time. (It's even worse than browsing SO, since error-handling adds lines of code.)
I guess the only general answer is "I do what makes sense in terms of saving time in the long term", which is, after all, the whole reason to use machines to do work for us.

Compromising design & code quality to integrate with existing modules

Greetings!
I inherited a C#.NET application I have been extending and improving for a while now. Overall it was obviously a rush-job (or whoever wrote it was seemingly less competent than myself). The app pulls some data from an embedded device & displays and manipulates it. At the core is a communications thread in the main application form which executes a 600+ lines of code method which calls functions all over the place, implementing a state machine - lots of if-state-then-do type code. Interaction with the device is done by setting the state/mode globally and letting the thread do it's thing. (This is just one example of the badness of the code - overall it is not very OO-like, it reminds of the style of embedded C code the device firmware is written in).
My problem is that this piece of code is central to the application. The software, communications protocol or device firmware are not documented at all. Obviously to carry on with my work I have to interact with this code.
What I would like some guidance on, is whether it is worth scrapping this code & trying to piece together something more reasonable from the information I can reverse engineer? I can't decide! The reason I don't want to refactor is because the code already works, and changing it will surely be a long, laborious and unpleasant task. On the flip side, not refactoring means I have to sometimes compromise the design of other modules so that I may call my code from this state machine!
I've heard of "If it ain't broke don't fix it!", so I am wondering if it should apply when "it" is influencing the design of future code! Any advice would be appreciated!
Thanks!
Also, the longer you wait, the worse the codebase will smell. My suggestion would be first create a testsuite that you can evaluate your refactoring against. This makes it a lot easier to see if you are refactoring or just plain breaking things :).
I would definitely recommend you to refactor the code if you feel its junky. Yes, during the process of refactoring you may have some inconsistencies/problems at the start. But that is why we have iterations and testing. Since you are going to build up on this core engine in future, why not make the basement as stable as possible.
However, be very sure on what you are going to do. Because at times long lines of code does not necessarily mean evil. On the other hand they may be very efficient in running time. If/else blocks are not bad if you ask me, as they are very intelligent in branching from a microprocessor's perspective. So, you will have to be judgmental and very clear before you touch this.
But once you refactor the code, you will definitely have fine control over it. And don't forget to document it!! Tomorrow, someone might very well come and say about you on whatever you've told about this guy who have written that core code.
This depends on the constraints you are facing, it's a decision to be based on practical basis, not on theoretical ones. You need three things to consider.
Time: you need to have enough time to learn it, implement it, and test it, without too many other tasks interrupting you
Boss #1: if you are working for someone, he needs to know and approve the time and effort you will spend immediately, required to rebuild your solution
Boss #2: your boss also needs to know that the advantage of having new and clean software will come at the price of possible regressions, and therefore at the beginning of the deployment there may be unexpected bugs
If you have those three, then go ahead and refactor it. It will be surely be worth it!
First and foremost, get all the business logic out of the Form. Second, locate all the parts where the code interacts with the global state (e.g. accessing the embedded system). Delegate all this access to methods. Then, move these methods into a new class and create an instance in the class's constructor. Finally, inject an instance for the class to use.
Following these steps, you can move your embedded system logic ("existing module") to a wrapper class you write, so the interface can be nice and clean and more manageable. Then you can better tackle refactoring the monster method because there is less global state to worry about (only local state).
If the code works and you can integrate your part with minimal changes to it then let the code as it is and do your integration.
If the code is simply a big barrier in your way to add new functionality then it is best for you to refactor it.
Talk with other people that are responsible for the project, explain the situation, give an estimation explaining the benefits gained after refactoring the code and I'm sure (I hope) that the best choice will be made. It is best to speak about what you think, don't keep anything inside, especially if this affects your productivity, motivation etc.
NOTE: Usually rewriting code is out of the question but depending on situation and amount of code needed to be rewritten the decision may vary.
You say that this is having an impact on the future design of the system. In this case I would say it is broken and does need fixing.
But you do have to take into account the business requirements. Often reality gets in the way!
Would it be possible to wrap this code up in another class whose interface better suits how you want to take the system forward? (See adapter pattern)
This would allow you to move forward with your requirements without the poor design having an impact.
It gives you an interface that you understand which you could write some unit tests for. These tests can be based on what your design requires from this code. It ensures that your assumptions about what it is doing is correct. If you say that this code works, then any failing tests may be that your assumptions are incorrect.
Once you have these tests you can safely refactor - one step at a time, and when you have some spare time or when it is needed - as per business requirements.
Quite often I find the best way to truly understand a piece of code is to refactor it.
EDIT
On reflection, as this is one big method with multiple calls to the outside world, you are going to need some kind of inverse Adapter class to wrap this method. If you can inject dependencies into the method (see Dependency Inversion such that the method calls methods in your classes then you can route these to the original calls.

What should a tester report?

I have a web site I am building for a client. I now have a tester on the project with me.
I feel testers are needed. REALLY! I cannot test my own code. I also appreciate the value of a new set of eyes. But what desires reporting?
It is easy to say everything should be reported, but I don't have someone between me and the tester to filter out the unimportant requests. The tester does not know the system nor the target user well. She is assigning me tasks and not the project manager. I think this will change soon, but until it does, what do you recommend? There seems to be a believe that our users have NEVER used the interent before at all, and they are as dumb as rocks.
The problem I am having is that EVERYTHING the tester suggests is being accepted automattically and assigned to me.
I have many cases that make me drop my jaw and say "Really? Are you serious? This deserves to be a issue?"
Ex: Need to add text at top of page that says "* = Required" for required fields.
Have you ever felt this way? How did you deal with it?
For now, I am just doing as I am told, but I am making it clear I do not agree.
It sounds to me like your tester is doing the right thing. You can't assume any level of user expertise when testing an application. If a user can break something, they will.
You and your tester need to work out a severity scale. The outliers (those that anybody with Internet experience could probably work around/would never hit) would be considered low priority and sit on the back burner until you knock out the high priority items.
...never the less, those outliers should still be logged because they can definitely come back to bite you in the ass in the end.
You need to add priorities for your issues. This will allow you to do the important issues first, and cosmetic issues last. Here is example priorities from Jira:
Priority 1 - a reproducible crash; issue blocking any further testing or development of a specific feature; loss of user's persistent data; huge memory leak
Priority 2 - a major issue that must be fixed before the product is released; prevents users from using a feature; negatively affects partner; significant memory leak in frequently used functionality
Priority 3 - a minor issue that should be fixed before a product is released; does not prevent users from using a product; highly visible usability issue; small memory leak in rarely used functionality
Priority 4 - a purely cosmetic issue; doesn't affect functionality
Actually it sounds like your tester is doing the right thing (and the text for "* = required" is a very good idea).
In addition to the suggestions about prioritizing reports, I would suggest that you categorize the reports as to whether they refer to user experience or functionality.
You and the tester will never exactly agree on what "needs" to be reported. Just set the priority on issues correctly, and get on with fixing the high-priority stuff first.
One thing you absolutely do not want to do is to discourage the tester from filing bugs. That'll come back to bite you when something ships totally broken, and they say "I thought that was just how it worked".
Do make sure that you're communicating the development schedule and status properly, so they don't waste time testing features that aren't sufficiently complete.
I would report to the client what each change will cost in terms of time and money. Things that are legitimate bugs you'll probably need to fix on your own time (unless your contract says otherwise). Things that are design / subjective issues you should be able to assign a cost to. Let the client know what it is going to cost them and they can decide if they want to proceed or not.
Hopefully you've got some sort of a project specification that the client has signed off on so that you know when the project is complete and what sort of things are not included in the project scope. If not, you might have a bit of a fight on your hands. For changes that you think are outside of the project scope, you might need to compromise - maybe bill them at a cheaper rate or split the cost with them. If you're in that situation it's a good learning experience to get everything documented in the project specification so that there is no question about what falls outside of the project scope. I've been there - one experience like this is enough to teach you to put more work into your specifications.
Report everything and triage. After a bit of time, she'll start to understand what gets past triage and what doesn't. Humans can learn; teach.

Can I control register allocation in g++?

I have highly optimized piece of C++ and making even small changes in places far from hot spots can hit performance as much as 20%. After deeper investigation it turned out to be (probably) slightly different registers used in hot spots.
I can control inlineing with always_inline attribute, but can I control register allocation?
If you really want to mess with the register alloation then you can force GCC to allocate local and global variables in certain registers.
You do this with a special variable declaration like this:
register int test_integer asm ("EBX");
Works for other architectures as well, just replace EBX with a target specific register name.
For more info on this I suggest you take a look at the gcc documentation:
http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Local-Reg-Vars.html
My suggestion however is not to mess with the register allocation unless you have very good reasons for it. If you allocate some registers yourself the allocator has less registers to work with and you may end up with a code that is worse than the code you started with.
If your function is that performance critical that you get 20% performance differences between compiles it may be a good idea to write that thing in inline-assembler.
EDIT: As strager pointed out the compiler is not forced to use the register for the variable. It's only forced to use the register if the variable is used at all. E.g. if the variable it does not survive an optimization pass it won't be used. Also the register can be used for other variables as well.
In general the register keyword is simply ignored by all modern compilers. The only exception is the (relatively) recent addition of an error if you attempt to take the address of a variable you've marked with the register keyword.
I've experienced this sort of pain as well, and eventually found the only real way around it was to look at output assembly to try and determine what is causing gcc to go off the deepend. There are other things you can do but it depends on exactly what your code is trying to do. I was working in a very very large function with a large amount of computed goto mayhem in which minor (seemingly innocuous) changes could cause catastrophic performance hits. If you're doing similar there are a few things you can do to try and mitigate the problem, but the details are somewhat icky so i'll forgo discussing them here unless it's actually relevant.
It depends on the processor you are using. Or should I say, yes you can with the register keyword, but this is frowned upon unless you are using a simple processor with no pipe-lining and a single core. These days GCC can do a way better job than you can with register allocation. Trust it.