5 Eylül 2017 Salı

DO-178B Structural Coverage Analysis

Requirements Based Testing Nedir
Açıklaması şöyle
Structural coverage analysis is an important verification tool
for establishing the completeness of testing.
 
DO-178C emphasizes the use of requirements-based testing as an important part of the software verification process.
 
In requirements-based testing, the high and low-level requirements are used to derive source code and the tests for that source code.
 
Traceability between the requirements, the test cases and the source code demonstrates:
 
• Every requirement has a test case
• All source code is traceable to a requirement
 
Measuring code coverage when the test cases are executed is essential for this process – where coverage is less than 100%, this points to code that is not traceable to requirements, tests or both.

Yazılım Kapsama Analizi yani Structural Coverage Analysis (SCA)
Bu faaliyet önemli bir efor gerektirdiği için kendi başlığı altında yazmak istedim.

Code Coverage Başka Süreçlerde de Var mı ?
Code Coverage sistematik test faaliyetinin temel öğelerinden birisi. Bir çok yazılım geliştirme sürecinde bu faaliyeti tanımlayan yazılar görülebilir. Her süreçte kapsama analizinde kullanılacak temel kriterler tanımlanıyor. En basiti genellikle testler yazılımın %80'ini çalıştırmalı şeklinde olanlar. Bu tür süreçlerde %80 rakamının aşılması yeterlidir. Function Coverage, Statement Coverage, Decision Coverage vs. detaylara bakılmaz.

SCA Nedir?
SCA hava aracına yüklenecek kod için yapılan bir kapsama analizi. Uçağa yüklenmeyecek özelliklerin etkin olduğu, debug modda derlenmiş koda SCA yapmak anlamsızdır!

Aşağıda seviyeye göre yapılması gereken SCA faaliyetini de görebilirsiniz.

Level A : Modified Condition/Decision Coverage (MCDC) , Decision Coverage & Statement Coverage.
Level B : Decision Coverage & Statement Coverage : Koşulun her çıkışı bir kere çalışmalı. Sadece if koşulu varsa ve else koşulu yoksa bile else olmasını sağlayacak şekilde de test edilmeli.
Level C : Statement Coverage : Her statement en az bir kere çalışmalı. Statement satır şeklinde düşünülmeli. Yani if/else koşulu için hem if hem de else satırları test edilmeli.
Level D : None Required
Level E : None Required 
Şeklen şöyle



Not : Emniyet kritik yazılımlarda kullanılan DO-178 A/B/C seviyesindeki süreçte gerçekleştirilen Structural Coverage Analysis (Yazılım Kapsama Analizi) ile ilgili yapılan bir çalışmayı EMO'nun sitesinde bulabilirsiniz.

SCA Nerede Yapılır?
Açıklaması şöyle. Yani istenirse target ortamda, istenirse de host ortamda yapılabilir.
Should you collect your coverage on-target or on-host?

On-target testing means the application is tested on the hardware to be deployed (the target).

On-host testing means testing the application on a host computer (such as the development system used to build the application).

On-target testing

The key principle behind testing an application on-target is that code is executed in the environment for which it was designed.

Test results are typically evaluated and analysed on a host. This has the following benefits:

• The “credibility gap”, the possibility that some unanticipated difference exists between executing on-host in a harness and executing on-target, is minimized.
This results in a lower likelihood of false-negative errors leading to errors not being detected, and faulty software being deployed, and of false-positive reports where time is wasted tracking down non-existent problems.
• The smaller “credibility gap” also makes it easier to provide an argument to certification authorities that testing achieves an appropriate level of rigor.
• Ability to execute all code. Some parts of your code might not be possible to run on host (for example, device specific code).

On-host testing

On-host testing involves compiling the application code to run on the host processor.

Typically, the application also requires a certain amount of adaptation to work in the host environment due to the following considerations:

• Running under a desktop OS rather than the target’s RTOS may require different API calls.
• If the embedded application includes libraries, these may not be available on the host (or may be different e.g. graphics libraries).
• Alternative interpretations of ambiguous/undefined programming language features or compiler bugs may cause different behaviors between the host and the target.
• The embedded application may require access to specific hardware features that are not available on the host system.

However, there are benefits that can arise from on-host testing:

• The target may not be available, or there may be only limited access to it when testing needs to take place.
• The “build-deploy-analyze” cycle may be quicker than on-target testing.
• It is well suited to unit testing – a test harness can be used to achieve 100% coverage, even when defensive programming techniques are used.

What to choose?

The choice is driven by a trade-off between cost/convenience and credibility of results.

A combination can offer dual benefits:

• Unit testing and test case development on-host gives the advantages of rapid turnaround;
• System/integration testing on-target provides the confidence that the code to be deployed has been tested in its intended environment.

Manual Analysis Nedir?
Açıklaması şöyle. Yani test edilemeyen kodlar için yapılır
4 ways to deal with less than 100% coverage in your DO-178C project…

If structural code analysis demonstrates less than 100% coverage, there are four main responses you can make, depending on the reason why coverage is incomplete:

1) Remove code. Review shows that this code is unnecessary to the system, and you can remove it with no negative effects.
2) Add (or fix) tests. Where tests (and possibly requirements) are incomplete, you need to develop new tests, which will improve the overall coverage level.
3) Justify why code will never be executed. For deactivated code, you need to provide some form of justification why this code cannot be executed.
4) Justify why it is not possible to test code. Through manual testing/review you should demonstrate that the code works correctly.
For example, for defensive programming structures, this could involve setting a breakpoint just before the test for the defensive code, then manually forcing the test to fail, and executing the defensive code.

When code is justified, it is important to demonstrate that it has not been executed during testing.
For example, deactivated code should never be executed, nor should code that is only accessible when the system is in a different mode.
If we have said “this code will never be executed because XYZ” and the code is then executed, that represents an error in our justifications.
 
When presenting your code coverage results, you should aim to present:

1) The parts of the code you have executed through testing.
2) The parts of the code you have not executed, but have provided some form of justification for.
3) The detailed justification for each piece of code that was not executed.
Açıklaması şöyle
If your DO-178C project is DAL C or above, you will need to provide evidence that your requirements-based testing and analysis has covered or justified [by manual analysis] 100% of your code.

Most code should be coverable by requirements-based tests, but often some code cannot be, or cannot easily be, covered by such tests.

Some causes of untestable, or not easily testable code, include:

• Coding standard – your coding standard may require the use of untestable coding structures such as default case statements that can never be executed, or destructors.

• Programming language – your choice of programming language may lead to the generation of code structures that cannot be executed, such as default base class implementations in object-oriented programming languages.

• Defensive programming – some code may only be executable in fault conditions that cannot be tested. Typically, you will need to provide a rationale for this defensive code in your Software Coding Standards.

• Unused library code – a general-purpose library may include routines that are never called during your tests.

• Initialization code and shutdowns – some code executes before you can set up the testing environment, making it difficult to test directly. Other tests may need to invoke resets of the target hardware during the test (e.g. to check that non-volatile memory is used correctly on a warm restart first pass), making it hard to record test successes and associated structural coverage.
Justification şeklen şöyle


Statement Coverage Nedir? - Level C
"Every statement in the program has been invoked at least once."
ANSI C dilinde statement şöyle gösteriliyor.
statement
    : labeled_statement
    | compound_statement
    | expression_statement
    | selection_statement
    | iteration_statement
    | jump_statement
    ;

expression_statement
    : ';'
    | expression ';'
    ;
Yani bir sürü çeşidi var. Biz temel olarak iki çeşit statement ile ilgileniyoruz. İlki simple statement (basit), diğer ise compound statement (bileşik) olarak adlandırılır. Simple statement şöyle tarif edilir.
A statement can consist of a single line of code that ends in a semicolon...
Yani C/C++ dilinde noktalı virgül satırı bitiren değil, simple statement'ı bitiren karakterdir.

Compound Statement ise şöyle tarif edilir.
A compound statement consists of zero or more statements enclosed in curly braces ({ }). A compound statement can be used anywhere a statement is expected. Compound statements are commonly called "blocks."
Yani C/C++ dilinde süslü parantezi compound statement'ı bitiren karakterdir.

Dolayısıyla Statement Coverage denilince  compound statement yani if/switch statement, while statement, do-while statement, for loop statement gibi cümleler de dahildir.

Boolean Logic
If statement için satırın çalışmasını sağlayan bir çok test yazılabilir. Önemli olan satırların bir kere test edilmesidir. Satırın Cyclomatic Complexity değeri kaç test yazılması gerektiğini bildirir.

Örnek
Örnek metodu x = 2, y = 0, ve z = 4 değerleri ile çağırırsak tüm satırları çalıştırırız.
if (x > 1) || (y = 0)
  z = z / x;
if (z > 2) || (y > 1)
  z = z + 1;

Ancak bu kapsama yöntemi tüm boolean logic hatalarını yakalamak için yetersiz kalabilir. Eğer yukarıdaki kodun aslında if (x > 1) && (y = 0) olması gerekseydi, hatayı yakalayamazdık.

Statement Coverage Kusurları
Statement Coverage bazı hataları ortaya çıkarmayabilir.

Basit If 
int* p = NULL;
if (condition) {
    p = &variable;
    *p = 1;
}
*p = 0; // Oops, possible null pointer dereference
Döngünün Sonlanması
char output[100];
for (int i = 0; i <= sizeof(output); i++) { // Oops, buffer overrun; comparison should be <
    output[i] = input[i];
    if (input[i] == '\0') {
        break;
    }
}
Overflow
Örnek
def Add(x as Int32, y as Int32) as Int32:
   return x + y

Test.Assert(Add(2, 2) == 4) //100% test coverage
Add(MAXINT, 5) //Throws an exception, despite 100% test coverage

Decision Coverage Nedir? - Level B
"Every decision in the program has take all possible outcomes at least once"
Özellikle and, or gibi Boolean logic kullanan if ifadelerinin testi için çok önemli bir faaliyet.

Level B için örnek vermek gerekirse
if (A== 0 and B < 2) {
//True
}
else {
//False
}
kod parçası için True ve False koşullarını sağlayan iki test yeterli. A ve B'nin alabileceği kombinasyonlara bakılmaz. İlk koşul için (TT) değerleri ile test etmek yeterli. Else koşulu için (TF), (FT), (FF) girdilerinden birisi kullanılabilir. Eğer FT veya FF seçilirse B'nin etkisi test edilmemiş olur.

Condition Coverage Nedir?
DO-178B tarafından istenmez. Her koşulu bir true bir de false olmasını test eder. MC/DC'yi anlamak için yazıya dahil ettim.

MC/DC Coverage Nedir? - Level A
MC/DC Coverage Nedir yazısına taşıdım.

Kapsama Analizi Sonucunda Ne Yapılır?
Yazılım Kapsama Analizi basitçe isterlere bakarak test geliştirmek ve kaynak kodu bu testlerle koşturarak çalışan/çalışmayan kod parçalarını tasnif etmek olarak düşünülebilir. Yükü çokça olan, fakat süreç tarafından yerine getirilmesi mecbur kılınan bir iş.

Analiz sonucunda, test tarafından kapsanamayan kod parçaları için alınan kararların bazıları şöyle olabilir. (Allowed Resolution Types)

1. Testin İyileştirilmesi
Test kodu çalıştırmak için yeterli değildir, iyileştirilmesi gerekir.

2. Gereksinimin İyileştirilmesi
Gereksinim yeterli değildir. Gereksinime bakılarak yazılan test, koda göre yüzeysel kalmaktadır. Gereksinimin iyileştirilmesi gerekir.

3. Ölü Kod Vardır
Dead Code'un açıklaması şöyle
RTCA DO-178C - the standard for safety critical code in aircraft - uses the terms "dead code" for code that is never reached in any path through the code.
Yani kod hiçbir zaman çalışmayacaktır. Silinmesi gerekir. Aslında Dead Code sadece unreachable cod değildir. Etkisiz kod da dead kod sayılabilir. Aşağıda bir örnek var. Ancak unreachable code nedense tanıma dahil edilmemiş.
x = 5;
/* Dead Code Begin */
x = 6;
x = 5;
/* Dead Code End */

Literatürde dead code
1. unconditional dead code ve
2. conditional dead kod olarak ikiye ayrılır.

1. Unconditional Dead Code
Unconditional dead code derleyiciler tarafından tespit edilebilir. Elimizde şöyle bir kod olsun. Bu bool bir değişken için ya A ya da B dalı çalışır. C dalı hiçbir zaman çalışmayacaktır. Bu derleyici tarafından tespit edilir ve uyarı verilir.
bool boolVal = /*anything boolean*/;

if (boolVal)
{
  // Do A
}
else if (!boolVal)
{
  // Do B
}
else
{
  // Do C
}
Şu tür dead code da derleyiciler tarafından tespit edilebilir. Return'den sonraki satır çalışmayacaktır.
public class DeadCode {
  public static void main(String[] args) {
     return;
     System.out.println("This line won't print.");
  }
}
2. Conditional dead code
Conditional dead code ise tespit edilemez. Bu problem "Halting Problem" ile alakalıdır.
Şöyle bir kodda M'nin ne zaman biteceğini bilmek imkansızdır çünkü x'e bağımlıdır. Dolayısıyla print'in çalışıp çalışmayacağından emin olamayız.
Run M on input x;
print "Finished running input";
DO-178 tarafından kast edilen dead code bu iki tanıma da girmez. Burada kast edilen gereksinim karşılığı bulunmayan koddur. Örneğin şöyle bir kod olsun. Eğer gereksinim porttan okunan değerin 2'den küçük olacağını söylerse else kısmı hiçbir zaman çalışmayacaktır. Bu durumda if koşulu da gereksizdir ve silinmesi gerekir.
int readValueFromPort(const unsigned int portNum);

int x = readValueFromPort(0x100); // just an example, nothing meaningful
if (x < 2)
{
    std::cout << "Hey! X < 2" << std::endl;
}
else
{
    std::cout << "X is too big!" << std::endl;
}

4. Etkisizleştirilmiş Kod Vardır
Açıklaması şöyle
The term "deactivated code" is for code that is deliberately never used in a particular configuration, but could be used in a different mode.
Etkisizleştirilmiş kod (deactivated/defensive code), geçerli konfigürasyon için çalışmayacaktır. Varlığı bir hata değildir.

Aslında defensive code deactivated code'dan bence farklı bir amaca hizmet ediyor. Ancak yine de aynı kapsamda değerlendirdim. Defensive code, beklenmeyen bir durum olursa örneğin bir pointer null gelirse veya bir değişken zaten belli aralıkta olması gerekirken tekrar kontrol edilirse gibi durumlarda için geçerli.

Nesneye yönelik yazılımlarda multi-mode uygulamalar için en çok kullanılan yöntem Strategy örüntüsü. Ancak DO-178B nesneye yönelik yazılımlara da çok mesafeli durduğu için bu yöntemi seçmek doğrudur da diyemiyorum.

SCA Ne Zaman Biter?
Unutulmaması gereken en önemli nokta SCA DO-178B emniyet seviyesinin belirttiği kapsama analizi %100 yerine getirildiği zaman biter!

SCA'da bir kısmı kod test edilemediği için "Göz ile Analiz" ile yapılabilir. Ancak analiz yapılan kod yüzdesinin çok küçük olması gerekir. Örneğin tüm kodun %1'i bile olmamalıdır.

SCA İçin Kullanılabilen Yazılımlar
VectorCast iyi bir seçim. Kullanılacak araçlar ilgili bir açıklama şöyle
How do you use code coverage results to support DO-178C certification?

Let’s take a look.

If evidence of code coverage is mandatory for the project, for example because your end customer requires strict adherence to DO-178C guidance, it’s important to be able to provide evidence that the process used to collect the data has worked correctly.

What to look for in a code coverage tool:

1) Can it adapt to different embedded environments?
2) Can it cope with low memory environments?
3) Will it support partial instrumentation and provide the ability to combine results?

The evidence must show that the tool works correctly within the context of the development environment for which it is producing results.
In the case of DO-178C/DO-330, the following items are recommended for tool qualification:

• PSAC (Plan for Software Aspects of Certification). This references the TQP and TAS (see below).
• TOR (Tool Operational Requirements). This describes what the tool does, how it is used and the environment in which it performs.
• TAS (Tool Accomplishment Summary). This is a summary of the data showing that all requirements in the TOR have been verified.
• TVR (Tool Verification Records). This comprises test cases, procedures and results.
• TQP (Tool Qualification Plan). This describes the process for qualifying the tool.

These items combine two main kinds of evidence:

1) Generic evidence. This needs to be provided by the tool vendor to define the tool operational requirements, and verification evidence to demonstrate that the tool meets the requirements.
2) Specific evidence. The tool user needs to demonstrate that the tool works correctly in a specific environment.

Ideally the tool vendor should provide support to simplify this process as much as possible.
Araç çıktısına bir örnek şöyle



Hiç yorum yok:

Yorum Gönder