Методы и способы идентификации сбоев и ошибок реферат

Предложите, как улучшить StudyLib

(Для жалоб на нарушения авторских прав, используйте

другую форму
)

Ваш е-мэйл

Заполните, если хотите получить ответ

Оцените наш проект

1

2

3

4

5

Обработка исключительных ситуаций. Методы и способы идентификации сбоев и ошибок.

Конструкция try..catch..finally

Иногда при выполнении программы возникают ошибки, которые трудно предусмотреть или предвидеть, а иногда и вовсе невозможно. Например, при передачи файла по сети может неожиданно оборваться сетевое подключение. такие ситуации называются исключениями. Язык C# предоставляет разработчикам возможности для обработки таких ситуаций. Для этого в C# предназначена конструкция try…catch…finally.

try
{
     
}
catch
{
     
}
finally
{
     
}

При использовании блока try…catch..finally вначале пытаются выполниться инструкции в блоке try. Если в этом блоке не возникло исключений, то после его выполнения начинает выполняться блок finally. И затем конструкция try..catch..finally завершает свою работу.

Если же в блоке try вдруг возникает исключение, то обычный порядок выполнения останавливается, и среда CLR (Common Language Runtime) начинает искать блок catch, который может обработать данное исключение. Если нужный блок catch найден, то он выполняется, и после его завершения выполняется блок finally.

Если нужный блок catch не найден, то при возникновении исключения программа аварийно завершает свое выполнение.

Рассмотрим следующий пример:

class Program
{
    static void Main(string[] args)
    {
        int x = 5;
        int y = x / 0;
        Console.WriteLine($"Результат: {y}");
        Console.WriteLine("Конец программы");
        Console.Read();
    }
}

В данном случае происходит деление числа на 0, что приведет к генерации исключения. И при запуске приложения в режиме отладки мы увидим в Visual Studio окошко, которое информирует об исключении:

В этом окошке мы видим, что возникло исключение, которое представляет тип System.DivideByZeroException, то есть попытка деления на ноль. С помощью пункта View Details можно посмотреть более детальную информацию об исключении.

И в этом случае единственное, что нам остается, это завершить выполнение программы.

Чтобы избежать подобного аварийного завершения программы, следует использовать для обработки исключений конструкцию try…catch…finally. Так, перепишем пример следующим образом:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            int x = 5;
            int y = x / 0;
            Console.WriteLine($"Результат: {y}");
        }
        catch
        {
            Console.WriteLine("Возникло исключение!");
        }
        finally
        {
            Console.WriteLine("Блок finally");
        }
        Console.WriteLine("Конец программы");
        Console.Read();
    }
}

В данном случае у нас опять же возникнет исключение в блоке try, так как мы пытаемся разделить на ноль. И дойдя до строки

выполнение программы остановится. CLR найдет блок catch и передаст управление этому блоку.

После блока catch будет выполняться блок finally.

Возникло исключение!
Блок finally
Конец программы

Таким образом, программа по-прежнему не будет выполнять деление на ноль и соответственно не будет выводить результат этого деления, но теперь она не будет аварийно завершаться, а исключение будет обрабатываться в блоке catch.

Следует отметить, что в этой конструкции обязателен блок try. При наличии блока catch мы можем опустить блок finally:

try
{
    int x = 5;
    int y = x / 0;
    Console.WriteLine($"Результат: {y}");
}
catch
{
    Console.WriteLine("Возникло исключение!");
}

И, наоборот, при наличии блока finally мы можем опустить блок catch и не обрабатывать исключение:

try
{
    int x = 5;
    int y = x / 0;
    Console.WriteLine($"Результат: {y}");
}
finally
{
    Console.WriteLine("Блок finally");
}

Однако, хотя с точки зрения синтаксиса C# такая конструкция вполне корректна, тем не менее, поскольку CLR не сможет найти нужный блок catch, то исключение не будет обработано, и программа аварийно завершится.

Обработка исключений и условные конструкции

Ряд исключительных ситуаций может быть предвиден разработчиком. Например, пусть программа предусматривает ввод числа и вывод его квадрата:

static void Main(string[] args)
{
    Console.WriteLine("Введите число");
    int x = Int32.Parse(Console.ReadLine());
 
    x *= x;
    Console.WriteLine("Квадрат числа: " + x);
    Console.Read();
}

Если пользователь введет не число, а строку, какие-то другие символы, то программа выпадет в ошибку. С одной стороны, здесь как раз та ситуация, когда можно применить блок try..catch, чтобы обработать возможную ошибку. Однако гораздо оптимальнее было бы проверить допустимость преобразования:

static void Main(string[] args)
{
    Console.WriteLine("Введите число");
    int x;
    string input = Console.ReadLine();
    if (Int32.TryParse(input, out x))
    {
        x *= x;
        Console.WriteLine("Квадрат числа: " + x);
    }
    else
    {
        Console.WriteLine("Некорректный ввод");
    }
    Console.Read();
}

Метод Int32.TryParse() возвращает true, если преобразование можно осуществить, и false — если нельзя. При допустимости преобразования переменная x будет содержать введенное число. Так, не используя try…catch можно обработать возможную исключительную ситуацию.

С точки зрения производительности использование блоков try..catch более накладно, чем применение условных конструкций. Поэтому по возможности вместо try..catch лучше использовать условные конструкции на проверку исключительных ситуаций.

Блок catch и фильтры исключений

Определение блока catch

За обработку исключения отвечает блок catch, который может иметь следующие формы:

  • Обрабатывает любое исключение, которое возникло в блоке try. Выше уже был продемонстрирован пример подобного блока.

    catch
    {
        // выполняемые инструкции
    }
  • Обрабатывает только те исключения, которые соответствуют типу, указаному в скобках после оператора catch.

    catch (тип_исключения)
    {
        // выполняемые инструкции
    }

    Например, обработаем только исключения типа DivideByZeroException:

    try
    {
        int x = 5;
        int y = x / 0;
        Console.WriteLine($"Результат: {y}");
    }
    catch(DivideByZeroException)
    {
        Console.WriteLine("Возникло исключение DivideByZeroException");
    }

    Однако если в блоке try возникнут исключения каких-то других типов, отличных от DivideByZeroException, то они не будут обработаны.

  • Обрабатывает только те исключения, которые соответствуют типу, указаному в скобках после оператора catch. А вся информация об исключении помещается в переменную данного типа.

    catch (тип_исключения имя_переменной)
    {
        // выполняемые инструкции
    }

    Например:

    try
    {
        int x = 5;
        int y = x / 0;
        Console.WriteLine($"Результат: {y}");
    }
    catch(DivideByZeroException ex)
    {
        Console.WriteLine($"Возникло исключение {ex.Message}");
    }

    Фактически этот случай аналогичен предыдущему за тем исключением, что здесь используется переменная. В данном случае в переменную ex, которая представляет тип DivideByZeroException, помещается информация о возникшем исключени. И с помощью свойства Message мы можем получить сообщение об ошибке.

    Если нам не нужна информация об исключении, то переменную можно не использовать как в предыдущем случае.

Фильтры исключений

Фильтры исключений позволяют обрабатывать исключения в зависимости от определенных условий. Для их применения после выражения catch идет выражение when, после которого в скобках указывается условие:

В этом случае обработка исключения в блоке catch производится только в том случае, если условие в выражении when истинно. Например:

int x = 1;
int y = 0;
 
try
{
    int result = x / y;
}
catch(DivideByZeroException) when (y==0 && x == 0)
{
    Console.WriteLine("y не должен быть равен 0");
}
catch(DivideByZeroException ex)
{
    Console.WriteLine(ex.Message);
}

В данном случае будет выброшено исключение, так как y=0. Здесь два блока catch, и оба они обрабатывают исключения типа DivideByZeroException, то есть по сути все исключения, генерируемые при делении на ноль. Но поскольку для первого блока указано условие y == 0 && x == 0, то оно не будет обрабатывать исключение — условие, указанное после оператора when возвращает false. Поэтому CLR будет дальше искать соответствующие блоки catch далее и для обработки исключения выберет второй блок catch. В итоге если мы уберем второй блок catch, то исключение вобще не будет обрабатываться.

Типы исключений. Класс Exception

Базовым для всех типов исключений является тип Exception. Этот тип определяет ряд свойств, с помощью которых можно получить информацию об исключении.

  • InnerException: хранит информацию об исключении, которое послужило причиной текущего исключения

  • Message: хранит сообщение об исключении, текст ошибки

  • Source: хранит имя объекта или сборки, которое вызвало исключение

  • StackTrace: возвращает строковое представление стека вызывов, которые привели к возникновению исключения

  • TargetSite: возвращает метод, в котором и было вызвано исключение

Например, обработаем исключения типа Exception:

static void Main(string[] args)
{
    try
    {
        int x = 5;
        int y = x / 0;
        Console.WriteLine($"Результат: {y}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Исключение: {ex.Message}");
        Console.WriteLine($"Метод: {ex.TargetSite}");
        Console.WriteLine($"Трассировка стека: {ex.StackTrace}");
    }
 
    Console.Read();
}

Однако так как тип Exception является базовым типом для всех исключений, то выражение catch (Exception ex) будет обрабатывать все исключения, которые могут возникнуть.

Но также есть более специализированные типы исключений, которые предназначены для обработки каких-то определенных видов исключений. Их довольно много, я приведу лишь некоторые:

  • DivideByZeroException: представляет исключение, которое генерируется при делении на ноль

  • ArgumentOutOfRangeException: генерируется, если значение аргумента находится вне диапазона допустимых значений

  • ArgumentException: генерируется, если в метод для параметра передается некорректное значение

  • IndexOutOfRangeException: генерируется, если индекс элемента массива или коллекции находится вне диапазона допустимых значений

  • InvalidCastException: генерируется при попытке произвести недопустимые преобразования типов

  • NullReferenceException: генерируется при попытке обращения к объекту, который равен null (то есть по сути неопределен)

И при необходимости мы можем разграничить обработку различных типов исключений, включив дополнительные блоки catch:

static void Main(string[] args)
{
    try
    {
        int[] numbers = new int[4];
        numbers[7] = 9;     // IndexOutOfRangeException
 
        int x = 5;
        int y = x / 0;  // DivideByZeroException
        Console.WriteLine($"Результат: {y}");
    }
    catch (DivideByZeroException)
    {
        Console.WriteLine("Возникло исключение DivideByZeroException");
    }
    catch (IndexOutOfRangeException ex)
    {
        Console.WriteLine(ex.Message);
    }
             
    Console.Read();
}

В данном случае блоки catch обрабатывают исключения типов IndexOutOfRangeException, DivideByZeroException и Exception. Когда в блоке try возникнет исключение, то CLR будет искать нужный блок catch для обработки исключения. Так, в данном случае на строке

происходит обращение к 7-му элементу массива. Однако поскольку в массиве только 4 элемента, то мы получим исключение типа IndexOutOfRangeException. CLR найдет блок catch, который обрабатывает данное исключение, и передаст ему управление.

Следует отметить, что в данном случае в блоке try есть ситуация для генерации второго исключения — деление на ноль. Однако поскольку после генерации IndexOutOfRangeException управление переходит в соответствующий блок catch, то деление на ноль int y = x / 0 в принципе не будет выполняться, поэтому исключение типа DivideByZeroException никогда не будет сгенерировано.

Однако рассмотрим другую ситуацию:

static void Main(string[] args)
{
    try
    {
        object obj = "you";
        int num = (int)obj;     // InvalidCastException
        Console.WriteLine($"Результат: {num}");
    }
    catch (DivideByZeroException)
    {
        Console.WriteLine("Возникло исключение DivideByZeroException");
    }
    catch (IndexOutOfRangeException)
    {
        Console.WriteLine("Возникло исключение IndexOutOfRangeException");
    }
             
    Console.Read();
}

В данном случае в блоке try генерируется исключение типа InvalidCastException, однако соответствующего блока catch для обработки данного исключения нет. Поэтому программа аварийно завершит свое выполнение.

Мы также можем определить для InvalidCastException свой блок catch, однако суть в том, что теоретически в коде могут быть сгенерированы сами различные типы исключений. А определять для всех типов исключений блоки catch, если обработка исключений однотипна, не имеет смысла. И в этом случае мы можем определить блок catch для базового типа Exception:

static void Main(string[] args)
{
    try
    {
        object obj = "you";
        int num = (int)obj;     // InvalidCastException
        Console.WriteLine($"Результат: {num}");
    }
    catch (DivideByZeroException)
    {
        Console.WriteLine("Возникло исключение DivideByZeroException");
    }
    catch (IndexOutOfRangeException)
    {
        Console.WriteLine("Возникло исключение IndexOutOfRangeException");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Исключение: {ex.Message}");
    }  
    Console.Read();
}

И в данном случае блок catch (Exception ex){} будет обрабатывать все исключения кроме DivideByZeroException и IndexOutOfRangeException. При этом блоки catch для более общих, более базовых исключений следует помещать в конце — после блоков catch для более конкретный, специализированных типов. Так как CLR выбирает для обработки исключения первый блок catch, который соответствует типу сгенерированного исключения. Поэтому в данном случае сначала обрабатывается исключение DivideByZeroException и IndexOutOfRangeException, и только потом Exception (так как DivideByZeroException и IndexOutOfRangeException наследуется от класса Exception).

Создание классов исключений

Если нас не устраивают встроенные типы исключений, то мы можем создать свои типы. Базовым классом для всех исключений является класс Exception, соответственно для создания своих типов мы можем унаследовать данный класс.

Допустим, у нас в программе будет ограничение по возрасту:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Person p = new Person { Name = "Tom", Age = 17 };
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Ошибка: {ex.Message}");
        }
        Console.Read();
    }
}
class Person
{
    private int age;
    public string Name { get; set; }
    public int Age
    {
        get { return age; }
        set
        {
            if (value < 18)
            {
                throw new Exception("Лицам до 18 регистрация запрещена");
            }
            else
            {
                age = value;
            }
        }
    }
}

В классе Person при установке возраста происходит проверка, и если возраст меньше 18, то выбрасывается исключение. Класс Exception принимает в конструкторе в качестве параметра строку, которое затем передается в его свойство Message.

Но иногда удобнее использовать свои классы исключений. Например, в какой-то ситуации мы хотим обработать определенным образом только те исключения, которые относятся к классу Person. Для этих целей мы можем сделать специальный класс PersonException:

class PersonException : Exception
{
    public PersonException(string message)
        : base(message)
    { }
}

По сути класс кроме пустого конструктора ничего не имеет, и то в конструкторе мы просто обращаемся к конструктору базового класса Exception, передавая в него строку message. Но теперь мы можем изменить класс Person, чтобы он выбрасывал исключение именно этого типа и соответственно в основной программе обрабатывать это исключение:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Person p = new Person { Name = "Tom", Age = 17 };
        }
        catch (PersonException ex)
        {
            Console.WriteLine("Ошибка: " + ex.Message);
        }
        Console.Read();
    }
}
class Person
{
    private int age;
    public int Age
    {
        get { return age; }
        set
        {
            if (value < 18)
                throw new PersonException("Лицам до 18 регистрация запрещена");
            else
                age = value;
        }
    }
}

Однако необязательно наследовать свой класс исключений именно от типа Exception, можно взять какой-нибудь другой производный тип. Например, в данном случае мы можем взять тип ArgumentException, который представляет исключение, генерируемое в результате передачи аргументу метода некорректного значения:

class PersonException : ArgumentException
{
    public PersonException(string message)
        : base(message)
    { }
}

Каждый тип исключений может определять какие-то свои свойства. Например, в данном случае мы можем определить в классе свойство для хранения устанавливаемого значения:

class PersonException : ArgumentException
{
    public int Value { get;}
    public PersonException(string message, int val)
        : base(message)
    {
        Value = val;
    }
}

В конструкторе класса мы устанавливаем это свойство и при обработке исключения мы его можем получить:

class Person
{
    public string Name { get; set; }
    private int age;
    public int Age
    {
        get { return age; }
        set
        {
            if (value < 18)
                throw new PersonException("Лицам до 18 регистрация запрещена", value);
            else
                age = value;
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        try
        {
            Person p = new Person { Name = "Tom", Age = 13 };
        }
        catch (PersonException ex)
        {
            Console.WriteLine($"Ошибка: {ex.Message}");
            Console.WriteLine($"Некорректное значение: {ex.Value}");
        }
        Console.Read();
    }
}

Поиск блока catch при обработке исключений

Если код, который вызывает исключение, не размещен в блоке try или помещен в конструкцию try..catch, которая не содержит соответствующего блока catch для обработки возникшего исключения, то система производит поиск соответствующего обработчика исключения в стеке вызовов.

Например, рассмотрим следующую программу:

using System;
 
namespace HelloApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                TestClass.Method1();
            }
            catch (DivideByZeroException ex)
            {
                Console.WriteLine($"Catch в Main : {ex.Message}");
            }
            finally
            {
                Console.WriteLine("Блок finally в Main");
            }
            Console.WriteLine("Конец метода Main");
            Console.Read();
        }
    }
    class TestClass
    {
        public static void Method1()
        {
            try
            {
                Method2();
            }
            catch (IndexOutOfRangeException ex)
            {
                Console.WriteLine($"Catch в Method1 : {ex.Message}");
            }
            finally
            {
                Console.WriteLine("Блок finally в Method1");
            }
            Console.WriteLine("Конец метода Method1");
        }
        static void Method2()
        {
            try
            {
                int x = 8;
                int y = x / 0;
            }
            finally
            {
                Console.WriteLine("Блок finally в Method2");
            }
            Console.WriteLine("Конец метода Method2");
        }
    }
}

В данном случае стек вызовов выглядит следующим образом: метод Main вызывает метод Method1, который, в свою очередь, вызывает метод Method2. И в методе Method2 генерируется исключение DivideByZeroException. Визуально стек вызовов можно представить следующим образом:

Внизу стека метод Main, с которого началось выполнение, и на самом верху метод Method2.

Что будет происходить в данном случае при генерации исключения?

  1. Метод Main вызывает метод Method1, а тот вызывает метод Method2, в котором генерируется исключение DivideByZeroException.

  2. Система видит, что код, который вызывал исключение, помещен в конструкцию try..catch

    try
    {
        int x = 8;
        int y = x / 0;
    }
    finally
    {
        Console.WriteLine("Блок finally в Method2");
    }

    Система ищет в этой конструкции блок catch, который обрабатывает исключение DivideByZeroException. Однако такого блока catch нет.

  3. Система опускается в стеке вызовов в метод Method1, который вызывал Method2. Здесь вызов Method2 помещен в конструкцию try..catch

    try
    {
        Method2();
    }
    catch (IndexOutOfRangeException ex)
    {
        Console.WriteLine($"Catch в Method1 : {ex.Message}");
    }
    finally
    {
        Console.WriteLine("Блок finally в Method1");
    }

    Система также ищет в этой конструкции блок catch, который обрабатывает исключение DivideByZeroException. Однако здесь также подобный блок catch отсутствует.

  4. Система далее опускается в стеке вызовов в метод Main, который вызывал Method1. Здесь вызов Method1 помещен в конструкцию try..catch

    try
    {
        TestClass.Method1();
    }
    catch (DivideByZeroException ex)
    {
        Console.WriteLine($"Catch в Main : {ex.Message}");
    }
    finally
    {
        Console.WriteLine("Блок finally в Main");
    }

    Система снова ищет в этой конструкции блок catch, который обрабатывает исключение DivideByZeroException. И в данном случае ткой блок найден.

  5. Система наконец нашла нужный блок catch в методе Main, для обработки исключения, которое возникло в методе Method2 — то есть к начальному методу, где непосредственно возникло исключение. Но пока данный блок catch НЕ выполняется. Система поднимается обратно по стеку вызовов в самый верх в метод Method2 и выполняет в нем блок finally:

    finally
    {
        Console.WriteLine("Блок finally в Method2");
    }
  6. Далее система возвращается по стеку вызовов вниз в метод Method1 и выполняет в нем блок finally:

    finally
    {
        Console.WriteLine("Блок finally в Method1");
    }
  7. Затем система переходит по стеку вызовов вниз в метод Main и выполняет в нем найденный блок catch и последующий блок finally:

    catch (DivideByZeroException ex)
    {
        Console.WriteLine($"Catch в Main : {ex.Message}");
    }
    finally
    {
        Console.WriteLine("Блок finally в Main");
    }
  8. Далее выполняется код, который идет в методе Main после конструкции try..catch:

    Console.WriteLine("Конец метода Main");

    Стоит отметить, что код, который идет после конструкции try…catch в методах Method1 и Method2, не выполняется, потому что обработчик исключения найден именно в методе Main.

Консольный вывод программы:

Блок finally в Method2
Блок finally в Method1
Catch в Main: Попытка деления на нуль.
Блок finally в Main
Конец метода Main

Генерация исключения и оператор throw

Обычно система сама генерирует исключения при определенных ситуациях, например, при делении числа на ноль. Но язык C# также позволяет генерировать исключения вручную с помощью оператора throw. То есть с помощью этого оператора мы сами можем создать исключение и вызвать его в процессе выполнения.

Например, в нашей программе происходит ввод строки, и мы хотим, чтобы, если длина строки будет больше 6 символов, возникало исключение:

static void Main(string[] args)
{
    try
    {
        Console.Write("Введите строку: ");
        string message = Console.ReadLine();
        if (message.Length > 6)
        {
            throw new Exception("Длина строки больше 6 символов");
        }
    }
    catch (Exception e)
    {
        Console.WriteLine($"Ошибка: {e.Message}");
    }
    Console.Read();
}

После оператора throw указывается объект исключения, через конструктор которого мы можем передать сообщение об ошибке. Естественно вместо типа Exception мы можем использовать объект любого другого типа исключений.

Затем в блоке catch сгенерированное нами исключение будет обработано.

Подобным образом мы можем генерировать исключения в любом месте программы. Но существует также и другая форма использования оператора throw, когда после данного оператора не указывается объект исключения. В подобном виде оператор throw может использоваться только в блоке catch:

try
{
    try
    {
        Console.Write("Введите строку: ");
        string message = Console.ReadLine();
        if (message.Length > 6)
        {
            throw new Exception("Длина строки больше 6 символов");
        }
    }
    catch
    {
        Console.WriteLine("Возникло исключение");
        throw;
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

В данном случае при вводе строки с длиной больше 6 символов возникнет исключение, которое будет обработано внутренним блоком catch. Однако поскольку в этом блоке используется оператор throw, то исключение будет передано дальше внешнему блоку catch.

Методы поиска ошибок в программах

Международный стандарт ANSI/IEEE-729-83 разделяет все ошибки в разработке программ на следующие типы.

Ошибка (error) — состояние программы, при котором выдаются неправильные результаты, причиной которых являются изъяны (flaw) в операторах программы или в технологическом процессе ее разработки, что приводит к неправильной интерпретации исходной информации, следовательно, и к неверному решению.

Дефект (fault) в программе — следствие ошибок разработчика на любом из этапов разработки, которая может содержаться в исходных или проектных спецификациях, текстах кодов программ, эксплуатационной документация и т.п. В процессе выполнения программы может быть обнаружен дефект или сбой.

Отказ (failure) — это отклонение программы от функционирования или невозможность программы выполнять функции, определенные требованиями и ограничениями, что рассматривается как событие, способствующее переходу программы в неработоспособное состояние из-за ошибок, скрытых в ней дефектов или сбоев в среде функционирования [7.6, 7.11]. Отказ может быть результатом следующих причин:

  • ошибочная спецификация или пропущенное требование, означающее, что спецификация точно не отражает того, что предполагал пользователь;
  • спецификация может содержать требование, которое невозможно выполнить на данной аппаратуре и программном обеспечении;
  • проект программы может содержать ошибки (например, база данных спроектирована без средств защиты от несанкционированного доступа пользователя, а требуется защита);
  • программа может быть неправильной, т.е. она выполняет несвойственный алгоритм или он реализован не полностью.

Таким образом, отказы, как правило, являются результатами одной или более ошибок в программе, а также наличия разного рода дефектов.

Ошибки на этапах процесса тестирования. Приведенные типы ошибок распределяются по этапам ЖЦ и им соответствуют такие источники их возникновения:

  • непреднамеренное отклонение разработчиков от рабочих стандартов или планов реализации;
  • спецификации функциональных и интерфейсных требований выполнены без соблюдения стандартов разработки, что приводит к нарушению функционирования программ;
  • организации процесса разработки — несовершенная или недостаточное управление руководителем проекта ресурсами (человеческими, техническими, программными и т.д.) и вопросами тестирования и интеграции элементов проекта.

Рассмотрим процесс тестирования, исходя из рекомендаций стандарта ISO/IEC 12207, и приведем типы ошибок, которые обнаруживаются на каждом процессе ЖЦ.

Процесс разработки требований. При определении исходной концепции системы и исходных требований к системе возникают ошибки аналитиков при спецификации верхнего уровня системы и построении концептуальной модели предметной области.

Характерными ошибками этого процесса являются:

  • неадекватность спецификации требований конечным пользователям;
  • некорректность спецификации взаимодействия ПО со средой функционирования или с пользователями;
  • несоответствие требований заказчика к отдельным и общим свойствам ПО;
  • некорректность описания функциональных характеристик;
  • необеспеченность инструментальными средствами всех аспектов реализации требований заказчика и др.

Процесс проектирования. Ошибки при проектировании компонентов могут возникать при описании алгоритмов, логики управления, структур данных, интерфейсов, логики моделирования потоков данных, форматов ввода-вывода и др. В основе этих ошибок лежат дефекты спецификаций аналитиков и недоработки проектировщиков. К ним относятся ошибки, связанные:

  • с определением интерфейса пользователя со средой;
  • с описанием функций (неадекватность целей и задач компонентов, которые обнаруживаются при проверке комплекса компонентов);
  • с определением процесса обработки информации и взаимодействия между процессами (результат некорректного определения взаимосвязей компонентов и процессов);
  • с некорректным заданием данных и их структур при описании отдельных компонентов и ПС в целом;
  • с некорректным описанием алгоритмов модулей;
  • с определением условий возникновения возможных ошибок в программе;
  • с нарушением принятых для проекта стандартов и технологий.

Этап кодирования. На данном этапе возникают ошибки, которые являются результатом дефектов проектирования, ошибок программистов и менеджеров в процессе разработки и отладки системы. Причиной ошибок являются:

  • бесконтрольность значений входных параметров, индексов массивов, параметров циклов, выходных результатов, деления на 0 и др.;
  • неправильная обработка нерегулярных ситуаций при анализе кодов возврата от вызываемых подпрограмм, функций и др.;
  • нарушение стандартов кодирования (плохие комментарии, нерациональное выделение модулей и компонент и др.);
  • использование одного имени для обозначения разных объектов или разных имен одного объекта, плохая мнемоника имен;
  • несогласованное внесение изменений в программу разными разработчиками и др.

Процесс тестирования. На этом процессе ошибки допускаются программистами и тестировщиками при выполнении технологии сборки и тестирования, выбора тестовых наборов и сценариев тестирования и др. Отказы в программном обеспечении, вызванные такого рода ошибками, должны выявляться, устраняться и не отражаться на статистике ошибок компонент и программного обеспечения в целом.

Процесс сопровождения. На процессе сопровождения обнаруживаются ошибки, причиной которых являются недоработки и дефекты эксплуатационной документации, недостаточные показатели модифицируемости и удобочитаемости, а также некомпетентность лиц, ответственных за сопровождение и/или усовершенствование ПО. В зависимости от сущности вносимых изменений на этом этапе могут возникать практически любые ошибки, аналогичные ранее перечисленным ошибкам на предыдущих этапах.

Все ошибки, которые возникают в программах, принято подразделять на следующие классы:

  • логические и функциональные ошибки;
  • ошибки вычислений и времени выполнения;
  • ошибки вводавывода и манипулирования данными;
  • ошибки интерфейсов;
  • ошибки объема данных и др.

Логические ошибки являются причиной нарушения логики алгоритма, внутренней несогласованности переменных и операторов, а также правил программирования. Функциональные ошибки — следствие неправильно определенных функций, нарушения порядка их применения или отсутствия полноты их реализации и т.д.

Ошибки вычислений возникают по причине неточности исходных данных и реализованных формул, погрешностей методов, неправильного применения операций вычислений или операндов. Ошибки времени выполнения связаны с необеспечением требуемой скорости обработки запросов или времени восстановления программы.

Ошибки ввода-вывода и манипулирования данными являются следствием некачественной подготовки данных для выполнения программы, сбоев при занесении их в базы данных или при выборке из нее.

Ошибки интерфейса относятся к ошибкам взаимосвязи отдельных элементов друг с другом, что проявляется при передаче данных между ними, а также при взаимодействии со средой функционирования.

Ошибки объема относятся к данным и являются следствием того, что реализованные методы доступа и размеры баз данных не удовлетворяют реальным объемам информации системы или интенсивности их обработки.

Приведенные основные классы ошибок свойственны разным типам компонентов ПО и проявляются они в программах по разному. Так, при работе с БД возникают ошибки представления и манипулирования данными, логические ошибки в задании прикладных процедур обработки данных и др. В программах вычислительного характера преобладают ошибки вычислений, а в программах управления и обработки — логические и функциональные ошибки. В ПО, которое состоит из множества разноплановых программ, реализующих разные функции, могут содержаться ошибки разных типов. Ошибки интерфейсов и нарушение объема характерны для любого типа систем.

Анализ типов ошибок в программах является необходимым условием создания планов тестирования и методов тестирования для обеспечения правильности ПО.

На современном этапе развития средств поддержки разработки ПО (CASE-технологии, объектно-ориентированные методы и средства проектирования моделей и программ) проводится такое проектирование, при котором ПО защищается от наиболее типичных ошибок и тем самым предотвращается появление программных дефектов.

Связь ошибки с отказом. Наличие ошибки в программе, как правило, приводит к отказу ПО при его функционировании. Для анализа причинно-следственных связей «ошибкаотказ» выполняются следующие действия:

  • идентификация изъянов в технологиях проектирования и программирования;
  • взаимосвязь изъянов процесса проектирования и допускаемых человеком ошибок;
  • классификация отказов, изъянов и возможных ошибок, а также дефектов на каждом этапе разработки;
  • сопоставление ошибок человека, допускаемых на определенном процессе разработки, и дефектов в объекте, как следствий ошибок спецификации проекта, моделей программ;
  • проверка и защита от ошибок на всех этапах ЖЦ, а также обнаружение дефектов на каждом этапе разработки;
  • сопоставление дефектов и отказов в ПО для разработки системы взаимосвязей и методики локализации, сбора и анализа информации об отказах и дефектах;
  • разработка подходов к процессам документирования и испытания ПО.

Конечная цель причинно-следственных связей «ошибка-отказ» заключается в определении методов и средств тестирования и обнаружения ошибок определенных классов, а также критериев завершения тестирования на множестве наборов данных; в определении путей совершенствования организации процесса разработки, тестирования и сопровождения ПО.

Приведем следующую классификацию типов отказов:

  • аппаратный, при котором общесистемное ПО не работоспособно;
  • информационный, вызванный ошибками во входных данных и передаче данных по каналам связи, а также при сбое устройств ввода (следствие аппаратных отказов);
  • эргономический, вызванный ошибками оператора при его взаимодействии с машиной (этот отказ — вторичный отказ, может привести к информационному или функциональному отказам);
  • программный, при наличии ошибок в компонентах и др.

Некоторые ошибки могут быть следствием недоработок при определении требований, проекта, генерации выходного кода или документации. С другой стороны, они порождаются в процессе разработки программы или при разработке интерфейсов отдельных элементов программы (нарушение порядка параметров, меньше или больше параметров и т.п.).

Источники ошибок. Ошибки могут быть порождены в процессе разработки проекта, компонентов, кода и документации. Как правило, они обнаруживаются при выполнении или сопровождении программного обеспечения в самых неожиданных и разных ее точках.

Некоторые ошибки в программе могут быть следствием недоработок при определении требований, проекта, генерации кода или документации. С другой стороны, ошибки порождаются в процессе разработки программы или интерфейсов ее элементов (например, при нарушении порядка задания параметров связи — меньше или больше, чем требуется и т.п.).

Причиной появления ошибок — непонимание требований заказчика; неточная спецификация требований в документах проекта и др. Это приводит к тому, что реализуются некоторые функции системы, которые будут работать не так, как предлагает заказчик. В связи с этим проводится совместное обсуждение заказчиком и разработчиком некоторых деталей требований для их уточнения.

Команда разработчиков системы может также изменить синтаксис и семантику описания системы. Однако некоторые ошибки могут быть не обнаружены (например, неправильно заданы индексы или значения переменных этих операторов).

Цель функционального тестирования — обнаружение несоответствий между реальным поведением реализованных функций и ожидаемым поведением в соответствии со спецификацией и исходными требованиями. Функциональные тесты должны охватывать все реализованные функции с учетом наиболее вероятных типов ошибок. Тестовые сценарии, объединяющие отдельные тесты, ориентированы на проверку качества решения функциональных задач.

Функциональные тесты создаются по внешним спецификациям функций, проектной информации и по тексту на ЯП, относятся к функциональным его характеристикам и применяются на этапе комплексного тестирования и испытаний для определения полноты реализации функциональных задач и их соответствия исходным требованиям.

В задачи функционального тестирования входят:

· идентификация множества функциональных требований;

· идентификация внешних функций и построение последовательностей функций в соответствии с их использованием в ПС;- идентификация множества входных данных каждой функции и определение областей их изменения;

· построение тестовых наборов и сценариев тестирования функций;

· выявление и представление всех функциональных требований с помощью тестовых наборов и проведение тестирования ошибок в программе и при взаимодействии со средой.

Тесты, создаваемые по проектной информации, связаны со структурами данных, алгоритмами, интерфейсами между отдельными компонентами и применяются для тестирования компонентов и их интерфейсов. Основная цель — обеспечение полноты и согласованности реализованных функций и интерфейсов между ними.

Комбинированный метод «черного ящика» и «прозрачного ящика» основан на разбиении входной области функции на подобласти обнаружения ошибок. Подобласть содержит однородные элементы, которые все обрабатываются корректно либо некорректно. Для тестирования подобласти производится выполнение программы на одном из элементов этой области.

Предпосылки функционального тестирования:

· корректное оформление требований и ограничений к качеству ПО;

· корректное описание модели функционирования ПО в среде эксплуатации у заказчика;

· адекватность модели ПО заданному классу.

Под инфраструктурой процесса тестирования понимается:

· выделение объектов тестирования;

· проведение классификации ошибок для рассматриваемого класса тестируемых программ;

· подготовка тестов, их выполнение и поиск разного рода ошибок и отказов в компонентах и в системе в целом;

· служба проведения и управление процессом тестирования;

· анализ результатов тестирования.

Объекты тестирования — компоненты, группы компонентов, подсистемы и система. Для каждого из них формируется стратегия проведения тестирования. Если объект тестирования относится к «белому ящику» или «черному ящику», состав компонентов которого неизвестный, то тестирование проводится посредством ввода внего входных тестовых данных для получения выходных данных. Стратегическая цель тестирования состоит в том, чтобы убедиться, что каждый рассматриваемый входной набор данных соответствует ожидаемым выходным выходных данным. При таком подходе к тестированию не требуется знания внутренней структуры и логики объекта тестирования.

Проектировщик тестов должен заглянуть внутрь «черного ящика» и исследовать детали процессов обработки данных, вопросы обеспечения защиты и восстановления данных, а также интерфейсы с другими программами и системами. Это способствует подготовке тестовых данных для проведения тестирования.

Для некоторых типов объектов группа тестирования не может сгенерировать представительное множество тестовых наборов, которые демонстрировали бы функциональную правильность работы компоненты при всех возможных наборах тестов.

Поэтому предпочтительным является метод «белого ящика», при котором можно использовать структуру объекта для организации тестирования по различным ветвям. Например, можно выполнить тестовые наборы, которые проходят через все операторы или все контрольные точки компонента для того, чтобы убедиться в правильности их работы.

Международный стандарт ANSI/IEEE-729-83 разделяет все ошибки в разработке программ на следующие типы.

Ошибка (error) — состояние программы, при котором выдаются неправильные результаты, причиной которых являются изъяны (flaw) в операторах программы или в технологическом процессе ее разработки, что приводит к неправильной интерпретации исходной информации, следовательно, и к неверному решению.

Дефект (fault) в программе — следствие ошибок разработчика на любом из этапов разработки, которая может содержаться в исходных или проектных спецификациях, текстах кодов программ, эксплуатационной документация и т.п. В процессе выполнения программы может быть обнаружен дефект или сбой.

Отказ (failure) — это отклонение программы от функционирования или невозможность программы выполнять функции, определенные требованиями и ограничениями, что рассматривается как событие, способствующее переходу программы в неработоспособное состояние из-за ошибок, скрытых в ней дефектов или сбоев в среде функционирования. Отказ может быть результатом следующих причин:

· ошибочная спецификация или пропущенное требование, означающее, что спецификация точно не отражает того, что предполагал пользователь;

· спецификация может содержать требование, которое невозможно выполнить на данной аппаратуре и программном обеспечении;

· проект программы может содержать ошибки (например, база данных спроектирована без средств защиты от несанкционированного доступа пользователя, а требуется защита);

· программа может быть неправильной, т.е. она выполняет несвойственный алгоритм или он реализован не полностью.

Таким образом, отказы, как правило, являются результатами одной или более ошибок в программе, а также наличия разного рода дефектов.

Ошибки на этапах процесса тестирования. Приведенные типы ошибок распределяются по этапам ЖЦ и им соответствуют такие источники их возникновения:

· непреднамеренное отклонение разработчиков от рабочих стандартов или планов реализации;

· спецификации функциональных и интерфейсных требований выполнены без соблюдения стандартов разработки, что приводит к нарушению функционирования программ;

· организации процесса разработки — несовершенная или недостаточное управление руководителем проекта ресурсами (человеческими, техническими, программными и т.д.) и вопросами тестирования и интеграции элементов проекта.

Рассмотрим процесс тестирования, исходя из рекомендаций стандарта ISO/IEC 12207, и приведем типы ошибок, которые обнаруживаются на каждом процессе ЖЦ.

Процесс разработки требований. При определении исходной концепции системы и исходных требований к системе возникают ошибки аналитиков при спецификации верхнего уровня системы и построении концептуальной модели предметной области.

Характерными ошибками этого процесса являются:

· неадекватность спецификации требований конечным пользователям;- некорректность спецификации взаимодействия ПО со средой функционирования или с пользователями;

· несоответствие требований заказчика к отдельным и общим свойствам ПО;

· некорректность описания функциональных характеристик;

· необеспеченность инструментальными средствами всех аспектов реализации требований заказчика и др.

Процесс проектирования. Ошибки при проектировании компонентов могут возникать при описании алгоритмов, логики управления, структур данных, интерфейсов, логики моделирования потоков данных, форматов ввода-вывода и др. В основе этих ошибок лежат дефекты спецификаций аналитиков и недоработки проектировщиков. К ним относятся ошибки, связанные:

· с определением интерфейса пользователя со средой;

· с описанием функций (неадекватность целей и задач компонентов, которые обнаруживаются при проверке комплекса компонентов);

· с определением процесса обработки информации и взаимодействия между процессами (результат некорректного определения взаимосвязей компонентов и процессов);

· с некорректным заданием данных и их структур при описании отдельных компонентов и ПС в целом;

· с некорректным описанием алгоритмов модулей;

· с определением условий возникновения возможных ошибок в программе;

· с нарушением принятых для проекта стандартов и технологий.

Этап кодирования. На данном этапе возникают ошибки, которые являются результатом дефектов проектирования, ошибок программистов и менеджеров в процессе разработки и отладки системы. Причиной ошибок являются:

· бесконтрольность значений входных параметров, индексов массивов, параметров циклов, выходных результатов, деления на 0 и др.;

· неправильная обработка нерегулярных ситуаций при анализе кодов возврата от вызываемых подпрограмм, функций и др.;

· нарушение стандартов кодирования (плохие комментарии, нерациональное выделение модулей и компонент и др.);

· использование одного имени для обозначения разных объектов или разных имен одного объекта, плохая мнемоника имен;- несогласованное внесение изменений в программу разными разработчиками и др.

Процесс тестирования. На этом процессе ошибки допускаются программистами и тестировщиками при выполнении технологии сборки и тестирования, выбора тестовых наборов и сценариев тестирования и др. Отказы в программном обеспечении, вызванные такого рода ошибками, должны выявляться, устраняться и не отражаться на статистике ошибок компонент и программного обеспечения в целом.

Процесс сопровождения. На процессе сопровождения обнаруживаются ошибки, причиной которых являются недоработки и дефекты эксплуатационной документации, недостаточные показатели модифицируемости и удобочитаемости, а также некомпетентность лиц, ответственных за сопровождение и/или усовершенствование ПО. В зависимости от сущности вносимых изменений на этом этапе могут возникать практически любые ошибки, аналогичные ранее перечисленным ошибкам на предыдущих этапах.

Все ошибки, которые возникают в программах, принято подразделять на следующие классы:

· логические и функциональные ошибки;

· ошибки вычислений и времени выполнения;

· ошибки ввода-вывода и манипулирования данными;

· ошибки интерфейсов;

· ошибки объема данных и др.

Логические ошибки являются причиной нарушения логики алгоритма, внутренней несогласованности переменных и операторов, а также правил программирования. Функциональные ошибки — следствие неправильно определенных функций, нарушения порядка их применения или отсутствия полноты их реализации и т.д.

Ошибки вычислений возникают по причине неточности исходных данных и реализованных формул, погрешностей методов, неправильного применения операций вычислений или операндов. Ошибки времени выполнения связаны с не обеспечением требуемой скорости обработки запросов или времени восстановления программы.

Ошибки ввода-вывода и манипулирования данными являются следствием некачественной подготовки данных для выполнения программы, сбоев при занесении их в базы данных или при выборке из нее.

Ошибки интерфейса относятся к ошибкам взаимосвязи отдельных элементов друг с другом, что проявляется при передаче данных между ними, а также при взаимодействии со средой функционирования.

Ошибки объема относятся к данным и являются следствием того, что реализованные методы доступа и размеры баз данных не удовлетворяют реальным объемам информации системы или интенсивности их обработки.

Приведенные основные классы ошибок свойственны разным типам компонентов ПО и проявляются они в программах по разному. Так, при работе с БД возникают ошибки представления и манипулирования данными, логические ошибки в задании прикладных процедур обработки данных и др. В программах вычислительного характера преобладают ошибки вычислений, а в программах управления и обработки — логические и функциональные ошибки. В ПО, которое состоит из множества разноплановых программ, реализующих разные функции, могут содержаться ошибки разных типов. Ошибки интерфейсов и нарушение объема характерны для любого типа систем.

Анализ типов ошибок в программах является необходимым условием создания планов тестирования и методов тестирования для обеспечения правильности ПО.

На современном этапе развития средств поддержки разработки ПО (CASE-технологии, объектно-ориентированные методы и средства проектирования моделей и программ) проводится такое проектирование, при котором ПО защищается от наиболее типичных ошибок и тем самым предотвращается появление программных дефектов.

Связь ошибки с отказом. Наличие ошибки в программе, как правило, приводит к отказу ПО при его функционировании. Для анализа причинно-следственных связей «ошибка отказ» выполняются следующие действия:

· идентификация изъянов в технологиях проектирования и программирования;

· взаимосвязь изъянов процесса проектирования и допускаемых человеком ошибок;

· классификация отказов, изъянов и возможных ошибок, а также дефектов на каждом этапе разработки;- сопоставление ошибок человека, допускаемых на определенном процессе разработки, и дефектов в объекте, как следствий ошибок спецификации проекта, моделей программ;

· проверка и защита от ошибок на всех этапах ЖЦ, а также обнаружение дефектов на каждом этапе разработки;

· сопоставление дефектов и отказов в ПО для разработки системы взаимосвязей и методики локализации, сбора и анализа информации об отказах и дефектах;

· разработка подходов к процессам документирования и испытания ПО.

Конечная цель причинно-следственных связей «ошибка отказ» заключается в определении методов и средств тестирования и обнаружения ошибок определенных классов, а также критериев завершения тестирования на множестве наборов данных; в определении путей совершенствования организации процесса разработки, тестирования и сопровождения ПО.

Приведем следующую классификацию типов отказов:

· аппаратный, при котором общесистемное ПО не работоспособно;

· информационный, вызванный ошибками во входных данных и передаче данных по каналам связи, а также при сбое устройств ввода (следствие аппаратных отказов);

· эргономический, вызванный ошибками оператора при его взаимодействии с машиной (этот отказ — вторичный отказ, может привести к информационному или функциональному отказам);

· программный, при наличии ошибок в компонентах и др.

Некоторые ошибки могут быть следствием недоработок при определении требований, проекта, генерации выходного кода или документации. С другой стороны, они порождаются в процессе разработки программы или при разработке интерфейсов отдельных элементов программы (нарушение порядка параметров, меньше или больше параметров и т.п.).

Источники ошибок. Ошибки могут быть порождены в процессе разработки проекта, компонентов, кода и документации. Как правило, они обнаруживаются при выполнении или сопровождении программного обеспечения в самых неожиданных и разных ее точках.

Некоторые ошибки в программе могут быть следствием недоработок при определении требований, проекта, генерации кода или документации. С другой стороны, ошибки порождаются в процессе разработки программы или интерфейсов ее элементов (например, при нарушении порядка задания параметров связи — меньше или больше, чем требуется и т.п.).

Причиной появления ошибок — непонимание требований заказчика; неточная спецификация требований в документах проекта и др. Это приводит к тому, что реализуются некоторые функции системы, которые будут работать не так, как предлагает

заказчик. В связи с этим проводится совместное обсуждение заказчиком и разработчиком некоторых деталей требований для их уточнения.

Команда разработчиков системы может также изменить синтаксис и семантику описания системы. Однако некоторые ошибки могут быть не обнаружены (например, неправильно заданы индексы или значения переменных этих операторов).

Дебаг и поиск ошибок

Для опытных разработчиков информация статьи может быть очевидной и если вы себя таковым считаете, то лучше добавьте в комментариях полезных советов.

По опыту работы с начинающими разработчиками, я сталкиваюсь с тем, что поиск ошибок порой занимает слишком много времени. Не из-за того, что они глупее более опытных товарищей или не разбираются в процессах, а из-за отсутствия понимания с чего начать и на чём акцентировать внимание. В статье я собрал общие советы о том где обитают ошибки и как найти причину их возникновения. Примеры в статье даны на JavaScript и .NET, но они актуальны и для других платформ с поправкой на специфику.

Как обнаружить ошибку

Прочитай информацию об исключении

Если выполнение программы прерывается исключением, то это первое место откуда стоит начинать поиск. 

В каждом языке есть свои способы уведомления об исключениях. Например в JavaScript для обработки ошибок связанных с Web Api существует DOMException. Для пользовательских сценариев есть базовый тип Error. В обоих случаях в них содержится информация о наименовании и описании ошибки.

Для .NET существует класс Exception и каждое исключение в приложении унаследовано от данного класса, который представляет ошибки происходящие во время выполнения программы. В свойстве Message читаем текст ошибки. Это даёт общее понимание происходящего. В свойстве Source смотрим в каком объекте произошла ошибка. В InnerException смотрим, нет ли внутреннего исключения и если было, то разворачиваем его и смотрим информацию уже в нём. В свойстве StackTrace хранится строковое представление информации о стеке вызова в момент появления ошибки.

Каким бы языком вы не пользовались, не поленитесь изучить каким образом язык предоставляет информацию об исключениях и что эта информация означает.

Всю полученную информацию читаем вдумчиво и внимательно. Любая деталь важна при поиске ошибки. Иногда начинающие разработчики не придают значения этому описанию. Например в .NET при возникновении ошибки NRE с описанием параметра, который разработчик задаёт выше по коду. Из-за этого думает, что параметр не может быть NRE, а значит ошибка в другом месте. На деле оказывается, что ошибки транслируют ту картину, которую видит среда выполнения и первым делом за гипотезу стоит взять утверждение, что этот параметр равен null. Поэтому разберитесь при каких условиях параметр стал null, даже если он определялся выше по коду.

Пример неявного переопределения параметров — использование интерцептора, который изменяет этот параметр в запросе и о котором вы не знаете.

Разверните стек

Когда выбрасывается исключение, помимо самого описания ошибки полезно изучить стек выполнения. Для .NET его можно посмотреть в свойстве исключения StackTrace. Для JavaScript аналогично смотрим в Error.prototype.stack (свойство не входит в стандарт) или можно вывести в консоль выполнив console.trace(). В стеке выводятся названия методов в том порядке в котором они вызывались. Если то место, где падает ошибка зависит от аргументов которые пришли из вызывающего метода, то если развернуть стек, мы проследим где эти аргументы формировались.

Загуглите текст ошибки

Очевидное правило, которым не все пользуются. Применимо к не типовым ошибкам, например связанным с конкретной библиотекой или со специфическим типом исключения. Поиск по тексту ошибки помогает найти аналогичные случаи, которые даже если не дадут конкретного решения, то помогут понять контекст её возникновения.

Прочитайте документацию

Если ошибка связана с использованием внешней библиотеки, убедитесь что понимаете как она работает и как правильно с ней взаимодействовать. Типичные ошибки, когда подключив новую библиотеку после прочтения Getting Started она не работает как ожидалось или выбрасывает исключение. Проблема может быть в том, что базовый шаблон подключения библиотеки не применим к текущему приложению и требуются дополнительные настройки или библиотека не совместима с текущим окружением. Разобраться в этом поможет прочтение документации.

Проведите исследовательское тестирование

Если используете библиотеку которая не работает как ожидалось, а нормальная документация отсутствует, то создайте тесты которые покроют интересующий функционал. В ассертах опишите ожидаемое поведение. Если тесты не проходят, то подбирая различные вариации входных данных выясните рабочую конфигурацию. Цель исследовательских тестов помочь разобраться без документации, какое ожидаемое поведение у изучаемой библиотеки в разных сценариях работы. Получив эти знания будет легче понять как правильно использовать библиотеку в проекте.

Бинарный поиск

В неочевидных случаях, если нет уверенности что проблема в вашем коде, а сообщение об ошибке не даёт понимания где проблема,  комментируем блок кода в котором обнаружилась проблема. Убеждаемся что ошибка пропала. Аналогично бинарному алгоритму раскомментировали половину кода, проверили воспроизводимость ошибки. Если воспроизвелась, закомментировали половину выполняемого кода, повторили проверку и так далее пока не будет локализовано место появления ошибки.

Где обитают ошибки

Ошибки в своём коде

Самые распространенные ошибки. Мы писали код, ошиблись в формуле, забыли присвоить значение переменной или что-то не проинициализировали перед вызовом. Такие ошибки легко исправить и легко найти место возникновения если внимательно прочитать описание возникшей ошибки.

Ошибки в чужом коде

Если над проектом работает больше одного разработчика, чей код взаимодействует друг с другом, возможна ситуация, когда ошибка происходит в чужом коде. Может сложиться впечатление, что если программа раньше работала, а сломалась только после того, как вы добавили свой код, то проблема в этом коде. На деле может быть, что ваш код обращается к уже существующему чужому коду, но передаёт туда граничные значения данных, работу с которыми забыли протестировать и обработать такие случаи. 

В зависимости от соглашений на проекте исправляйте такие ошибки как свои собственные, либо сообщайте о них автору и ждите внесения правок.

Ошибки в библиотеках

Ошибки могут падать во внешних библиотеках к которым нет доступа и в таком случае непонятно что делать. Такие ошибки можно разделить на два типа. Первый- это ошибки в коде библиотеки. Второй- это ошибки связанные с невалидными данными или окружением, которые приводят к внутреннему исключению. 

Первый случай хотя и редкий, но не стоит о нём забывать. В этом случае можно откатиться на другую версию библиотеки и создать Issue с описанием проблемы. Если это open-source и нет времени ждать обновления, можно собрать свою версию исправив баг самостоятельно, с последующей заменой на официальную исправленную версию.

Во втором случае определите откуда из вашего кода пришли невалидные данные. Для этого смотрим стек выполнения и по цепочке прослеживаем место в котором библиотека вызывается из нашего кода. Далее с этого места начинаем анализ, как туда попали невалидные данные.

Ошибки не воспроизводимые локально

Ошибка воспроизводится на develop стенде или в production, но не воспроизводится локально. Такие ошибки сложнее отлавливать потому что не всегда есть возможность  запустить дебаг на удалённой машине. Поэтому убеждаемся, что ваше окружение соответствует внешнему. 

Проверьте версию приложения

На стенде и локально версии приложения должны совпадать. Возможно на стенде приложение развёрнуто из другой ветки.

Проверьте данные

Проблема может быть в невалидных данных, а локальная и тестовая база данных рассинхронизированы. В этом случае поиск ошибки воспроизводим локально подключившись к тестовой БД, либо сняв с неё актуальный дамп.

Проверьте соответствие окружений

Если проект на стенде развёрнут в контейнере, то в некоторых IDE (JB RIder) можно дебажить в контейнере. Если проект развёрнут не в контейнере, то воспроизводимость ошибки может зависеть от окружения. Хотя .Net Core мультиплатформенный фреймворк, не всё что работает под Windows так же работает под Linux. В этом случае либо найти рабочую машину с таким же окружением, либо воспроизвести окружение через контейнеры или виртуальную машину.

Коварные ошибки

Метод из подключенной библиотеки не хочет обрабатывать ваши аргументы или не имеет нужных аргументов. Такие ситуации возникают, когда в проекте подключены две разных библиотеки содержащие методы с одинаковым названием, а разработчик по привычке понадеялся, что IDE автоматически подключит правильный using. Такое часто бывает с библиотеками расширяющими функционал LINQ в .NET. Поэтому при автоматическом добавлении using, если всплывает окно с выбором из нескольких вариантов, будьте внимательны. 

Похожая ситуация и с одинаково названными типами. Если сборка включает несколько проектов в которых присутствуют одинаково названные классы, то можно по ошибке обращаться не к тому который требуется. Чтобы избежать обоих случаев, убедитесь, что в месте возникновения ошибки идёт обращение к правильным типам и методам.

Дополнительные материалы

Алгоритм отладки

  1. Повтори ошибку.

  2. Опиши проблему.

  3. Сформулируй гипотезу.

  4. Проверь гипотезу — если гипотеза проверку не прошла то п.3.

  5. Примени исправления.

  6. Убедись что исправлено — если не исправлено, то п.3.

Подробнее ознакомиться с ним можно в докладе Сергея Щегриковича «Отладка как процесс».

Чем искать ошибки, лучше не допускать ошибки. Прочитайте статью «Качество вместо контроля качества», чтобы узнать как это делать.

Итого

  1. При появлении ошибки в которой сложно разобраться сперва внимательно и вдумчиво читаем текст ошибки. 

  2. Смотрим стек выполнения и проверяем, не находится ли причина возникновения выше по стеку.

  3. Если по прежнему непонятно, гуглим текст и ищем похожие случаи. 

  4. Если проблема при взаимодействии с внешней библиотекой, читаем документацию.

  5. Если нет документации проводим исследовательское тестирование.

  6. Если не удается локализовать причину ошибки, применяем метод Бинарного поиска.

To clean up transmission errors introduced by Earth’s atmosphere (left), Goddard scientists applied Reed–Solomon error correction (right), which is commonly used in CDs and DVDs. Typical errors include missing pixels (white) and false signals (black). The white stripe indicates a brief period when transmission was interrupted.

In information theory and coding theory with applications in computer science and telecommunication, error detection and correction (EDAC) or error control are techniques that enable reliable delivery of digital data over unreliable communication channels. Many communication channels are subject to channel noise, and thus errors may be introduced during transmission from the source to a receiver. Error detection techniques allow detecting such errors, while error correction enables reconstruction of the original data in many cases.

Definitions[edit]

Error detection is the detection of errors caused by noise or other impairments during transmission from the transmitter to the receiver.

Error correction is the detection of errors and reconstruction of the original, error-free data.

History[edit]

In classical antiquity, copyists of the Hebrew Bible were paid for their work according to the number of stichs (lines of verse). As the prose books of the Bible were hardly ever written in stichs, the copyists, in order to estimate the amount of work, had to count the letters.[1] This also helped ensure accuracy in the transmission of the text with the production of subsequent copies.[2][3] Between the 7th and 10th centuries CE a group of Jewish scribes formalized and expanded this to create the Numerical Masorah to ensure accurate reproduction of the sacred text. It included counts of the number of words in a line, section, book and groups of books, noting the middle stich of a book, word use statistics, and commentary.[1] Standards became such that a deviation in even a single letter in a Torah scroll was considered unacceptable.[4] The effectiveness of their error correction method was verified by the accuracy of copying through the centuries demonstrated by discovery of the Dead Sea Scrolls in 1947–1956, dating from c.150 BCE-75 CE.[5]

The modern development of error correction codes is credited to Richard Hamming in 1947.[6] A description of Hamming’s code appeared in Claude Shannon’s A Mathematical Theory of Communication[7] and was quickly generalized by Marcel J. E. Golay.[8]

Introduction[edit]

All error-detection and correction schemes add some redundancy (i.e., some extra data) to a message, which receivers can use to check consistency of the delivered message, and to recover data that has been determined to be corrupted. Error-detection and correction schemes can be either systematic or non-systematic. In a systematic scheme, the transmitter sends the original data, and attaches a fixed number of check bits (or parity data), which are derived from the data bits by some deterministic algorithm. If only error detection is required, a receiver can simply apply the same algorithm to the received data bits and compare its output with the received check bits; if the values do not match, an error has occurred at some point during the transmission. In a system that uses a non-systematic code, the original message is transformed into an encoded message carrying the same information and that has at least as many bits as the original message.

Good error control performance requires the scheme to be selected based on the characteristics of the communication channel. Common channel models include memoryless models where errors occur randomly and with a certain probability, and dynamic models where errors occur primarily in bursts. Consequently, error-detecting and correcting codes can be generally distinguished between random-error-detecting/correcting and burst-error-detecting/correcting. Some codes can also be suitable for a mixture of random errors and burst errors.

If the channel characteristics cannot be determined, or are highly variable, an error-detection scheme may be combined with a system for retransmissions of erroneous data. This is known as automatic repeat request (ARQ), and is most notably used in the Internet. An alternate approach for error control is hybrid automatic repeat request (HARQ), which is a combination of ARQ and error-correction coding.

Types of error correction[edit]

There are three major types of error correction.[9]

Automatic repeat request[edit]

Automatic repeat request (ARQ) is an error control method for data transmission that makes use of error-detection codes, acknowledgment and/or negative acknowledgment messages, and timeouts to achieve reliable data transmission. An acknowledgment is a message sent by the receiver to indicate that it has correctly received a data frame.

Usually, when the transmitter does not receive the acknowledgment before the timeout occurs (i.e., within a reasonable amount of time after sending the data frame), it retransmits the frame until it is either correctly received or the error persists beyond a predetermined number of retransmissions.

Three types of ARQ protocols are Stop-and-wait ARQ, Go-Back-N ARQ, and Selective Repeat ARQ.

ARQ is appropriate if the communication channel has varying or unknown capacity, such as is the case on the Internet. However, ARQ requires the availability of a back channel, results in possibly increased latency due to retransmissions, and requires the maintenance of buffers and timers for retransmissions, which in the case of network congestion can put a strain on the server and overall network capacity.[10]

For example, ARQ is used on shortwave radio data links in the form of ARQ-E, or combined with multiplexing as ARQ-M.

Forward error correction[edit]

Forward error correction (FEC) is a process of adding redundant data such as an error-correcting code (ECC) to a message so that it can be recovered by a receiver even when a number of errors (up to the capability of the code being used) are introduced, either during the process of transmission or on storage. Since the receiver does not have to ask the sender for retransmission of the data, a backchannel is not required in forward error correction. Error-correcting codes are used in lower-layer communication such as cellular network, high-speed fiber-optic communication and Wi-Fi,[11][12] as well as for reliable storage in media such as flash memory, hard disk and RAM.[13]

Error-correcting codes are usually distinguished between convolutional codes and block codes:

  • Convolutional codes are processed on a bit-by-bit basis. They are particularly suitable for implementation in hardware, and the Viterbi decoder allows optimal decoding.
  • Block codes are processed on a block-by-block basis. Early examples of block codes are repetition codes, Hamming codes and multidimensional parity-check codes. They were followed by a number of efficient codes, Reed–Solomon codes being the most notable due to their current widespread use. Turbo codes and low-density parity-check codes (LDPC) are relatively new constructions that can provide almost optimal efficiency.

Shannon’s theorem is an important theorem in forward error correction, and describes the maximum information rate at which reliable communication is possible over a channel that has a certain error probability or signal-to-noise ratio (SNR). This strict upper limit is expressed in terms of the channel capacity. More specifically, the theorem says that there exist codes such that with increasing encoding length the probability of error on a discrete memoryless channel can be made arbitrarily small, provided that the code rate is smaller than the channel capacity. The code rate is defined as the fraction k/n of k source symbols and n encoded symbols.

The actual maximum code rate allowed depends on the error-correcting code used, and may be lower. This is because Shannon’s proof was only of existential nature, and did not show how to construct codes which are both optimal and have efficient encoding and decoding algorithms.

Hybrid schemes[edit]

Hybrid ARQ is a combination of ARQ and forward error correction. There are two basic approaches:[10]

  • Messages are always transmitted with FEC parity data (and error-detection redundancy). A receiver decodes a message using the parity information, and requests retransmission using ARQ only if the parity data was not sufficient for successful decoding (identified through a failed integrity check).
  • Messages are transmitted without parity data (only with error-detection information). If a receiver detects an error, it requests FEC information from the transmitter using ARQ, and uses it to reconstruct the original message.

The latter approach is particularly attractive on an erasure channel when using a rateless erasure code.

Error detection schemes[edit]

Error detection is most commonly realized using a suitable hash function (or specifically, a checksum, cyclic redundancy check or other algorithm). A hash function adds a fixed-length tag to a message, which enables receivers to verify the delivered message by recomputing the tag and comparing it with the one provided.

There exists a vast variety of different hash function designs. However, some are of particularly widespread use because of either their simplicity or their suitability for detecting certain kinds of errors (e.g., the cyclic redundancy check’s performance in detecting burst errors).

Minimum distance coding[edit]

A random-error-correcting code based on minimum distance coding can provide a strict guarantee on the number of detectable errors, but it may not protect against a preimage attack.

Repetition codes[edit]

A repetition code is a coding scheme that repeats the bits across a channel to achieve error-free communication. Given a stream of data to be transmitted, the data are divided into blocks of bits. Each block is transmitted some predetermined number of times. For example, to send the bit pattern «1011», the four-bit block can be repeated three times, thus producing «1011 1011 1011». If this twelve-bit pattern was received as «1010 1011 1011» – where the first block is unlike the other two – an error has occurred.

A repetition code is very inefficient, and can be susceptible to problems if the error occurs in exactly the same place for each group (e.g., «1010 1010 1010» in the previous example would be detected as correct). The advantage of repetition codes is that they are extremely simple, and are in fact used in some transmissions of numbers stations.[14][15]

Parity bit[edit]

A parity bit is a bit that is added to a group of source bits to ensure that the number of set bits (i.e., bits with value 1) in the outcome is even or odd. It is a very simple scheme that can be used to detect single or any other odd number (i.e., three, five, etc.) of errors in the output. An even number of flipped bits will make the parity bit appear correct even though the data is erroneous.

Parity bits added to each «word» sent are called transverse redundancy checks, while those added at the end of a stream of «words» are called longitudinal redundancy checks. For example, if each of a series of m-bit «words» has a parity bit added, showing whether there were an odd or even number of ones in that word, any word with a single error in it will be detected. It will not be known where in the word the error is, however. If, in addition, after each stream of n words a parity sum is sent, each bit of which shows whether there were an odd or even number of ones at that bit-position sent in the most recent group, the exact position of the error can be determined and the error corrected. This method is only guaranteed to be effective, however, if there are no more than 1 error in every group of n words. With more error correction bits, more errors can be detected and in some cases corrected.

There are also other bit-grouping techniques.

Checksum[edit]

A checksum of a message is a modular arithmetic sum of message code words of a fixed word length (e.g., byte values). The sum may be negated by means of a ones’-complement operation prior to transmission to detect unintentional all-zero messages.

Checksum schemes include parity bits, check digits, and longitudinal redundancy checks. Some checksum schemes, such as the Damm algorithm, the Luhn algorithm, and the Verhoeff algorithm, are specifically designed to detect errors commonly introduced by humans in writing down or remembering identification numbers.

Cyclic redundancy check[edit]

A cyclic redundancy check (CRC) is a non-secure hash function designed to detect accidental changes to digital data in computer networks. It is not suitable for detecting maliciously introduced errors. It is characterized by specification of a generator polynomial, which is used as the divisor in a polynomial long division over a finite field, taking the input data as the dividend. The remainder becomes the result.

A CRC has properties that make it well suited for detecting burst errors. CRCs are particularly easy to implement in hardware and are therefore commonly used in computer networks and storage devices such as hard disk drives.

The parity bit can be seen as a special-case 1-bit CRC.

Cryptographic hash function[edit]

The output of a cryptographic hash function, also known as a message digest, can provide strong assurances about data integrity, whether changes of the data are accidental (e.g., due to transmission errors) or maliciously introduced. Any modification to the data will likely be detected through a mismatching hash value. Furthermore, given some hash value, it is typically infeasible to find some input data (other than the one given) that will yield the same hash value. If an attacker can change not only the message but also the hash value, then a keyed hash or message authentication code (MAC) can be used for additional security. Without knowing the key, it is not possible for the attacker to easily or conveniently calculate the correct keyed hash value for a modified message.

Error correction code[edit]

Any error-correcting code can be used for error detection. A code with minimum Hamming distance, d, can detect up to d − 1 errors in a code word. Using minimum-distance-based error-correcting codes for error detection can be suitable if a strict limit on the minimum number of errors to be detected is desired.

Codes with minimum Hamming distance d = 2 are degenerate cases of error-correcting codes, and can be used to detect single errors. The parity bit is an example of a single-error-detecting code.

Applications[edit]

Applications that require low latency (such as telephone conversations) cannot use automatic repeat request (ARQ); they must use forward error correction (FEC). By the time an ARQ system discovers an error and re-transmits it, the re-sent data will arrive too late to be usable.

Applications where the transmitter immediately forgets the information as soon as it is sent (such as most television cameras) cannot use ARQ; they must use FEC because when an error occurs, the original data is no longer available.

Applications that use ARQ must have a return channel; applications having no return channel cannot use ARQ.

Applications that require extremely low error rates (such as digital money transfers) must use ARQ due to the possibility of uncorrectable errors with FEC.

Reliability and inspection engineering also make use of the theory of error-correcting codes.[16]

Internet[edit]

In a typical TCP/IP stack, error control is performed at multiple levels:

  • Each Ethernet frame uses CRC-32 error detection. Frames with detected errors are discarded by the receiver hardware.
  • The IPv4 header contains a checksum protecting the contents of the header. Packets with incorrect checksums are dropped within the network or at the receiver.
  • The checksum was omitted from the IPv6 header in order to minimize processing costs in network routing and because current link layer technology is assumed to provide sufficient error detection (see also RFC 3819).
  • UDP has an optional checksum covering the payload and addressing information in the UDP and IP headers. Packets with incorrect checksums are discarded by the network stack. The checksum is optional under IPv4, and required under IPv6. When omitted, it is assumed the data-link layer provides the desired level of error protection.
  • TCP provides a checksum for protecting the payload and addressing information in the TCP and IP headers. Packets with incorrect checksums are discarded by the network stack, and eventually get retransmitted using ARQ, either explicitly (such as through three-way handshake) or implicitly due to a timeout.

Deep-space telecommunications[edit]

The development of error-correction codes was tightly coupled with the history of deep-space missions due to the extreme dilution of signal power over interplanetary distances, and the limited power availability aboard space probes. Whereas early missions sent their data uncoded, starting in 1968, digital error correction was implemented in the form of (sub-optimally decoded) convolutional codes and Reed–Muller codes.[17] The Reed–Muller code was well suited to the noise the spacecraft was subject to (approximately matching a bell curve), and was implemented for the Mariner spacecraft and used on missions between 1969 and 1977.

The Voyager 1 and Voyager 2 missions, which started in 1977, were designed to deliver color imaging and scientific information from Jupiter and Saturn.[18] This resulted in increased coding requirements, and thus, the spacecraft were supported by (optimally Viterbi-decoded) convolutional codes that could be concatenated with an outer Golay (24,12,8) code. The Voyager 2 craft additionally supported an implementation of a Reed–Solomon code. The concatenated Reed–Solomon–Viterbi (RSV) code allowed for very powerful error correction, and enabled the spacecraft’s extended journey to Uranus and Neptune. After ECC system upgrades in 1989, both crafts used V2 RSV coding.

The Consultative Committee for Space Data Systems currently recommends usage of error correction codes with performance similar to the Voyager 2 RSV code as a minimum. Concatenated codes are increasingly falling out of favor with space missions, and are replaced by more powerful codes such as Turbo codes or LDPC codes.

The different kinds of deep space and orbital missions that are conducted suggest that trying to find a one-size-fits-all error correction system will be an ongoing problem. For missions close to Earth, the nature of the noise in the communication channel is different from that which a spacecraft on an interplanetary mission experiences. Additionally, as a spacecraft increases its distance from Earth, the problem of correcting for noise becomes more difficult.

Satellite broadcasting[edit]

The demand for satellite transponder bandwidth continues to grow, fueled by the desire to deliver television (including new channels and high-definition television) and IP data. Transponder availability and bandwidth constraints have limited this growth. Transponder capacity is determined by the selected modulation scheme and the proportion of capacity consumed by FEC.

Data storage[edit]

Error detection and correction codes are often used to improve the reliability of data storage media.[19] A parity track capable of detecting single-bit errors was present on the first magnetic tape data storage in 1951. The optimal rectangular code used in group coded recording tapes not only detects but also corrects single-bit errors. Some file formats, particularly archive formats, include a checksum (most often CRC32) to detect corruption and truncation and can employ redundancy or parity files to recover portions of corrupted data. Reed-Solomon codes are used in compact discs to correct errors caused by scratches.

Modern hard drives use Reed–Solomon codes to detect and correct minor errors in sector reads, and to recover corrupted data from failing sectors and store that data in the spare sectors.[20] RAID systems use a variety of error correction techniques to recover data when a hard drive completely fails. Filesystems such as ZFS or Btrfs, as well as some RAID implementations, support data scrubbing and resilvering, which allows bad blocks to be detected and (hopefully) recovered before they are used.[21] The recovered data may be re-written to exactly the same physical location, to spare blocks elsewhere on the same piece of hardware, or the data may be rewritten onto replacement hardware.

Error-correcting memory[edit]

Dynamic random-access memory (DRAM) may provide stronger protection against soft errors by relying on error-correcting codes. Such error-correcting memory, known as ECC or EDAC-protected memory, is particularly desirable for mission-critical applications, such as scientific computing, financial, medical, etc. as well as extraterrestrial applications due to the increased radiation in space.

Error-correcting memory controllers traditionally use Hamming codes, although some use triple modular redundancy. Interleaving allows distributing the effect of a single cosmic ray potentially upsetting multiple physically neighboring bits across multiple words by associating neighboring bits to different words. As long as a single-event upset (SEU) does not exceed the error threshold (e.g., a single error) in any particular word between accesses, it can be corrected (e.g., by a single-bit error-correcting code), and the illusion of an error-free memory system may be maintained.[22]

In addition to hardware providing features required for ECC memory to operate, operating systems usually contain related reporting facilities that are used to provide notifications when soft errors are transparently recovered. One example is the Linux kernel’s EDAC subsystem (previously known as Bluesmoke), which collects the data from error-checking-enabled components inside a computer system; besides collecting and reporting back the events related to ECC memory, it also supports other checksumming errors, including those detected on the PCI bus.[23][24][25] A few systems[specify] also support memory scrubbing to catch and correct errors early before they become unrecoverable.

See also[edit]

  • Berger code
  • Burst error-correcting code
  • ECC memory, a type of computer data storage
  • Link adaptation
  • List of algorithms § Error detection and correction
  • List of hash functions

References[edit]

  1. ^ a b «Masorah». Jewish Encyclopedia.
  2. ^ Pratico, Gary D.; Pelt, Miles V. Van (2009). Basics of Biblical Hebrew Grammar: Second Edition. Zondervan. ISBN 978-0-310-55882-8.
  3. ^ Mounce, William D. (2007). Greek for the Rest of Us: Using Greek Tools Without Mastering Biblical Languages. Zondervan. p. 289. ISBN 978-0-310-28289-1.
  4. ^ Mishneh Torah, Tefillin, Mezuzah, and Sefer Torah, 1:2. Example English translation: Eliyahu Touger. The Rambam’s Mishneh Torah. Moznaim Publishing Corporation.
  5. ^ Brian M. Fagan (5 December 1996). «Dead Sea Scrolls». The Oxford Companion to Archaeology. Oxford University Press. ISBN 0195076184.
  6. ^ Thompson, Thomas M. (1983), From Error-Correcting Codes through Sphere Packings to Simple Groups, The Carus Mathematical Monographs (#21), The Mathematical Association of America, p. vii, ISBN 0-88385-023-0
  7. ^ Shannon, C.E. (1948), «A Mathematical Theory of Communication», Bell System Technical Journal, 27 (3): 379–423, doi:10.1002/j.1538-7305.1948.tb01338.x, hdl:10338.dmlcz/101429, PMID 9230594
  8. ^ Golay, Marcel J. E. (1949), «Notes on Digital Coding», Proc.I.R.E. (I.E.E.E.), 37: 657
  9. ^ Gupta, Vikas; Verma, Chanderkant (November 2012). «Error Detection and Correction: An Introduction». International Journal of Advanced Research in Computer Science and Software Engineering. 2 (11). S2CID 17499858.
  10. ^ a b A. J. McAuley, Reliable Broadband Communication Using a Burst Erasure Correcting Code, ACM SIGCOMM, 1990.
  11. ^ Shah, Pradeep M.; Vyavahare, Prakash D.; Jain, Anjana (September 2015). «Modern error correcting codes for 4G and beyond: Turbo codes and LDPC codes». 2015 Radio and Antenna Days of the Indian Ocean (RADIO): 1–2. doi:10.1109/RADIO.2015.7323369. ISBN 978-9-9903-7339-4. S2CID 28885076. Retrieved 22 May 2022.
  12. ^ «IEEE SA — IEEE 802.11ac-2013». IEEE Standards Association.
  13. ^ «Transition to Advanced Format 4K Sector Hard Drives | Seagate US». Seagate.com. Retrieved 22 May 2022.
  14. ^ Frank van Gerwen. «Numbers (and other mysterious) stations». Archived from the original on 12 July 2017. Retrieved 12 March 2012.
  15. ^ Gary Cutlack (25 August 2010). «Mysterious Russian ‘Numbers Station’ Changes Broadcast After 20 Years». Gizmodo. Retrieved 12 March 2012.
  16. ^ Ben-Gal I.; Herer Y.; Raz T. (2003). «Self-correcting inspection procedure under inspection errors» (PDF). IIE Transactions. IIE Transactions on Quality and Reliability, 34(6), pp. 529-540. Archived from the original (PDF) on 2013-10-13. Retrieved 2014-01-10.
  17. ^ K. Andrews et al., The Development of Turbo and LDPC Codes for Deep-Space Applications, Proceedings of the IEEE, Vol. 95, No. 11, Nov. 2007.
  18. ^ Huffman, William Cary; Pless, Vera S. (2003). Fundamentals of Error-Correcting Codes. Cambridge University Press. ISBN 978-0-521-78280-7.
  19. ^ Kurtas, Erozan M.; Vasic, Bane (2018-10-03). Advanced Error Control Techniques for Data Storage Systems. CRC Press. ISBN 978-1-4200-3649-7.[permanent dead link]
  20. ^ Scott A. Moulton. «My Hard Drive Died». Archived from the original on 2008-02-02.
  21. ^ Qiao, Zhi; Fu, Song; Chen, Hsing-Bung; Settlemyer, Bradley (2019). «Building Reliable High-Performance Storage Systems: An Empirical and Analytical Study». 2019 IEEE International Conference on Cluster Computing (CLUSTER): 1–10. doi:10.1109/CLUSTER.2019.8891006. ISBN 978-1-7281-4734-5. S2CID 207951690.
  22. ^ «Using StrongArm SA-1110 in the On-Board Computer of Nanosatellite». Tsinghua Space Center, Tsinghua University, Beijing. Archived from the original on 2011-10-02. Retrieved 2009-02-16.
  23. ^ Jeff Layton. «Error Detection and Correction». Linux Magazine. Retrieved 2014-08-12.
  24. ^ «EDAC Project». bluesmoke.sourceforge.net. Retrieved 2014-08-12.
  25. ^ «Documentation/edac.txt». Linux kernel documentation. kernel.org. 2014-06-16. Archived from the original on 2009-09-05. Retrieved 2014-08-12.

Further reading[edit]

  • Shu Lin; Daniel J. Costello, Jr. (1983). Error Control Coding: Fundamentals and Applications. Prentice Hall. ISBN 0-13-283796-X.
  • SoftECC: A System for Software Memory Integrity Checking
  • A Tunable, Software-based DRAM Error Detection and Correction Library for HPC
  • Detection and Correction of Silent Data Corruption for Large-Scale High-Performance Computing

External links[edit]

  • The on-line textbook: Information Theory, Inference, and Learning Algorithms, by David J.C. MacKay, contains chapters on elementary error-correcting codes; on the theoretical limits of error-correction; and on the latest state-of-the-art error-correcting codes, including low-density parity-check codes, turbo codes, and fountain codes.
  • ECC Page — implementations of popular ECC encoding and decoding routines

To clean up transmission errors introduced by Earth’s atmosphere (left), Goddard scientists applied Reed–Solomon error correction (right), which is commonly used in CDs and DVDs. Typical errors include missing pixels (white) and false signals (black). The white stripe indicates a brief period when transmission was interrupted.

In information theory and coding theory with applications in computer science and telecommunication, error detection and correction (EDAC) or error control are techniques that enable reliable delivery of digital data over unreliable communication channels. Many communication channels are subject to channel noise, and thus errors may be introduced during transmission from the source to a receiver. Error detection techniques allow detecting such errors, while error correction enables reconstruction of the original data in many cases.

Definitions[edit]

Error detection is the detection of errors caused by noise or other impairments during transmission from the transmitter to the receiver.

Error correction is the detection of errors and reconstruction of the original, error-free data.

History[edit]

In classical antiquity, copyists of the Hebrew Bible were paid for their work according to the number of stichs (lines of verse). As the prose books of the Bible were hardly ever written in stichs, the copyists, in order to estimate the amount of work, had to count the letters.[1] This also helped ensure accuracy in the transmission of the text with the production of subsequent copies.[2][3] Between the 7th and 10th centuries CE a group of Jewish scribes formalized and expanded this to create the Numerical Masorah to ensure accurate reproduction of the sacred text. It included counts of the number of words in a line, section, book and groups of books, noting the middle stich of a book, word use statistics, and commentary.[1] Standards became such that a deviation in even a single letter in a Torah scroll was considered unacceptable.[4] The effectiveness of their error correction method was verified by the accuracy of copying through the centuries demonstrated by discovery of the Dead Sea Scrolls in 1947–1956, dating from c.150 BCE-75 CE.[5]

The modern development of error correction codes is credited to Richard Hamming in 1947.[6] A description of Hamming’s code appeared in Claude Shannon’s A Mathematical Theory of Communication[7] and was quickly generalized by Marcel J. E. Golay.[8]

Introduction[edit]

All error-detection and correction schemes add some redundancy (i.e., some extra data) to a message, which receivers can use to check consistency of the delivered message, and to recover data that has been determined to be corrupted. Error-detection and correction schemes can be either systematic or non-systematic. In a systematic scheme, the transmitter sends the original data, and attaches a fixed number of check bits (or parity data), which are derived from the data bits by some deterministic algorithm. If only error detection is required, a receiver can simply apply the same algorithm to the received data bits and compare its output with the received check bits; if the values do not match, an error has occurred at some point during the transmission. In a system that uses a non-systematic code, the original message is transformed into an encoded message carrying the same information and that has at least as many bits as the original message.

Good error control performance requires the scheme to be selected based on the characteristics of the communication channel. Common channel models include memoryless models where errors occur randomly and with a certain probability, and dynamic models where errors occur primarily in bursts. Consequently, error-detecting and correcting codes can be generally distinguished between random-error-detecting/correcting and burst-error-detecting/correcting. Some codes can also be suitable for a mixture of random errors and burst errors.

If the channel characteristics cannot be determined, or are highly variable, an error-detection scheme may be combined with a system for retransmissions of erroneous data. This is known as automatic repeat request (ARQ), and is most notably used in the Internet. An alternate approach for error control is hybrid automatic repeat request (HARQ), which is a combination of ARQ and error-correction coding.

Types of error correction[edit]

There are three major types of error correction.[9]

Automatic repeat request[edit]

Automatic repeat request (ARQ) is an error control method for data transmission that makes use of error-detection codes, acknowledgment and/or negative acknowledgment messages, and timeouts to achieve reliable data transmission. An acknowledgment is a message sent by the receiver to indicate that it has correctly received a data frame.

Usually, when the transmitter does not receive the acknowledgment before the timeout occurs (i.e., within a reasonable amount of time after sending the data frame), it retransmits the frame until it is either correctly received or the error persists beyond a predetermined number of retransmissions.

Three types of ARQ protocols are Stop-and-wait ARQ, Go-Back-N ARQ, and Selective Repeat ARQ.

ARQ is appropriate if the communication channel has varying or unknown capacity, such as is the case on the Internet. However, ARQ requires the availability of a back channel, results in possibly increased latency due to retransmissions, and requires the maintenance of buffers and timers for retransmissions, which in the case of network congestion can put a strain on the server and overall network capacity.[10]

For example, ARQ is used on shortwave radio data links in the form of ARQ-E, or combined with multiplexing as ARQ-M.

Forward error correction[edit]

Forward error correction (FEC) is a process of adding redundant data such as an error-correcting code (ECC) to a message so that it can be recovered by a receiver even when a number of errors (up to the capability of the code being used) are introduced, either during the process of transmission or on storage. Since the receiver does not have to ask the sender for retransmission of the data, a backchannel is not required in forward error correction. Error-correcting codes are used in lower-layer communication such as cellular network, high-speed fiber-optic communication and Wi-Fi,[11][12] as well as for reliable storage in media such as flash memory, hard disk and RAM.[13]

Error-correcting codes are usually distinguished between convolutional codes and block codes:

  • Convolutional codes are processed on a bit-by-bit basis. They are particularly suitable for implementation in hardware, and the Viterbi decoder allows optimal decoding.
  • Block codes are processed on a block-by-block basis. Early examples of block codes are repetition codes, Hamming codes and multidimensional parity-check codes. They were followed by a number of efficient codes, Reed–Solomon codes being the most notable due to their current widespread use. Turbo codes and low-density parity-check codes (LDPC) are relatively new constructions that can provide almost optimal efficiency.

Shannon’s theorem is an important theorem in forward error correction, and describes the maximum information rate at which reliable communication is possible over a channel that has a certain error probability or signal-to-noise ratio (SNR). This strict upper limit is expressed in terms of the channel capacity. More specifically, the theorem says that there exist codes such that with increasing encoding length the probability of error on a discrete memoryless channel can be made arbitrarily small, provided that the code rate is smaller than the channel capacity. The code rate is defined as the fraction k/n of k source symbols and n encoded symbols.

The actual maximum code rate allowed depends on the error-correcting code used, and may be lower. This is because Shannon’s proof was only of existential nature, and did not show how to construct codes which are both optimal and have efficient encoding and decoding algorithms.

Hybrid schemes[edit]

Hybrid ARQ is a combination of ARQ and forward error correction. There are two basic approaches:[10]

  • Messages are always transmitted with FEC parity data (and error-detection redundancy). A receiver decodes a message using the parity information, and requests retransmission using ARQ only if the parity data was not sufficient for successful decoding (identified through a failed integrity check).
  • Messages are transmitted without parity data (only with error-detection information). If a receiver detects an error, it requests FEC information from the transmitter using ARQ, and uses it to reconstruct the original message.

The latter approach is particularly attractive on an erasure channel when using a rateless erasure code.

Error detection schemes[edit]

Error detection is most commonly realized using a suitable hash function (or specifically, a checksum, cyclic redundancy check or other algorithm). A hash function adds a fixed-length tag to a message, which enables receivers to verify the delivered message by recomputing the tag and comparing it with the one provided.

There exists a vast variety of different hash function designs. However, some are of particularly widespread use because of either their simplicity or their suitability for detecting certain kinds of errors (e.g., the cyclic redundancy check’s performance in detecting burst errors).

Minimum distance coding[edit]

A random-error-correcting code based on minimum distance coding can provide a strict guarantee on the number of detectable errors, but it may not protect against a preimage attack.

Repetition codes[edit]

A repetition code is a coding scheme that repeats the bits across a channel to achieve error-free communication. Given a stream of data to be transmitted, the data are divided into blocks of bits. Each block is transmitted some predetermined number of times. For example, to send the bit pattern «1011», the four-bit block can be repeated three times, thus producing «1011 1011 1011». If this twelve-bit pattern was received as «1010 1011 1011» – where the first block is unlike the other two – an error has occurred.

A repetition code is very inefficient, and can be susceptible to problems if the error occurs in exactly the same place for each group (e.g., «1010 1010 1010» in the previous example would be detected as correct). The advantage of repetition codes is that they are extremely simple, and are in fact used in some transmissions of numbers stations.[14][15]

Parity bit[edit]

A parity bit is a bit that is added to a group of source bits to ensure that the number of set bits (i.e., bits with value 1) in the outcome is even or odd. It is a very simple scheme that can be used to detect single or any other odd number (i.e., three, five, etc.) of errors in the output. An even number of flipped bits will make the parity bit appear correct even though the data is erroneous.

Parity bits added to each «word» sent are called transverse redundancy checks, while those added at the end of a stream of «words» are called longitudinal redundancy checks. For example, if each of a series of m-bit «words» has a parity bit added, showing whether there were an odd or even number of ones in that word, any word with a single error in it will be detected. It will not be known where in the word the error is, however. If, in addition, after each stream of n words a parity sum is sent, each bit of which shows whether there were an odd or even number of ones at that bit-position sent in the most recent group, the exact position of the error can be determined and the error corrected. This method is only guaranteed to be effective, however, if there are no more than 1 error in every group of n words. With more error correction bits, more errors can be detected and in some cases corrected.

There are also other bit-grouping techniques.

Checksum[edit]

A checksum of a message is a modular arithmetic sum of message code words of a fixed word length (e.g., byte values). The sum may be negated by means of a ones’-complement operation prior to transmission to detect unintentional all-zero messages.

Checksum schemes include parity bits, check digits, and longitudinal redundancy checks. Some checksum schemes, such as the Damm algorithm, the Luhn algorithm, and the Verhoeff algorithm, are specifically designed to detect errors commonly introduced by humans in writing down or remembering identification numbers.

Cyclic redundancy check[edit]

A cyclic redundancy check (CRC) is a non-secure hash function designed to detect accidental changes to digital data in computer networks. It is not suitable for detecting maliciously introduced errors. It is characterized by specification of a generator polynomial, which is used as the divisor in a polynomial long division over a finite field, taking the input data as the dividend. The remainder becomes the result.

A CRC has properties that make it well suited for detecting burst errors. CRCs are particularly easy to implement in hardware and are therefore commonly used in computer networks and storage devices such as hard disk drives.

The parity bit can be seen as a special-case 1-bit CRC.

Cryptographic hash function[edit]

The output of a cryptographic hash function, also known as a message digest, can provide strong assurances about data integrity, whether changes of the data are accidental (e.g., due to transmission errors) or maliciously introduced. Any modification to the data will likely be detected through a mismatching hash value. Furthermore, given some hash value, it is typically infeasible to find some input data (other than the one given) that will yield the same hash value. If an attacker can change not only the message but also the hash value, then a keyed hash or message authentication code (MAC) can be used for additional security. Without knowing the key, it is not possible for the attacker to easily or conveniently calculate the correct keyed hash value for a modified message.

Error correction code[edit]

Any error-correcting code can be used for error detection. A code with minimum Hamming distance, d, can detect up to d − 1 errors in a code word. Using minimum-distance-based error-correcting codes for error detection can be suitable if a strict limit on the minimum number of errors to be detected is desired.

Codes with minimum Hamming distance d = 2 are degenerate cases of error-correcting codes, and can be used to detect single errors. The parity bit is an example of a single-error-detecting code.

Applications[edit]

Applications that require low latency (such as telephone conversations) cannot use automatic repeat request (ARQ); they must use forward error correction (FEC). By the time an ARQ system discovers an error and re-transmits it, the re-sent data will arrive too late to be usable.

Applications where the transmitter immediately forgets the information as soon as it is sent (such as most television cameras) cannot use ARQ; they must use FEC because when an error occurs, the original data is no longer available.

Applications that use ARQ must have a return channel; applications having no return channel cannot use ARQ.

Applications that require extremely low error rates (such as digital money transfers) must use ARQ due to the possibility of uncorrectable errors with FEC.

Reliability and inspection engineering also make use of the theory of error-correcting codes.[16]

Internet[edit]

In a typical TCP/IP stack, error control is performed at multiple levels:

  • Each Ethernet frame uses CRC-32 error detection. Frames with detected errors are discarded by the receiver hardware.
  • The IPv4 header contains a checksum protecting the contents of the header. Packets with incorrect checksums are dropped within the network or at the receiver.
  • The checksum was omitted from the IPv6 header in order to minimize processing costs in network routing and because current link layer technology is assumed to provide sufficient error detection (see also RFC 3819).
  • UDP has an optional checksum covering the payload and addressing information in the UDP and IP headers. Packets with incorrect checksums are discarded by the network stack. The checksum is optional under IPv4, and required under IPv6. When omitted, it is assumed the data-link layer provides the desired level of error protection.
  • TCP provides a checksum for protecting the payload and addressing information in the TCP and IP headers. Packets with incorrect checksums are discarded by the network stack, and eventually get retransmitted using ARQ, either explicitly (such as through three-way handshake) or implicitly due to a timeout.

Deep-space telecommunications[edit]

The development of error-correction codes was tightly coupled with the history of deep-space missions due to the extreme dilution of signal power over interplanetary distances, and the limited power availability aboard space probes. Whereas early missions sent their data uncoded, starting in 1968, digital error correction was implemented in the form of (sub-optimally decoded) convolutional codes and Reed–Muller codes.[17] The Reed–Muller code was well suited to the noise the spacecraft was subject to (approximately matching a bell curve), and was implemented for the Mariner spacecraft and used on missions between 1969 and 1977.

The Voyager 1 and Voyager 2 missions, which started in 1977, were designed to deliver color imaging and scientific information from Jupiter and Saturn.[18] This resulted in increased coding requirements, and thus, the spacecraft were supported by (optimally Viterbi-decoded) convolutional codes that could be concatenated with an outer Golay (24,12,8) code. The Voyager 2 craft additionally supported an implementation of a Reed–Solomon code. The concatenated Reed–Solomon–Viterbi (RSV) code allowed for very powerful error correction, and enabled the spacecraft’s extended journey to Uranus and Neptune. After ECC system upgrades in 1989, both crafts used V2 RSV coding.

The Consultative Committee for Space Data Systems currently recommends usage of error correction codes with performance similar to the Voyager 2 RSV code as a minimum. Concatenated codes are increasingly falling out of favor with space missions, and are replaced by more powerful codes such as Turbo codes or LDPC codes.

The different kinds of deep space and orbital missions that are conducted suggest that trying to find a one-size-fits-all error correction system will be an ongoing problem. For missions close to Earth, the nature of the noise in the communication channel is different from that which a spacecraft on an interplanetary mission experiences. Additionally, as a spacecraft increases its distance from Earth, the problem of correcting for noise becomes more difficult.

Satellite broadcasting[edit]

The demand for satellite transponder bandwidth continues to grow, fueled by the desire to deliver television (including new channels and high-definition television) and IP data. Transponder availability and bandwidth constraints have limited this growth. Transponder capacity is determined by the selected modulation scheme and the proportion of capacity consumed by FEC.

Data storage[edit]

Error detection and correction codes are often used to improve the reliability of data storage media.[19] A parity track capable of detecting single-bit errors was present on the first magnetic tape data storage in 1951. The optimal rectangular code used in group coded recording tapes not only detects but also corrects single-bit errors. Some file formats, particularly archive formats, include a checksum (most often CRC32) to detect corruption and truncation and can employ redundancy or parity files to recover portions of corrupted data. Reed-Solomon codes are used in compact discs to correct errors caused by scratches.

Modern hard drives use Reed–Solomon codes to detect and correct minor errors in sector reads, and to recover corrupted data from failing sectors and store that data in the spare sectors.[20] RAID systems use a variety of error correction techniques to recover data when a hard drive completely fails. Filesystems such as ZFS or Btrfs, as well as some RAID implementations, support data scrubbing and resilvering, which allows bad blocks to be detected and (hopefully) recovered before they are used.[21] The recovered data may be re-written to exactly the same physical location, to spare blocks elsewhere on the same piece of hardware, or the data may be rewritten onto replacement hardware.

Error-correcting memory[edit]

Dynamic random-access memory (DRAM) may provide stronger protection against soft errors by relying on error-correcting codes. Such error-correcting memory, known as ECC or EDAC-protected memory, is particularly desirable for mission-critical applications, such as scientific computing, financial, medical, etc. as well as extraterrestrial applications due to the increased radiation in space.

Error-correcting memory controllers traditionally use Hamming codes, although some use triple modular redundancy. Interleaving allows distributing the effect of a single cosmic ray potentially upsetting multiple physically neighboring bits across multiple words by associating neighboring bits to different words. As long as a single-event upset (SEU) does not exceed the error threshold (e.g., a single error) in any particular word between accesses, it can be corrected (e.g., by a single-bit error-correcting code), and the illusion of an error-free memory system may be maintained.[22]

In addition to hardware providing features required for ECC memory to operate, operating systems usually contain related reporting facilities that are used to provide notifications when soft errors are transparently recovered. One example is the Linux kernel’s EDAC subsystem (previously known as Bluesmoke), which collects the data from error-checking-enabled components inside a computer system; besides collecting and reporting back the events related to ECC memory, it also supports other checksumming errors, including those detected on the PCI bus.[23][24][25] A few systems[specify] also support memory scrubbing to catch and correct errors early before they become unrecoverable.

See also[edit]

  • Berger code
  • Burst error-correcting code
  • ECC memory, a type of computer data storage
  • Link adaptation
  • List of algorithms § Error detection and correction
  • List of hash functions

References[edit]

  1. ^ a b «Masorah». Jewish Encyclopedia.
  2. ^ Pratico, Gary D.; Pelt, Miles V. Van (2009). Basics of Biblical Hebrew Grammar: Second Edition. Zondervan. ISBN 978-0-310-55882-8.
  3. ^ Mounce, William D. (2007). Greek for the Rest of Us: Using Greek Tools Without Mastering Biblical Languages. Zondervan. p. 289. ISBN 978-0-310-28289-1.
  4. ^ Mishneh Torah, Tefillin, Mezuzah, and Sefer Torah, 1:2. Example English translation: Eliyahu Touger. The Rambam’s Mishneh Torah. Moznaim Publishing Corporation.
  5. ^ Brian M. Fagan (5 December 1996). «Dead Sea Scrolls». The Oxford Companion to Archaeology. Oxford University Press. ISBN 0195076184.
  6. ^ Thompson, Thomas M. (1983), From Error-Correcting Codes through Sphere Packings to Simple Groups, The Carus Mathematical Monographs (#21), The Mathematical Association of America, p. vii, ISBN 0-88385-023-0
  7. ^ Shannon, C.E. (1948), «A Mathematical Theory of Communication», Bell System Technical Journal, 27 (3): 379–423, doi:10.1002/j.1538-7305.1948.tb01338.x, hdl:10338.dmlcz/101429, PMID 9230594
  8. ^ Golay, Marcel J. E. (1949), «Notes on Digital Coding», Proc.I.R.E. (I.E.E.E.), 37: 657
  9. ^ Gupta, Vikas; Verma, Chanderkant (November 2012). «Error Detection and Correction: An Introduction». International Journal of Advanced Research in Computer Science and Software Engineering. 2 (11). S2CID 17499858.
  10. ^ a b A. J. McAuley, Reliable Broadband Communication Using a Burst Erasure Correcting Code, ACM SIGCOMM, 1990.
  11. ^ Shah, Pradeep M.; Vyavahare, Prakash D.; Jain, Anjana (September 2015). «Modern error correcting codes for 4G and beyond: Turbo codes and LDPC codes». 2015 Radio and Antenna Days of the Indian Ocean (RADIO): 1–2. doi:10.1109/RADIO.2015.7323369. ISBN 978-9-9903-7339-4. S2CID 28885076. Retrieved 22 May 2022.
  12. ^ «IEEE SA — IEEE 802.11ac-2013». IEEE Standards Association.
  13. ^ «Transition to Advanced Format 4K Sector Hard Drives | Seagate US». Seagate.com. Retrieved 22 May 2022.
  14. ^ Frank van Gerwen. «Numbers (and other mysterious) stations». Archived from the original on 12 July 2017. Retrieved 12 March 2012.
  15. ^ Gary Cutlack (25 August 2010). «Mysterious Russian ‘Numbers Station’ Changes Broadcast After 20 Years». Gizmodo. Retrieved 12 March 2012.
  16. ^ Ben-Gal I.; Herer Y.; Raz T. (2003). «Self-correcting inspection procedure under inspection errors» (PDF). IIE Transactions. IIE Transactions on Quality and Reliability, 34(6), pp. 529-540. Archived from the original (PDF) on 2013-10-13. Retrieved 2014-01-10.
  17. ^ K. Andrews et al., The Development of Turbo and LDPC Codes for Deep-Space Applications, Proceedings of the IEEE, Vol. 95, No. 11, Nov. 2007.
  18. ^ Huffman, William Cary; Pless, Vera S. (2003). Fundamentals of Error-Correcting Codes. Cambridge University Press. ISBN 978-0-521-78280-7.
  19. ^ Kurtas, Erozan M.; Vasic, Bane (2018-10-03). Advanced Error Control Techniques for Data Storage Systems. CRC Press. ISBN 978-1-4200-3649-7.[permanent dead link]
  20. ^ Scott A. Moulton. «My Hard Drive Died». Archived from the original on 2008-02-02.
  21. ^ Qiao, Zhi; Fu, Song; Chen, Hsing-Bung; Settlemyer, Bradley (2019). «Building Reliable High-Performance Storage Systems: An Empirical and Analytical Study». 2019 IEEE International Conference on Cluster Computing (CLUSTER): 1–10. doi:10.1109/CLUSTER.2019.8891006. ISBN 978-1-7281-4734-5. S2CID 207951690.
  22. ^ «Using StrongArm SA-1110 in the On-Board Computer of Nanosatellite». Tsinghua Space Center, Tsinghua University, Beijing. Archived from the original on 2011-10-02. Retrieved 2009-02-16.
  23. ^ Jeff Layton. «Error Detection and Correction». Linux Magazine. Retrieved 2014-08-12.
  24. ^ «EDAC Project». bluesmoke.sourceforge.net. Retrieved 2014-08-12.
  25. ^ «Documentation/edac.txt». Linux kernel documentation. kernel.org. 2014-06-16. Archived from the original on 2009-09-05. Retrieved 2014-08-12.

Further reading[edit]

  • Shu Lin; Daniel J. Costello, Jr. (1983). Error Control Coding: Fundamentals and Applications. Prentice Hall. ISBN 0-13-283796-X.
  • SoftECC: A System for Software Memory Integrity Checking
  • A Tunable, Software-based DRAM Error Detection and Correction Library for HPC
  • Detection and Correction of Silent Data Corruption for Large-Scale High-Performance Computing

External links[edit]

  • The on-line textbook: Information Theory, Inference, and Learning Algorithms, by David J.C. MacKay, contains chapters on elementary error-correcting codes; on the theoretical limits of error-correction; and on the latest state-of-the-art error-correcting codes, including low-density parity-check codes, turbo codes, and fountain codes.
  • ECC Page — implementations of popular ECC encoding and decoding routines

Предупреждение,
обнаружение, исправление ошибок,
обеспечение устойчивости к ошибкам.
Тестирование, доказательство, контроль,
испытание, аттестация, отладка.

ПРОВЕРКА
ПРАВИЛЬНОСТИ ПРОГРАММ.

Программу
нельзя использовать до тех пор, пока не
будет уверенности в ее надежности.
Надежность — это свойство программы,
более строгое, чем корректность, поскольку
программа может быть корректной, но не
быть надежной. Программа является
корректной, если удовлетворяет внешним
спецификациям, т.е. выдает ожидаемые
ответы на определенные комбинации
значений входных данных. Программа
является надежной, если она корректна,
приемлемо реагирует на неточные входные
данные и удовлетворительно функционирует
в необычных условиях.

В
процессе создания программы программист
старается предвидеть все возможные
ситуации и написать программу так, чтобы
она реагировала на них вполне
удовлетворительно. Этап тестирования
является последней попыткой определить
надежность и корректность программы.
Проверка надежности включает в себя
просмотр проектной документации и
текста программы, анализ текста программы,
тестирование и, наконец, демонстрацию
заказчику того, что программа работает
надежно.

Все
принципы и методы разработки надежного
программного обеспечения можно разбить
на четыре группы:

1.
Предупреждение ошибок.

2.
Обнаружение ошибок.

3.
Исправление ошибок.

4.
Обеспечение устойчивости к ошибкам.

Предупреждение
ошибок
.
К этой группе относятся принципы и
методы, цель которых — не допустить
появление ошибок в готовой программе.
Большинство методов концентрируется
на отдельных процессах перевода и
направлено на предупреждение ошибок в
этих процессах (упрощение программ,
достижение большей точности при переводе,
немедленное обнаружение и устранение
ошибок).

Обнаружение
ошибок
.
Если предполагать, что в программном
обеспечении какие-то ошибки все же
будут, то лучшая стратегия в этом случае
— включить средства обнаружения ошибок
в само программное обеспечение.
Немедленное обнаружение имеет два
преимущества: можно минимизировать как
влияние ошибки, так и последующие
затруднения для человека, которому
придется извлекать информацию об этой
ошибке, находить ее место и исправлять.

Исправление
ошибок
.
После того, как ошибка обнаружена, либо
она сама, либо ее последствия должны
быть исправлены программным обеспечением.
Некоторые устройства способны обнаружить
неисправные компоненты и перейти к
использованию резервных. Другой метод
— восстановление информации (например,
при сбое питания).

Устойчивость
к ошибкам
.
Методы этой группы ставят своей целью
обеспечит функционирование программной
системы при наличии в ней ошибок. Они
разбиваются на три подгруппы: динамическая
избыточность (методы голосования,
резервных копий); методы отступления
(когда необходимо корректно закончить
работу — например, закрыть базу данных);
изоляция ошибок (основная идея — не дать
последствиям ошибки выйти за пределы
как можно меньшей части системы
программного обеспечения, так, чтобы
если ошибка возникнет, то не вся система
оказалась бы неработоспособной).

8.1.
Основные определения.

Тестирование
— процесс выполнения программы с
намерением найти ошибки. Если Ваша цель
— показать отсутствие ошибок, Вы их
найдете не слишком много. Если же Ваша
цель — показать наличие ошибок, Вы найдете
значительную их часть.

Доказательство
— попытка найти ошибки в программе
безотносительно к внешней для программы
среде. Большинство методов доказательства
предполагает формулировку утверждений
о поведении программы и затем вывод и
доказательство математических теорем
о правильности программы. Доказательства
могут рассматриваться как форма
тестирования, хотя они и не предполагают
прямого выполнения программы.

Контроль
— попытка найти ошибки, выполняя программу
в тестовой, или моделируемой, среде.

Испытание
— попытка найти ошибки, выполняя программу
в заданной реальной среде.

Аттестация
— авторитетное подтверждение правильности
программы. При тестировании с целью
аттестации выполняется сравнение с
некоторым заранее определенным
стандартом.

Отладка
— не является разновидностью тестирования.
Хотя слова «отладка» и «тестирование»
часто используются как синонимы, под
ними подразумеваются разные виды
деятельности. Тестирование — деятельность,
направленная на обнаружение ошибок;
отладка направлена на установление
точной природы известной ошибки, а затем
— на исправление этой ошибки. Эти два
вида деятельности связаны — результаты
тестирования являются исходными данными
для отладки.

Тестирование
модуля, или автономное тестирование —
контроль отдельного программного
модуля, обычно в изолированной среде.
Тестирование модуля иногда включает
также математическое доказательство.

Тестирование
сопряжений — контроль сопряжений между
частями системы (модулями, компонентами,
подсистемами).

Тестирование
внешних функций — контроль внешнего
поведения системы, определенного
внешними спецификациями.

Комплексное
тестирование — контроль и испытание
системы по отношению к исходным целям.
Комплексное тестирование является
процессом испытания, если выполняется
в среде реальной, жизненной.

Тестирование
приемлемости — проверка соответствия
программы требованиям пользователя.

Тестирование
настройки — проверка соответствия
каждого конкретного варианта установки
системы с целью выявить любые ошибки,
возникшие в процессе настройки системы.

8.2.
Базовые правила тестирования.

Обсудим
некоторые из важнейших аксиом тестирования.
они приведены в настоящем разделе и
являются фундаментальными принципами
тестирования.

Хорош
тот тест, для которого высока вероятность
обнаружить ошибку, а не тот, который
демонстрирует правильную работу
программы. Поскольку невозможно показать,
что программа не имеет ошибок и, значит,
все такие попытки бесплодны, процесс
тестирования должен представлять собой
попытки обнаружить а программе прежде
не найденные ошибки.

Одна
из самых сложных проблем при тестировании
— решить, когда нужно закончить. Как уже
говорилось, исчерпывающее тестирование
(т.е. испытание всех входных значений)
невозможно. Таким образом, при тестировании
мы сталкиваемся с экономической
проблемой: как выбрать конечное число
тестов, которое дает максимальную отдачу
(вероятность обнаружения ошибок) для
данных затрат. Известно слишком много
случаев, когда написанные тесты имели
крайне малую вероятность обнаружения
новых ошибок, в то время как довольно
очевидные хорошие тесты оставались
незамеченными.

Невозможно
тестировать свою собственную программу.
Ни один программист не должен пытаться
тестировать свою собственную программу.
Тестирование должно быть в высшей
степени разрушительным процессом, но
имеются глубокие психологические
причины, по которым программист не может
относится к своей программе как
разрушитель.

Необходимая
часть всякого теста — описание ожидаемых
выходных данных или результатов. Одна
из самых распространенных ошибок при
тестировании состоит в том, что результаты
каждого теста не прогнозируются до его
выполнения. Ожидаемые результаты нужно
определять заранее, чтобы не возникла
ситуация, когда «глаз видит то, что
хочет увидеть». Чтобы совсем исключить
такую возможность, лучше разрабатывать
самопроверяющиеся тесты, либо пользоваться
инструментами тестирования, способными
автоматически сверять ожидаемые и
фактические результаты.

Избегайте
невоспроизводимых тестов, не тестируйте
«с лету». В условиях диалога
программист слишком часто выполняет
тестирование «с лету», т.е., сидя за
терминалом, задает конкретные значения
и выполняет программу, чтобы посмотреть,
что получится. Это -неряшливая и
нежелательная форма тестирования.
Основной ее недостаток в том, что такие
тесты мимолетны; они исчезают по окончании
их выполнения. Никогда не используйте
тестов, которые тут же выбрасываются.

Готовьте
тесты как для правильных, так и для
неправильных входных данных. Многие
программисты ориентируются в своих
тестах на «разумные» условия на
входе, забывая о последствиях появления
непредусмотренных или ошибочных входных
данных. Однако многие ошибки, которые
потом неожиданно обнаруживаются в
работающих программах, проявляются
вследствии никак не предусмотренных
действий пользователя программы. Тесты,
представляющие неожиданные или
неправильные входные данные, часто
лучше обнаруживают ошибки, чем «правильные»
тесты.

Детально
изучите результаты каждого теста. Самые
изощренные тесты ничего не стоят, если
их результаты удостаиваются лишь беглого
взгляда. Тестирование программы означает
большее, нежели выполнение достаточного
количества тестов; оно также предполагает
изучение результатов каждого теста.

По
мере того как число ошибок, обнаруженных
в некоторой компоненте программного
обеспечения увеличивается, растет также
относительная вероятность существования
в ней необнаруженных ошибок. Этот феномен
наблюдался во многих системах. Его
понимание способно повысить качество
тестирования, обеспечивая обратную
связь между результатами прогона тестов
и их проектированием. Если конкретная
часть системы окажется при тестировании
полной ошибок, для нее следует подготовить
дополнительные тесты.

Поручайте
тестирование самым способным программистам.
Тестирование, и в особенности проектирование
тестов, — этап в разработке программного
обеспечения, требующий особенно
творческого подхода. К сожалению, во
многих организациях на тестирование
смотрят совсем не так. Его часто считают
рутинной, нетворческой работой. Однако
практика показывает, что проектирование
тестов требует даже больше творчества,
чем разработка архитектуры и проектирование
программного обеспечения.

Считайте
тестируемость ключевой задачей Вашей
разработки. Хотя «тестируемость»
и не фигурировала явно в «проектных»
главах, сложность тестирования программы
напрямую зависит от ее структуры и
качества проектирования. Несмотря на
то, что эта связь осознана еще недостаточно
глубоко, можно утверждать, что многие
характеристики хорошего проекта
(например, небольшие, в значительной
степени независимые модули и независимые
подсистемы), улучшают и тестируемость
программы.

Никогда
не изменяйте программу, чтобы облегчить
ее тестируемость. Часто возникает
соблазн изменить программу, чтобы было
легче ее тестировать. Например,
программист, тестируя модуль, содержащий
цикл, который должен повторяться 100 раз,
меняет его так, чтобы цикл повторялся
только 10 раз.

8.3.
Отладка.

Рекомендуемый
подход к методам отладки аналогичен
особенностям проектирования и включает
в себя следующие этапы:

1.
Поймите задачу. Многие программисты
начинают процесс отладки бессистемно,
пропуская жизненно важный этап детального
анализа имеющихся данных. Первым делом
нужно тщательно исследовать, что в
программе выполнено правильно, а что —
неправильно, чтобы выработать одну или
несколько гипотез о природе ошибки.
Одна из самых распространенных причин
затруднений при отладке — не учтен
какой-нибудь существенный фактор в
выходных данных программы. Важно
исследовать данные в поисках противоречий
гипотезе (например, ошибка возникает
только в каждой второй записи), потому
что это поведет к уточнению гипотезы
или, возможно, покажет, что имеется не
одна причина ошибки.

2.
Разработайте план. Следующий шаг —
построить одну или несколько гипотез
об ошибке и разработать план проверки
этих гипотез.

3.
Выполните план. Следуя своему плану,
пытайтесь доказать гипотезу. Если план
включает несколько шагов, нужно проверить
каждый.

4.
Проверьте решение. Если кажется, что
точное местоположение ошибки обнаружено,
необходимо выполнить еще несколько
проверок, прежде чем пытаться исправить
ошибку. Проанализируйте, может ли
предполагаемая ошибка давать в точности
известные симптомы. Убедитесь, что
найденная причина полностью объясняет
все симптомы, а не только их часть.
Проверьте, не вызовет ли ее исправление
новой ошибки.

Главная
причина затруднений при отладке — такая
психологическая установка, когда разум
видит то, что он ожидает увидеть, а совсем
не то, что имеет место в действительности.
Один из способов преодоления такой
установки — скептицизм в отношении
всего, что Вы изучаете, в особенности
комментариев и документации. Опытные
специалисты по отладке, изучая модуль,
часто закрывают комментарии, поскольку
комментарии нередко описывают, что
программа делает, по мнению ее создателя.
Обратный просмотр (чтение программы в
обратном направлении) — еще один полезный
тактический прием, поскольку он помогает
по-новому взглянуть на алгоритм.

Еще
одна трудность при отладке — такое
состояние, когда все идеи зашли в тупик
и найти местоположение ошибки кажется
просто невозможно. Это означает, что Вы
либо смотрите не туда, куда нужно, и
следует еще раз изучить симптомы и
построить новую гипотезу, либо подозрения
правильные, но разум уже не способен
заметить ошибку. Если кажется, что именно
так и есть , то лучший принцип — «утро
вечера мудренее». Переключите внимание
на другую деятельность, и пусть над
задачей работает Ваше подсознание.
Многие программисты признают, что самые
трудные свои задачи они решают во время
бритья или по дороге на работу.

Когда
Вы найдете и проверите ошибку и убедитесь
в том, что нашли ее правильно, не забудьте
о том, что вероятность других ошибок в
этой части программы теперь выше. Изучите
программу в окрестности найденной
ошибки в поисках новых неприятностей.
Проверьте, не была ли сделана такая же
ошибка в других местах программы.

Исследования
методов отладки вначале концентрировались
на сравнении отладки в пакетном и
диалоговом режимах, причем большинство
исследований приходило к выводу, что
диалоговый режим предпочтительнее.
Однако более поздняя работа показала,
что, вероятно, наилучший способ отладки
— просто читать программу и изо всех сил
стараться вникнуть в алгоритм, хотя это
требует усердия и собранности.

Важно
подчеркнуть, что многие из методов
проектирования помогают и в процессе
отладки, такие методы, как структурное
программирование и хороший стиль
программирования не только уменьшают
исходное количество ошибок, но и облегчают
отладку, делая программу более простой
для понимания.

После
того, как точно установлено, где находится
ошибка, надо ее исправить. Самая большая
трудность на этом шаге — суметь охватить
проблему целиком; самая распространенная
неприятность — устранить только некоторые
симптомы ошибки. Избегайте «экспериментальных»
исправлений; они показывают, что Вы еще
недостаточно подготовлены к отладке
этой программы, поскольку не понимаете
ее.

В
деле исправления ошибок очень важно
понимать, что оно возвращает нас назад,
к стадии проектирования. Обидно, если
после завершения хорошо организованного
проектирования весь его строгий порядок
нарушается, когда вносятся поправки.
Исправления должны выполняться по
крайней мере так же строго, как
первоначальное выполнение программы.
Если необходимо, следует обновить
документацию, поправки должны проходить
сквозной структурный контроль или
другие формы контрольного чтения
программы. Ни одна поправка не «мала»
настолько, чтобы не нуждаться в
тестировании.

По
самой своей природе исправления всегда
имеют некоторое отрицательное влияние
на структуру программы и легкость ее
чтения. Тот факт, что они делаются в
условиях жесткого давления, усиливает
это влияние. Опыт показывает, что при
исправлении довольно высока вероятность
внесения в программу новой ошибки
(обычно от 20 до 50).
Из этого следует, что отладка должна
выполняться лучшими программистами
проекта.

Изучение
процесса отладки.

Один
из лучших способов повысить надежность
программного обеспечения в нынешних
или в будущих проектах — очевидный, но
часто упускаемый из виду процесс обучения
на сделанных ошибках. Каждую ошибку
следует внимательно изучить, чтобы
понять, почему она возникла и что должно
было бы сделано, чтобы ее предотвратить
или обнаружить раньше. Редко можно
встретить программиста или организацию,
которые выполняли бы такой полезный
анализ, а когда он проводится, то обычно
имеет поверхностный характер и сводится,
например, к классификации ошибок: ошибки
проектирования, логические ошибки,
ошибки сопряжения или другие, не имеющие
особого смысла категории.

Нужно
уделять время изучению природы каждой
обнаруженной ошибки. Необходимо
подчеркнуть, что анализ ошибок должен
быть в значительной мере качественным
и не сводиться просто к упражнению в
количественном подсчете. Чтобы понять
причины , лежащие в основе ошибок, и
усовершенствовать процессы проектирования
и тестирования, нужно ответить на
следующие вопросы:

1.
Почему возникла именно такая ошибка? В
ответе должны быть указаны как
первоисточник, так и непосредственный
источник ошибки. Например, ошибка могла
быть сделана при программировании
конкретного модуля, но в ее основе могла
лежать неоднозначность в спецификациях
или исправление другой ошибки.

2.
Как и когда ошибка была обнаружена?
Поскольку мы только что добились
значительного успеха, почему бы нам не
воспользоваться приобретенным опытом?

3.
Почему эта ошибка не была обнаружена
при проектировании, контроле или на
предыдущей фазе тестирования?

4.
Что следовало сделать при проектировании
или тестировании, чтобы предупредить
появление этой ошибки или обнаружить
ее раньше?

Собирать
эту информацию нужно не только для того,
чтобы учиться на ошибках. Официально
отчетность об ошибках и об их исправлении
необходима и для того, чтобы гарантировать,
что обнаруженные ошибки в работающих
или тестируемых системах не упущены и
что исправления выполнены в соответствии
с принятыми нормами.

Другой
способ обучения на ошибках в программном
обеспечении — учиться на опыте других
организаций. К сожалению, это не жизненный
вариант, поскольку даже в лучшие времена
научного книгоиздания, такие материалы
если и встречались то крайне редко.

1. Методы и способы идентификации сбоев и ошибок

2.

Международный стандарт ANSI/IEEE-729-83
разделяет все ошибки в разработке программ на
следующие типы.
• Ошибка (error) — состояние программы, при
котором выдаются неправильные результаты,
причиной которых являются изъяны (flaw) в
операторах программы или в технологическом
процессе ее разработки, что приводит к
неправильной
интерпретации
исходной
информации, следовательно, и к неверному
решению.

3.

• Дефект (fault) в программе — следствие ошибок
разработчика на любом из этапов разработки,
которая может содержаться в исходных или
проектных
спецификациях,
текстах
кодов
программ, эксплуатационной документация и т.п. В
процессе выполнения программы может быть
обнаружен дефект или сбой.
• Отказ (failure) — это отклонение программы от
функционирования или невозможность программы
выполнять функции, определенные требованиями и
ограничениями, что рассматривается как событие,
способствующее
переходу
программы
в
неработоспособное состояние из-за ошибок,
скрытых в ней дефектов или сбоев в среде
функционирования.

4.

Отказ может быть результатом следующих причин:
• ошибочная спецификация или пропущенное требование,
означающее, что спецификация точно не отражает того,
что предполагал пользователь;
• спецификация может содержать требование, которое
невозможно выполнить на данной аппаратуре и
программном обеспечении;
• проект программы может содержать ошибки (например,
база данных спроектирована без средств защиты от
несанкционированного доступа пользователя, а требуется
защита);
• программа может быть неправильной, т.е. она выполняет
несвойственный алгоритм или он реализован не
полностью.
Таким образом, отказы, как правило, являются результатами
одной или более ошибок в программе, а также наличия
разного рода дефектов.

5. Ошибки на этапах процесса тестирования.

Приведенные типы ошибок распределяются по этапам ЖЦ
и им соответствуют такие источники их возникновения:
• непреднамеренное отклонение разработчиков от
рабочих стандартов или планов реализации;
• спецификации функциональных и интерфейсных
требований выполнены без соблюдения стандартов
разработки, что приводит к нарушению
функционирования программ;
• организации процесса разработки — несовершенная или
недостаточное управление руководителем проекта
ресурсами (человеческими, техническими,
программными и т.д.) и вопросами тестирования и
интеграции элементов проекта.

6. Рассмотрим процесс тестирования, исходя из рекомендаций стандарта ISO/IEC 12207, и приведем типы ошибок, которые обнаруживаются

на каждом процессе ЖЦ.
Процесс разработки требований. При определении исходной
концепции системы и исходных требований к системе возникают
ошибки аналитиков при спецификации верхнего уровня системы и
построении концептуальной модели предметной области.
Характерными ошибками этого процесса являются:
• неадекватность
спецификации
требований
конечным
пользователям;
некорректность
спецификации
взаимодействия ПО со средой функционирования или с
пользователями;
• несоответствие требований заказчика к отдельным и общим
свойствам ПО;
• некорректность описания функциональных характеристик;
• необеспеченность инструментальными средствами всех
аспектов реализации требований заказчика и др.

7. Процесс проектирования

• Ошибки при проектировании компонентов
могут возникать при описании алгоритмов,
логики управления, структур данных,
интерфейсов, логики моделирования
потоков данных, форматов ввода-вывода и
др. В основе этих ошибок лежат дефекты
спецификаций аналитиков и недоработки
проектировщиков.

8.

К ним относятся ошибки, связанные:
• с определением интерфейса пользователя со средой;
• с описанием функций (неадекватность целей и задач
компонентов, которые обнаруживаются при проверке
комплекса компонентов);
• с определением процесса обработки информации и
взаимодействия
между
процессами
(результат
некорректного определения взаимосвязей компонентов
и процессов);
• с некорректным заданием данных и их структур при
описании отдельных компонентов и ПС в целом;
• с некорректным описанием алгоритмов модулей;
• с определением условий возникновения возможных
ошибок в программе;
• с нарушением принятых для проекта стандартов и
технологий.

9. Этап кодирования

• На данном этапе возникают ошибки, которые являются
результатом
дефектов
проектирования,
ошибок
программистов и менеджеров в процессе разработки и
отладки системы. Причиной ошибок являются:
• бесконтрольность значений входных параметров, индексов
массивов, параметров циклов, выходных результатов,
деления на 0 и др.;
• неправильная обработка нерегулярных ситуаций при анализе
кодов возврата от вызываемых подпрограмм, функций и др.;
• нарушение стандартов кодирования (плохие комментарии,
нерациональное выделение модулей и компонент и др.);
• использование одного имени для обозначения разных
объектов или разных имен одного объекта, плохая
мнемоника имен;- несогласованное внесение изменений в
программу разными разработчиками и др.

10. Процесс тестирования.

• На этом процессе ошибки допускаются
программистами и тестировщиками при
выполнении
технологии
сборки
и
тестирования, выбора тестовых наборов и
сценариев тестирования и др. Отказы в
программном обеспечении, вызванные такого
рода
ошибками,
должны
выявляться,
устраняться и не отражаться на статистике
ошибок
компонент
и
программного
обеспечения в целом.

11. Процесс сопровождения.

На процессе сопровождения обнаруживаются
ошибки,
причиной
которых
являются
недоработки и дефекты эксплуатационной
документации,
недостаточные
показатели
модифицируемости и удобочитаемости, а также
некомпетентность лиц, ответственных за
сопровождение и/или усовершенствование ПО.
В зависимости от сущности вносимых изменений
на этом этапе могут возникать практически
любые
ошибки,
аналогичные
ранее
перечисленным ошибкам на предыдущих
этапах.

7.2.3. Функциональное тестирование

Цель функционального тестирования — обнаружение несоответствий между реальным поведением реализованных функций и ожидаемым поведением в соответствии со спецификацией и исходными требованиями. Функциональные тесты должны охватывать все реализованные функции с учетом наиболее вероятных типов ошибок. Тестовые сценарии, объединяющие отдельные тесты, ориентированы на проверку качества решения функциональных задач.

Функциональные тесты создаются по внешним спецификациям функций, проектной информации и по тексту на ЯП, относятся к функциональным его характеристикам и применяются на этапе комплексного тестирования и испытаний для определения полноты реализации функциональных задач и их соответствия исходным требованиям.

В задачи функционального тестирования входят:

  • идентификация множества функциональных требований;
  • идентификация внешних функций и построение последовательностей функций в соответствии с их использованием в ПС;- идентификация множества входных данных каждой функции и определение областей их изменения;
  • построение тестовых наборов и сценариев тестирования функций;
  • выявление и представление всех функциональных требований с помощью тестовых наборов и проведение тестирования ошибок в программе и при взаимодействии со средой.

Тесты, создаваемые по проектной информации, связаны со структурами данных, алгоритмами, интерфейсами между отдельными компонентами и применяются для тестирования компонентов и их интерфейсов. Основная цель — обеспечение полноты и согласованности реализованных функций и интерфейсов между ними.

Комбинированный метод «черного ящика» и «прозрачного ящика» основан на разбиении входной области функции на подобласти обнаружения ошибок. Подобласть содержит однородные элементы, которые все обрабатываются корректно либо некорректно. Для тестирования подобласти производится выполнение программы на одном из элементов этой области.

Предпосылки функционального тестирования:

  • корректное оформление требований и ограничений к качеству ПО;
  • корректное описание модели функционирования ПО в среде эксплуатации у заказчика;
  • адекватность модели ПО заданному классу.

7.3. Инфраструктура процесса тестирования ПС

Под инфраструктурой процесса тестирования понимается:

  • выделение объектов тестирования;
  • проведение классификации ошибок для рассматриваемого класса тестируемых программ;
  • подготовка тестов, их выполнение и поиск разного рода ошибок и отказов в компонентах и в системе в целом;
  • служба проведения и управление процессом тестирования;
  • анализ результатов тестирования.

Объекты тестирования — компоненты, группы компонентов, подсистемы и система. Для каждого из них формируется стратегия проведения тестирования. Если объект тестирования относится к «белому ящику» или «черному ящику», состав компонентов которого неизвестный, то тестирование проводится посредством ввода внего входных тестовых данных для получения выходных данных. Стратегическая цель тестирования состоит в том, чтобы убедиться, что каждый рассматриваемый входной набор данных соответствует ожидаемым выходным выходных данным. При таком подходе к тестированию не требуется знания внутренней структуры и логики объекта тестирования.

Проектировщик тестов должен заглянуть внутрь «черного ящика» и исследовать детали процессов обработки данных, вопросы обеспечения защиты и восстановления данных, а также интерфейсы с другими программами и системами. Это способствует подготовке тестовых данных для проведения тестирования.

Для некоторых типов объектов группа тестирования не может сгенерировать представительное множество тестовых наборов, которые демонстрировали бы функциональную правильность работы компоненты при всех возможных наборах тестов.

Поэтому предпочтительным является метод «белого ящика», при котором можно использовать структуру объекта для организации тестирования по различным ветвям. Например, можно выполнить тестовые наборы, которые проходят через все операторы или все контрольные точки компонента для того, чтобы убедиться в правильности их работы.

7.3.1. Методы поиска ошибок в программах

Международный стандарт ANSI/IEEE-729-83 разделяет все ошибки в разработке программ на следующие типы.

Ошибка (error) — состояние программы, при котором выдаются неправильные результаты, причиной которых являются изъяны (flaw) в операторах программы или в технологическом процессе ее разработки, что приводит к неправильной интерпретации исходной информации, следовательно, и к неверному решению.

Дефект (fault) в программе — следствие ошибок разработчика на любом из этапов разработки, которая может содержаться в исходных или проектных спецификациях, текстах кодов программ, эксплуатационной документация и т.п. В процессе выполнения программы может быть обнаружен дефект или сбой.

Отказ (failure) — это отклонение программы от функционирования или невозможность программы выполнять функции, определенные требованиями и ограничениями, что рассматривается как событие, способствующее переходу программы в неработоспособное состояние из-за ошибок, скрытых в ней дефектов или сбоев в среде функционирования [7.6, 7.11]. Отказ может быть результатом следующих причин:

  • ошибочная спецификация или пропущенное требование, означающее, что спецификация точно не отражает того, что предполагал пользователь;
  • спецификация может содержать требование, которое невозможно выполнить на данной аппаратуре и программном обеспечении;
  • проект программы может содержать ошибки (например, база данных спроектирована без средств защиты от несанкционированного доступа пользователя, а требуется защита);
  • программа может быть неправильной, т.е. она выполняет несвойственный алгоритм или он реализован не полностью.

Таким образом, отказы, как правило, являются результатами одной или более ошибок в программе, а также наличия разного рода дефектов.

Ошибки на этапах процесса тестирования.Приведенные типы ошибок распределяются по этапам ЖЦ и им соответствуют такие источники их возникновения [7.12]:

  • непреднамеренное отклонение разработчиков от рабочих стандартов или планов реализации;
  • спецификации функциональных и интерфейсных требований выполнены без соблюдения стандартов разработки, что приводит к нарушению функционирования программ;
  • организации процесса разработки — несовершенная или недостаточное управление руководителем проекта ресурсами (человеческими, техническими, программными и т.д.) и вопросами тестирования и интеграции элементов проекта.

Рассмотрим процесс тестирования, исходя из рекомендаций стандарта ISO/IEC 12207, и приведем типы ошибок, которые обнаруживаются на каждом процессе ЖЦ.

Процесс разработки требований. При определении исходной концепции системы и исходных требований к системе возникают ошибки аналитиков при спецификации верхнего уровня системы и построении концептуальной модели предметной области.

Характерными ошибками этого процесса являются:

  • неадекватность спецификации требований конечным пользователям;- некорректность спецификации взаимодействия ПО со средой функционирования или с пользователями;
  • несоответствие требований заказчика к отдельным и общим свойствам ПО;
  • некорректность описания функциональных характеристик;
  • необеспеченность инструментальными средствами всех аспектов реализации требований заказчика и др.

Процесс проектирования.Ошибки при проектировании компонентов могут возникать при описании алгоритмов, логики управления, структур данных, интерфейсов, логики моделирования потоков данных, форматов ввода-вывода и др. В основе этих ошибок лежат дефекты спецификаций аналитиков и недоработки проектировщиков. К ним относятся ошибки, связанные:

  • с определением интерфейса пользователя со средой;
  • с описанием функций (неадекватность целей и задач компонентов, которые обнаруживаются при проверке комплекса компонентов);
  • с определением процесса обработки информации и взаимодействия между процессами (результат некорректного определения взаимосвязей компонентов и процессов);
  • с некорректным заданием данных и их структур при описании отдельных компонентов и ПС в целом;
  • с некорректным описанием алгоритмов модулей;
  • с определением условий возникновения возможных ошибок в программе;
  • с нарушением принятых для проекта стандартов и технологий.

Этап кодирования.На данном этапе возникают ошибки, которые являются результатом дефектов проектирования, ошибок программистов и менеджеров в процессе разработки и отладки системы. Причиной ошибок являются:

  • бесконтрольность значений входных параметров, индексов массивов, параметров циклов, выходных результатов, деления на 0 и др.;
  • неправильная обработка нерегулярных ситуаций при анализе кодов возврата от вызываемых подпрограмм, функций и др.;
  • нарушение стандартов кодирования (плохие комментарии, нерациональное выделение модулей и компонент и др.);
  • использование одного имени для обозначения разных объектов или разных имен одного объекта, плохая мнемоника имен;- несогласованное внесение изменений в программу разными разработчиками и др.

Процесс тестирования.На этом процессе ошибки допускаются программистами и тестировщиками при выполнении технологии сборки и тестирования, выбора тестовых наборов и сценариев тестирования и др. Отказы в программном обеспечении, вызванные такого рода ошибками, должны выявляться, устраняться и не отражаться на статистике ошибок компонент и программного обеспечения в целом.

Процесс сопровождения.На процессе сопровождения обнаруживаются ошибки, причиной которых являются недоработки и дефекты эксплуатационной документации, недостаточные показатели модифицируемости и удобочитаемости, а также некомпетентность лиц, ответственных за сопровождение и/или усовершенствование ПО. В зависимости от сущности вносимых изменений на этом этапе могут возникать практически любые ошибки, аналогичные ранее перечисленным ошибкам на предыдущих этапах.

Все ошибки, которые возникают в программах, принято подразделять на следующие классы [7.12]:

  • логические и функциональные ошибки;
  • ошибки вычислений и времени выполнения;
  • ошибки вводавывода и манипулирования данными;
  • ошибки интерфейсов;
  • ошибки объема данных и др.

Логические ошибки являются причиной нарушения логики алгоритма, внутренней несогласованности переменных и операторов, а также правил программирования. Функциональные ошибки — следствие неправильно определенных функций, нарушения порядка их применения или отсутствия полноты их реализации и т.д.

Ошибки вычислений возникают по причине неточности исходных данных и реализованных формул, погрешностей методов, неправильного применения операций вычислений или операндов. Ошибки времени выполнения связаны с необеспечением требуемой скорости обработки запросов или времени восстановления программы.

Ошибки ввода-вывода и манипулирования данными являются следствием некачественной подготовки данных для выполнения программы, сбоев при занесении их в базы данных или при выборке из нее.

Ошибки интерфейса относятся к ошибкам взаимосвязи отдельных элементов друг с другом, что проявляется при передаче данных между ними, а также при взаимодействии со средой функционирования.

Ошибки объема относятся к данным и являются следствием того, что реализованные методы доступа и размеры баз данных не удовлетворяют реальным объемам информации системы или интенсивности их обработки.

Приведенные основные классы ошибок свойственны разным типам компонентов ПО и проявляются они в программах по разному. Так, при работе с БД возникают ошибки представления и манипулирования данными, логические ошибки в задании прикладных процедур обработки данных и др. В программах вычислительного характера преобладают ошибки вычислений, а в программах управления и обработки — логические и функциональные ошибки. В ПО, которое состоит из множества разноплановых программ, реализующих разные функции, могут содержаться ошибки разных типов. Ошибки интерфейсов и нарушение объема характерны для любого типа систем.

Анализ типов ошибок в программах является необходимым условием создания планов тестирования и методов тестирования для обеспечения правильности ПО.

На современном этапе развития средств поддержки разработки ПО (CASE-технологии, объектно-ориентированные методы и средства проектирования моделей и программ) проводится такое проектирование, при котором ПО защищается от наиболее типичных ошибок и тем самым предотвращается появление программных дефектов.

Связь ошибки с отказом.Наличие ошибки в программе, как правило, приводит к отказу ПО при его функционировании. Для анализа причинно-следственных связей «ошибкаотказ» выполняются следующие действия:

  • идентификация изъянов в технологиях проектирования и программирования;
  • взаимосвязь изъянов процесса проектирования и допускаемых человеком ошибок;
  • классификация отказов, изъянов и возможных ошибок, а также дефектов на каждом этапе разработки;- сопоставление ошибок человека, допускаемых на определенном процессе разработки, и дефектов в объекте, как следствий ошибок спецификации проекта, моделей программ;
  • проверка и защита от ошибок на всех этапах ЖЦ, а также обнаружение дефектов на каждом этапе разработки;
  • сопоставление дефектов и отказов в ПО для разработки системы взаимосвязей и методики локализации, сбора и анализа информации об отказах и дефектах;
  • разработка подходов к процессам документирования и испытания ПО.

Конечная цель причинно-следственных связей «ошибкаотказ» заключается в определении методов и средств тестирования и обнаружения ошибок определенных классов, а также критериев завершения тестирования на множестве наборов данных; в определении путей совершенствования организации процесса разработки, тестирования и сопровождения ПО.

Приведем следующую классификацию типов отказов:

  • аппаратный, при котором общесистемное ПО не работоспособно;
  • информационный, вызванный ошибками во входных данных и передаче данных по каналам связи, а также при сбое устройств ввода (следствие аппаратных отказов);
  • эргономический, вызванный ошибками оператора при его взаимодействии с машиной (этот отказ — вторичный отказ, может привести к информационному или функциональному отказам);
  • программный, при наличии ошибок в компонентах и др.

Некоторые ошибки могут быть следствием недоработок при определении требований, проекта, генерации выходного кода или документации. С другой стороны, они порождаются в процессе разработки программы или при разработке интерфейсов отдельных элементов программы (нарушение порядка параметров, меньше или больше параметров и т.п.).

Источники ошибок.Ошибки могут быть порождены в процессе разработки проекта, компонентов, кода и документации. Как правило, они обнаруживаются при выполнении или сопровождении программного обеспечения в самых неожиданных и разных ее точках.

Некоторые ошибки в программе могут быть следствием недоработок при определении требований, проекта, генерации кода или документации. С другой стороны, ошибки порождаются в процессе разработки программы или интерфейсов ее элементов (например, при нарушении порядка задания параметров связи — меньше или больше, чем требуется и т.п.).

Причиной появления ошибок — непонимание требований заказчика; неточная спецификация требований в документах проекта и др. Это приводит к тому, что реализуются некоторые функции системы, которые будут работать не так, как предлагает заказчик. В связи с этим проводится совместное обсуждение заказчиком и разработчиком некоторых деталей требований для их уточнения.

Команда разработчиков системы может также изменить синтаксис и семантику описания системы. Однако некоторые ошибки могут быть не обнаружены (например, неправильно заданы индексы или значения переменных этих операторов).

МЕТОДИЧЕСКИЕ 
РЕКОМЕНДАЦИИ  ДЛЯ   СТУДЕНТОВ

Ульяновский
авиационный колледж

ПРОФЕССИОНАЛЬНЫЙ 
ЦИКЛ

Тестирование
информационных систем

ЛЕКЦИИ

на специальности СПО базовой подготовки

09.02.07 
Информационные системы и программирование

Ульяновск

 2021

ОДОБРЕНО

на заседании ЦМК

программирования и ИТ

Протокол № __

от «__» ______20___ г.

Председатель ЦМК:

_________________ А.А. Шарифуллина

УТВЕРЖДАЮ

Зам. директора по
учебной работе

_______________ Г.В.
Знаенко

 «_____» __________ 20_____ г.

РАЗРАБОТЧИК:
Кякшта М.А.,  преподаватель информационных дисциплин Ульяновского
авиационного колледжа.

Содержание

Введение………………………………………………………………………….5

Тема 3.1 Организация тестирования в
команде разработчиков………………6

Цели и область тестирования……………………………………………………6

Коммуникация и взаимодействие в процессе
тестирования………………….8

Методология тестирования………………………………………………………9

Тестовые среды………………………………………………………………….10

Документированность процесса тестирования………………………………..12

Методология тестирования сложных систем………………………………….13

Тема 3.2 Тестирование web-приложений………………………………………15

Особенности тестирования web-приложений…………………………………15

Тестирование пользовательского интерфейса.
……………………………….17

Ручное тестирование…………………………………………………………….18

Тема 3.3 Организация тестирования
информационных систем……………19

Основные этапы тестирования……………………………………………….19

Функциональное  тестирование………………………………………………21

Структурное тестирование……………………………………………………23

Тестирование покрытия программного кода………………………………..24

Тестирование скорости загрузки системы…………………………………..26

Тестирование функциональных требований.
Комплексное тестирование..28

Тестирование граничных условий……………………………………………31

Тестирование утечки памяти………………………………………………….32

Тема 3.4 Тестирование отдельных модулей…………………………………33

Инструментарии анализа качества
программных продуктов в среде разработке………………………………………………………………………34

Выявление ошибок системных компонентов………………………………..35

Методы идентификации сбоев и ошибок……………………………………37

Автоматизация тестирования в продуктивной
среде……………………….39

Тема 3.5 Реинжиниринг бизнес-процессов в
информационных системах..41

Сущность реинжиниринга бизнес-процессов.
Этапы реинжиниринга……41

Изучение методологии структурного
системного анализа…………………42

Основные методологии обследования
организаций………………………..44

Особенности национальной практики
применения функционального моделирования ………………………………………………………………..45

Причины реинжиниринга информационных
систем……………………….46

Список использованных
источников………………………………………..48

Введение

       Тестирование
— очень важный и трудоемкий этап процесса разработки программного обеспечения,
так как он позволяет выявить подавляющее большинство ошибок, допущенных при
составлении программ.

Процесс
разработки программного обеспечения предполагает три стадии тестирования:

·       
автономное тестирование компонентов
программного обеспечения;

·       
комплексное тестирование разрабатываемого
программного обеспечения;

·       
системное или оценочное тестирование на
соответствие основным критериям качества.

Для
повышения качества тестирования рекомендуется соблюдать следующие основные
принципы:

·       
предполагаемые результаты должны быть
известны до тестирования;

·       
следует избегать тестирования программы
автором;

·       
досконально изучать результаты каждого
теста;

·       
необходимо проверять работу программы на
неверных данных;

·       
вероятность наличия необнаруженных ошибок
в части программы пропорциональна числу ошибок, уже обнаруженных в этой части.

Формирование
набора тестов имеет большое значение, поскольку тестирование является одним из
наиболее трудоемких этапов (от 30 до 60 % общей трудоемкости) создания
программного продукта. Существуют два принципиально разных подхода к
формированию тестовых наборов – структурный и функциональный.

Структурный
подход базируется на том, что известны алгоритмы работы программы. В основе
структурного тестирования лежит концепция максимально полного тестирования всех
маршрутов программы.

Функциональный
подход основывается на том, что алгоритм работы программного обеспечения не
известен. Тесты строят, опираясь на функциональные спецификации. Программа
рассматривается как «черный ящик», и целью тестирования является выяснение
обстоятельств, в которых поведение программы не соответствует требованиям.

Опытные
отладчики обнаруживают ошибки путём сравнения шаблонов тестовых выходных данных
с выходными данными тестируемых систем. Чтобы определить местоположение ошибки,
необходимы знания о типах ошибок, шаблонах выходных данных, языке и процессе
программирования. Очень важны знания о процессе разработке программного
обеспечения.

Тема
3.1 Организация тестирования в команде разработчиков

Цели
и область тестирования

Качество
программного продукта характеризуется набором свойств, определяющих, насколько
продукт «хорош» с точки зрения заинтересованных сторон, таких как заказчик
продукта, спонсор, конечный пользователь, разработчики и тестировщики продукта,
инженеры поддержки, сотрудники отделов маркетинга, обучения и продаж. Каждый из
участников может иметь различное представление о продукте и том, насколько он
хорош или плох, то есть о том, насколько высоко качество продукта. Таким
образом, постановка задачи обеспечения качества продукта выливается в задачу
определения заинтересованных лиц, их критериев качества и затем нахождения
оптимального решения, удовлетворяющего этим критериям. Тестирование является
одним из наиболее устоявшихся способов обеспечения качества разработки
программного обеспечения и входит в набор эффективных средств современной
системы обеспечения качества программного продукта.

С
технической точки зрения тестирование заключается в выполнении приложения на
некотором множестве исходных данных м сверке получаемых результатов с заранее
известными (эталонными) с целью установить соответствие различных свойств и
характеристик приложения заказанным свойствам. Отладка(debug, debugging) —
процесс поиска, локализации и исправления ошибок в программе.

Термин
«отладка» в отечественной литературе используется двояко: для обозначения
активности по поиску ошибок (собственно тестирование), по нахождению причин их
появления и исправлению, или активности по локализации и исправлению ошибок.

Тестирование
— это процесс выполнения ПО системы или компонента в условиях анализа или
записи получаемых результатов с целью проверки (оценки) некоторых свойств
тестируемого объекта.

Тестирование
— это процесс анализа пункта требований к ПО с целью фиксации различий между
существующим состоянием ПО и требуемым (что свидетельствует о проявлении
ошибки) при экспериментальной проверке соответствующего пункта требований.

Тестирование
— это контролируемое выполнение программы на конечном множестве тестовых данных
и анализ результатов этого выполнения для поиска ошибок.

Целью
проектирования тестовых вариантов является систематическое обнаружение
различных классов ошибок при минимальных затратах времени и стоимости.

Тестирование
обеспечивает:

·       
Обнаружение ошибок.

·       
Демонстрацию соответствия функций
программы ее назначению.

·       
Демонстрацию реализации требований к
характеристикам программы.

·       
Отображение надежности как индикатора
качества программы.

Тестирование
не может показать отсутствие дефектов (оно может показывать только присутствие
дефектов). Важно помнить это утверждение при проведении тестирования.

Тестирование
— важная часть любой программы контроля качества, а зачастую и единственная.
Это печально, так как разнообразные методики совместной разработки позволяют
находить больше ошибок, чем тестирование, и в то же время обходятся более чем
вдвое дешевле в расчете на одну обнаруженную ошибку. Каждый из отдельных этапов
тестирования (блочное тестирование, тестирование компонентов и интеграционное
тестирование) обычно позволяют найти менее 50% ошибок. Комбинация этапов
тестирования часто приводит к обнаружению менее 60% ошибок.

Коммуникация
и взаимодействие в процессе тестирования

В
зависимости от потребностей проекта команда может включать участников с
различными ролями. При этом на практике часто бывает, что один человек
одновременно выполняет несколько ролей, если имеет необходимые навыки и знания
для исполнения обязанностей.

Аккаунт-менеджер
— менеджер по работе с клиентами, специалист, который работает с клиентами
компании и обеспечивает их лояльность. Аккаунт-менеджер обеспечивает выполнение
всех необходимых клиенту задач, находит к каждому заказчику индивидуальный
подход, поддерживает с ним хорошие отношения (даже после того, как все заказы
уже выполнены), предлагает ему новые услуги и продукты. Иными словами,
профессия аккаунт-менеджера обязывает ее представителя сделать все возможное,
чтобы клиент был счастлив, работал с компанией всегда и всем ее рекомендовал.

Менеджер
проекта (Project manager, руководитель проекта, проект-менеджер; сокращенно —
PM, ПМ, РП) — лицо, ответственное за управление проектом. Менеджер проекта
несет ответственность за достижение целей проекта в рамках бюджета, в срок и с
заданным уровнем качества.

Системный
аналитик (аналитик) является “мостиком” между заказчиком и членами команды.
Переводит пожелания заказчика в формат точно описанных технических заданий. 

Системный
архитектор (архитектор) проектирует разрабатываемую систему на самом верхнем
уровне и принимает ключевые решения по поводу технологий и методологий
разработки. Активно занимается исследованиями и экспериментами, рисует
многочисленные диаграммы и документирует архитектурные решения.

Программист
(разработчик) пишет код на языках программирования, т.е. непосредственно
кодирует логику работы программы. Также является ее первым пользователем и
тестировщиком. Непосредственно отвечает за то, что программа работает и
работает правильно (в соответствии с техническим заданием). 

Ведущий
программист (технический лидер, техлид) — программист, который с технической
точки зрения принимает решения о формате реализации функционала и координирует
работу команды разработчиков. 

QA-специалист
— специалист, который обеспечивает качество продукта (тестирует, контролирует и
управляет качеством продукта).

SDET-специалист
(контроль качества, автоматизация тестирования) — специалист, который проверяет
и отвечает за качество продукта. Пишет код для автоматизации процесса
тестирования на разных языках программирования. Помогает команде разработки с
точки зрения технических вопросов, вопросов архитектуры и построения приложения

QA
lead (ведущий специалист по управлению и контролю качества) — QA-специалист,
который руководит командой тестирования.

Тимлид
— лидер команды, обеспечивающий достижение проектных целей посредством
организации работы команды, состоящей из сотрудников различных направлений
компании, а также отвечающий за развитие участников команды, построение
коммуникаций (как внутри, так и извне), дисциплину и управление составом
команды. 

Методология
тестирования

Тестирование
— самая популярная методика повышения качества, подкрепленная многими
исследованиями и богатым опытом разработки коммерческих приложений. Существует
множество видов тестирования: одни обычно выполняют сами разработчики, а другие
— специализированные группы. Виды тестирования перечислены ниже:

·
Блочным тестированием называют тестирование полного класса, метода или
небольшого приложения, написанного одним программистом или группой, выполняемое
отдельно от прочих частей системы.

·
Тестирование компонента — это тестирование класса, пакета, небольшого
приложения или другого элемента системы, разработанного несколькими
программистами или группами, выполняемое в изоляции от остальных частей
системы.

·
Интеграционное тестирование — это совместное выполнение двух или более классов,
пакетов, компонентов или подсистем, созданных несколькими программистами или
группами.

·
Регрессивным тестированием называют повторное выполнение тестов, направленное
на обнаружение дефектов в программе, уже прошедшей этот набор тестов.

·
Тестирование системы — это выполнение ПО в его окончательной конфигурации,
интегрированного с другими программными и аппаратными системами.

Фазы
тестирования.

Реализация
тестирования делится на три этапа:

1.
Создание тестового набора (test suite) путем ручной разработки или
автоматической генерации для конкретной среды тестирования (testing
environment).

2.
Прогон программы на тестах, управляемый тестовым монитором (test monitor, test
driver) с получением протокола тестирования (test log).

3.
Оценка результатов выполнения программы на наборе тестов с целью принятия
решения о продолжении или остановке тестирования.

Тестовые
среды

Среда
тестирования — это настройка программного и аппаратного обеспечения для групп
тестирования для выполнения тестовых случаев. Другими словами, он поддерживает
выполнение теста с настроенным оборудованием, программным обеспечением и сетью.

Испытательный
стенд или тестовая среда настраиваются в соответствии с требованиями
тестируемого приложения. В некоторых случаях испытательный стенд может
представлять собой комбинацию тестовой среды и тестовых данных, которые он
использует.

Важно
понимать, что процесс тестирования требует системного подхода и использовать
для этого лучшие практики недостаточно. Чтобы получить положительные
результаты, необходимо с самого начала организовать процесс правильно. Для
начала необходимо определиться с целями, областью, методологией тестирования и
позаботиться о подготовке тестовой среды.

 Сегодня
многие организации, в том числе команды разработки, уходят от традиционных
подходов к организации тестовых сред. Если раньше под эти задачи разворачивали
собственную инфраструктуру, которая требовала отдельной поддержки и
дополнительных финансовых вливаний, теперь чаще отдается предпочтение более
экономичным вариантам. Одним из них является виртуальный хостинг,
представляющий собой один из удобных вариантов организации процесса
тестирования, который отличается целым рядом конкурентных преимуществ.
Примечательно, что тестовые среды, развернутые на базе виртуального хостинга,
избавляют от простоев собственных серверов, поскольку отпадает необходимость в
их использовании. Вместо этого вы получаете необходимые виртуальные ресурсы без
потери качества.

В
последнее время большинство приложений создаются с возможностью доступа через
стандартный интернет-браузер, и они также нуждаются в проверке
работоспособности на уровне кода. Очень важно, чтобы приложение точно повторяло
взаимодействие с пользователем. Кроме того, важно получить обратную связь
относительно производительности и надежности работы сервиса. Используя для этих
задач виртуальный хостинг, можно получить практически мгновенный ответ и
обратную связь относительно функциональности и согласованности работы
конкретного решения.

Документированность
процесса тестирования

Тестовый
план — это документ, или набор документов, который содержит тестовые ресурсы,
перечень функций и подсистем, подлежащих тестированию, тестовую стратегию,
расписание тестовых циклов, фиксацию тестовой конфигурации (состава и
конкретных параметров аппаратуры и программного окружения), определение списка
тестовых метрик, которые на тестовом цикле необходимо собрать и
проанализировать (например метрик, оценивающих степень покрытия тестами набора
требований).

Тесты
разрабатывают на основе спецификаций как вручную, так и с помощью
автоматизирующих средств. Помимо собственно кода, в понятие «тест»
включается его общее описание и подробное описание шагов, выполняемых в данном
тесте.

Для
оценки качества тестов используют различные метрики, связанные с количеством
найденных дефектов, покрытием кода, функциональных требований, множества
сценариев.

Вся
информация об обнаруженных в процессе тестирования дефектах (тип, условия
обнаружения, причина, условия исправления, время, затраченное на исправление)
заносятся в базу дефектов.

Информация
о тестовом плане, тестах и дефектах используется в конце каждого цикла
тестирования для генерации тестового отчета и корректирования системы тестов
для следующей итерации.

В
тестовом плане определяются и документируются различные типы тестов. Типы
тестирования по виду подсистемы или продукта таковы:

·       
Тестирование основной функциональности,
когда тестированию подвергается собственно система, являющаяся основным
выпускаемым продуктом.

·       
Тестирование инсталляции включает
тестирование сценариев первичной инсталляции системы, сценариев повторной
инсталляции (поверх уже существующей копии), тестирование деинсталляции,
тестирование инсталляции в условиях наличия ошибок в инсталлируемом пакете, в
окружении или в сценарии и т. п.

·       
Тестирование пользовательской документации
включает проверку полноты и понятности описания правил и особенностей
использования продукта, наличие описания всех сценариев и функциональности,
синтаксис и грамматику языка, работоспособность примеров и т. п.

Методология
тестирования сложных систем

Тестирование
сложных программных решений и комплексных систем.

Сложная
система — система, состоящая из множества взаимодействующих составляющих,
вследствие чего сложная система приобретает новые свойства, которые отсутствуют
на подсистемном уровне и не могут быть сведены к свойствам подсистемного
уровня.

Эффективно
начинать тестирование комплексных (и других) систем на ранних стадиях
разработки ПО.

Методы
тестирования в основном отличаются подходами к выбору множества тестовых данных
из входного пространства. Основная цель тестирования — обнаружить дефекты в ПС
и установить ее функциональную пригодность, удобство применения, производительность
и др.

Тестирование
на протяжении процесса разработки сложной структуры из модулей выполняется на
нескольких уровнях. Для каждого определяются категория объектов тестирования
(ПС, компоненты, отдельные модули) и набор проверяемых тестируемых характеристик.

На
каждом уровне тестирование повторяется многократно, образуя циклы: тестирование
— исправление — повторное тестирование.

В
современной практике тестирования все виды действий, начиная с планирования до
оценки результатов тестирования, должны интегрироваться в четко определенный,
документируемый и контролируемый процесс тестирования. Это облегчает
взаимодействие между разработчиками, группой тестирования и руководством
проекта, а также позволяет сделать процесс видимым, повторяемым и измеряемым.

Тестирование
имеет много общего с процессами верификации и валидации (V& V). Общность
процесса тестирования с процессами V& V заключается в единстве состава и
структуры планов, рекомендуемых стандартом IEEE Std. 829, а также объектов и
применяемых методов. Отличие этих процессов состоит в условиях их применения.
Тестирование выполняется всегда, для всех объектов ПО системы независимо от ее
критичности. Процессы V&.V в современной трактовке стандартов IEEE Std.
1012 и ISO/IEC 12207 — поддерживающие процессы, которые могут применяться к
выбранным объектам тестирования для проверки планов тестирования и
подтверждения того, что выполненное тестирование адекватно уровню критичности
ПС. По отношению к процессу тестирования V&V выполняет контрольную функцию
и подтверждает соответствие объектов установленным требованиям.

Тестирование
ПС тесно связано с отладкой и собственно программированием, но охватывает
гораздо более широкий круг проблем и участников — программистов, тестировщиков,
аналитиков и инженеров по качеству.

Традиционно
выделяются три уровня тестирования ПО: автономное или модульное (unit testing),
интеграционное (integrating testing) и системное (system testing). В стандарте
ISO/IEC 12207 прослеживаются четыре уровня тестирования:


модульное (в процессе «Построение ПО»);


интеграционное (в процессе «Сборка ПО»);


тестирование ПС (как процесс);


системное (в процессе «Испытания ПС»)

Тема
3.2 Тестирование web-приложений

Особенности
тестирования web-приложений

Тестирование
веб-приложений – это комплекс услуг, который может включать в себя различные
виды тестирования ПО. Основная цель любого тестирования, в том числе и
тестирования веб-приложений, – обнаружить все ошибки в программном обеспечении
и разработать рекомендации по их предотвращению в будущем.

Функциональное
тестирование – процесс оценки поведения приложения, позволяющий определить, все
ли разработанные функции ведут себя так, как нужно. Для корректной работы
продукта все процессы должны работать так, как это предусмотрено в требованиях:
от разграничения прав доступа при авторизации до корректного выхода из системы.
Функциональное тестирование может быть выполнено с использованием заранее
подготовленных тестовых сценариев или методами исследовательского тестирования.

Тестирование
совместимости – это процесс оценки поведения приложения в различных браузерах,
операционных системах, на устройствах с разным разрешением экрана. Проверка
совместимости продукта со всеми последними версиями браузеров Chrome, Firefox,
MS Edge, Safari и ОС Windows 7, 8 и 10 является примером данного вида
тестирования.

Тестирование
производительности – комплекс проверок, направленный на определение лимитов
производительности приложения. После проведения тестирования специалисты
предоставят отчет, который будет содержать следующую информацию:

·       
Статистические данные по времени отклика с
сервера для наиболее важных операций;

·       
Диаграммы, показывающие зависимость
производительности приложения от количества пользователей, одновременно
работающих в программе;

·       
Данные о максимально возможном числе
пользователей, при котором система справляется с нагрузкой;

·       
Информация об устойчивости системы и ее
способности выдерживать постоянную нагрузку;

·       
Статистика ошибок;

·       
Выводы об эффективности системы в целом,
ошибках ее производительности;

·       
Рекомендации по повышению
производительности системы.

Тестирование
безопасности и тестирование на проникновение позволяет определить, как и при
каких обстоятельствах приложение может быть взломано. Анализ и оценка уровня
защищенности приложения – зона ответственности инженеров по тестированию
безопасности.

Локализованный
продукт всегда дает больше возможностей для бизнеса. Процесс проверки качества
локализации называется тестированием локализации. Аспекты, качество которых
проверяют специалисты по тестированию локализации:

·       
Перевод содержимого страницы и элементов
пользовательского интерфейса;

·       
Формат данных и времени;

·       
Обозначение денежных единиц;

·       
Цветовые схемы, символы, значки и другие
графические элементы, которые могут быть по-разному истолкованы в различных
регионах;

·       
Правовые нормы, которые следует учитывать.

Цель
тестирования соответствия – установить, соответствует ли приложение юридическим
нормам и стандартам, которым подчиняется ваш бизнес. Примером тестирования
соответствия является проверка выполнения рекомендаций Руководства по
обеспечению доступности веб-контента (WCAG). Учет требований данного
Руководства помогает сделать веб-продукт доступным для людей с ограниченными
возможностями.

Тестирование
пользовательского интерфейса.

Графический
интерфейс пользователя (Graphical user interface, GUI) –разновидность
пользовательского интерфейса, в котором элементы интерфейса (меню, кнопки,
значки, списки и т. п.), представленные пользователю на дисплее, исполнены в
виде графических изображений. Проверяется в целом общий вид приложения и в
отдельности формы, расположенные на странице.

Общие
проверки:

·       
Вид элементов при уменьшении окна браузера
+ появление скрола

·       
Правильность написания текста + текст
должен быть выровнен

·       
Правильность перемещения фокуса в окне
(Tab / Tab+Shift)

·       
Выбранные элементы выделяются

·       
Неизменяемые поля выглядят одинаково и
отличаются от редактируемых

·       
Желательно не использовать двойной клик

·       
Проверка наличия нужных нотификейшенов

·       
Унификация дизайна (цвет, шрифт, размер)

·       
При необходимости должны быть тултипы

·       
Изменение вида элемента при ховере на него

·       
Если формы дублируются, то должны быть
одинаковые названия

·       
Дополнительные проверки для веб-форм

Основные
моменты при проверке GUI:

·       
расположение, размер, цвет, ширина, длина
элементов; возможность ввода букв или цифр

·       
реализуется ли функционал приложения с
помощью графических элементов

·       
размещение всех сообщений об ошибках,
уведомленией (а также шрифт, цвет, размер, расположение и орфография текста)

·       
читабелен ли использованный шрифт

·       
переходит ли курсор из текстового в
поинтер при наведении на активные элементы, выделяются ли выбранные элементы

·       
выравнивание текста и форм 

·       
качество изображений

·       
проверить расположение и отображение всех
элементов при различных разрешениях экрана, а также при изменении размера окна
браузера (проверить, появляется ли скролл)

·       
проверить текст на орфографические,
пунктуационные ошибки

·       
появляются ли тултипы (если есть
необходимость)

·       
унификация дизайна (цвета, шрифты, текст
сообщений, названия кнопок и т.д.)

Наиболее
распространенные баги:

·       
курсор не переходит в поинтер при
наведении на активный элемент

·       
орфографические и грамматические ошибки

·       
не ровное расположение полей ввода в
формах, самих форм

·       
неправильное отображение элементов при
смене размера окна браузера и масштаба страницы

·       
изменение размера текста при смене языка

·       
неровное расположение форм

·       
разные шрифты

·       
выбранные элементы не отличаются от не
выбранных

Ручное
тестирование

Ручное
тестирование (manual testing)  — часть процесса тестирования на этапе контроля
качества в процессе разработки программного обеспечения. Оно производится
тестировщиком без использования программных средств, для проверки программы или
сайта путём моделирования действий пользователя. В роли тестировщиков могут
выступать и обычные пользователи, сообщая разработчикам о найденных ошибках.

Сегодня
есть множество фреймворков для тестирования, поддерживающих практически все
существующие языки. Казалось бы — можно брать и автоматизировать. Но даже
сейчас ручные тесты важны.

Одно
из объяснений их необходимости заключается в том в том, что при ручном
тестировании функционала мы можем гораздо быстрее получить информацию о
состоянии продукта, который анализируем, о качестве разработки. Кроме того, при
автоматизации предварительно разработанные кейсы часто приходится менять и
актуализировать, а на написание автотестов требуется определённое время.

При
этом в процессе разработки может прийти обратная связь от заказчика, когда он
увидит в готовом продукте какую-то функцию, которую решит изменить до релиза —
и, если вы уже подготовили для неё программные тесты, их придётся переписать.
Обновление кейсов, автотестов и их проверка отнимут ценное время, которое можно
было бы использовать на само обновление этой фичи.

Всё
это означает, что главная цель ручных тестов — предварительно убедиться в том,
что заявленный функционал работоспособен, не имеет ошибок и выдаёт ожидаемые,
запланированные результаты. Без них нельзя быть уверенным в том, что можно
работать дальше. Особенно это актуально для функций, на реализацию которых
завязана последующая разработка. В таком случае возня с созданием автотестов на
эти фичи становится блокирующим фактором для всей разработки продукта, сдвигая
сроки и срывая дедлайны. Момент, когда кейсы придёт пора автоматизировать, всё
равно рано или поздно наступит — но не стоит стремиться приблизить его искусственно
в погоне за тотальным исключением ручного труда.

Тема
3.3 Организация тестирования информационных систем

Основные
этапы тестирования

Тестирование
программного продукта позволяет на протяжении всего жизненного цикла ПО
гарантировать, что программные проекты отвечают заданным параметрам качества.
Главная цель тестирования — определить отклонения в реализации функциональных
требований, обнаружить ошибки в выполнении программ и исправить их как можно
раньше в процессе выполнения проекта.

На
протяжении всего жизненного цикла разработки ПО применяются различные типы
тестирования для гарантии того, что промежуточные версии отвечают заданным
показателям качества. При этом применяются автоматические и ручные тесты.

Модульное
тестирование    предназначено для проверки правильности функционирования
методов классов ПО. Модульные тесты пишутся и исполняются разработчиками в
процессе написания кода. Модульное тестирование применяется как для проверки
качества кода приложения, так и для проверки объектов баз данных.

Исследовательское
тестирование предназначено для тестирования, при котором тестировщик не имеет
заранее определенных тестовых сценариев и пытается интуитивно исследовать
возможности программного продукта и обнаружить и зафиксировать неизвестные
ошибки.

Интеграционное
тестирование     используется для проверки корректности совместной работы
компонентов программного продукта.

Функциональное
тестирование     предполагает проверку конкретных требований к ПО и проводится
после добавление к системе новых функций.

Нагрузочное
тестирование  предназначено для проверки работоспособности программного
продукта при предельной входной нагрузке.

Регрессионное
тестирование        применяется при внесении изменений в программное
обеспечение с целью проверки корректности работы компонентов системы, которые
потенциально могут взаимодействовать с измененным компонентом.

Комплексное
тестирование предназначено для тестирования функциональных и нефункциональных
требований всей системы программного продукта.

Приемочное
тестирование   представляет собой функциональные испытания, которые должны
подтвердить то, что программный продукт соответствует требованиям и ожиданиям
пользователей и заказчиков. Приемочные тесты пишутся бизнес-аналитиками,
специалистами по контролю качества и тестировщиками.

Функциональное 
тестирование

Существуют
2 основных принципа тестирования программ:

1)
функциональное тестирование (тестирование черного ящика);

2)
структурное тестирование (тестирование белого ящика).

При
тестировании черного ящика известны функции программы и исследуется работа
каждой функции на всей области определения.

Функциональные
тесты базируются на функциях, а также взаимодействии с другими системами, и
могут быть представлены на всех уровнях тестирования: компонентном,
интеграционном, системном и приемочном. Функциональные виды тестирования
рассматривают внешнее поведение системы, т.е. функции, которые описывают, «что»
система делает.

Функциональное
тестирование основывается на знании о поведении системы, которое описывается в
проектной документации.

Цель
функционального тестирования – подтвердить, что программный продукт реализован
в соответствии с функциональными требованиями.

Тестирование
функциональности может проводиться в двух аспектах:

●     требования

●     бизнес-процессы

Тестирование
в перспективе «требования» использует спецификацию функциональных требований к
системе как основу для дизайна тестовых случаев (Test Cases). В этом случае
необходимо сделать список того, что будет тестироваться, а что нет,
приоритезировать требования на основе рисков (если это не сделано в документе с
требованиями), а на основе этого приоритезировать тестовые сценарии (test
cases).

Это
позволит сфокусироваться и не упустить при тестировании наиболее важный
функционал.

Тестирование
в перспективе «бизнес-процессы» использует знание этих самых бизнес-процессов,
которые описывают сценарии ежедневного использования системы. В этой
перспективе тестовые сценарии (test scripts), как правило, основываются на
случаях использования системы (use cases).

Тестирование
взаимодействия (Interoperability Testing)  — это функциональное тестирование,
проверяющее способность приложения взаимодействовать с одним и более
компонентами или системами, и включающее в себя тестирование совместимости и
интеграционное тестирование  

Тестирование
безопасности – это вид тестирования, используемый для проверки безопасности
системы, а также для анализа рисков, связанных с обеспечением целостного
подхода к защите приложения, атак хакеров, вирусов, несанкционированного
доступа к конфиденциальным данным.

Принципы
безопасности программного обеспечения: 

Общая
стратегия безопасности основывается на трех основных принципах:

Конфиденциальность
– это сокрытие определенных ресурсов или информации. Под конфиденциальностью
можно понимать ограничение доступа к ресурсу некоторой категории пользователей,
или другими словами, при каких условиях пользователь авторизован получить
доступ к данному ресурсу.

Целостность
— существует два основных критерия при определении понятия целостности:

1.    Доверие.
Ожидается, что ресурс будет изменен только соответствующим способом
определенной группой пользователей.

2.    Повреждение
и восстановление. В случае когда данные повреждаются или неправильно меняются
авторизованным или не авторизованным пользователем, вы должны определить на
сколько важной является процедура восстановления данных.

Доступность
представляет собой требования о том, что ресурсы должны быть доступны
авторизованному пользователю, внутреннему объекту или устройству. Как правило,
чем более критичен ресурс, тем выше уровень доступности должен быть.

Структурное
тестирование

Структурное
тестирование основывается на детальном изучении логики программы и подборе
тестов, обеспечивающих максимально возможное число проверяемых операторов,
логических ветвлений и условий. Его еще называют «тестирование по маршрутам».
Под маршрутом понимают последовательности операторов программы, которые
выполняются при конкретном варианте исхоных данных. При построении тестов
используют следующие критерии:


покрытие операторов путем выбора набора данных, обеспечивающего выполнение
каждого оператора в программе по крайней мере один раз.


покрытие условий путем подбора наборов данных, обеспечивающих в узлах ветвления
с более чем одним условием принятие каждым условием значения «истина»
или «ложь» хотя бы по одному разу.


комбинаторное покрытие условий путем подбора тестов, обеспечивающих в узлах
ветвления с более чем одним условием перебор всех возможных сочетаний значений
условий в одном узле ветвления.

Считают,
что программа проверена полностью, если с помощью тестов удается осуществить
выполнение программы по всем возможным маршрутам передач управления. Однако
нетрудно видеть, что даже в программе среднего уровня сложности число
неповтояющихся маршрутов может быть очень велико и, следовательно, полное или
исчерпывающее тестирование маршрутов, как правило, невозможно.

При
тестировании белого ящика объектом тестирования является не внешнее, а
внутреннее поведение программы. Проверяется корректность построения всех элементов
программы и правильность их взаимодействия друг с другом. При этом обычно
анализируются управляющие связи элементов, реже информационные.

Тестирование
по принципу белого ящика характеризуется степенью, в которой тесты выполняют
логику, т.е. исходный текст программы.

Обычно
тестирование белого ящика основано на анализе управляющей структуры программы.
Программа считается полностью проверенной, если проведено исчерпывающее
тестирование маршрутов графа управления. В этом случае формируются тестовые варианты,
в которых:

1)
гарантируется проверка всех независимых маршрутов программы;

2)
проверяются ветви TRUE и FALSE для всех логических решений;

3)
выполняются все циклы в пределах их границ и диапазонов;

4)
анализируется правильность внутренних структур данных.

Тестирование
покрытия программного кода

Покрытие
– это часть структуры программы, которая была охвачена тестированием,
выраженная в процентах.

Существует
несколько различных способов измерения покрытия:

·       
покрытие операторов — каждая ли строка
исходного кода была выполнена и протестирована;

·       
покрытие условий — каждая ли точка решения
(вычисления истинно ли или ложно выражение) была выполнена и протестирована;

·       
покрытие путей — все ли возможные пути
через заданную часть кода были выполнены и протестированы;

·       
покрытие функций — каждая ли функция
программы была выполнена;

·       
покрытие вход/выход — все ли вызовы
функций и возвраты из них были выполнены.

·       
покрытие значений параметров — все ли
типовые и граничные значения параметров были проверены.

Полная
система тестов позволяет утверждать, что система реализует всю
функциональность, указанную в требованиях, и, что еще более важно – не
реализует никакой другой функциональности. Степень покрытия программного кода
тестами – важный количественный показатель, позволяющий оценить качество
системы тестов, а в некоторых случаях – и качество тестируемой программной
системы.

Одним
из наиболее часто используемых методов определения полноты системы тестов
является определение отношения количества тест-требований, для которых
существуют тестовые примеры, к общему количеству тест-требований, — т.е. в
данном случае речь идет о покрытии тестовыми примерами тест-требований. В
качестве единицы измерения степени покрытия здесь выступает процент
тест-требований, для которых существуют тестовые примеры, называемый процентом
покрытых тест-требований. Покрытие требований позволяет оценить степень полноты
системы тестов по отношению к функциональности системы, но не позволяет оценить
полноту по отношению к ее программной реализации. Одна и та же функция может
быть реализована при помощи совершенно различных алгоритмов, требующих разного
подхода к организации тестирования.

Для
более детальной оценки полноты системы тестов при тестировании стеклянного
ящика анализируется покрытие программного кода, называемое также структурным
покрытием.

Во
время работы каждого тестового примера выполняется некоторый участок
программного кода системы, при выполнении всей системы тестов выполняются все
участки программного кода, которые задействует эта система тестов. В случае,
если существуют участки программного кода, не выполненные при выполнении
системы тестов, система тестов потенциально неполна (т.е. не проверяет всю
функциональность системы), либо система содержит участки защитного кода или
неиспользуемый код (например, «закладки» или задел на будущее
использование системы). Таким образом, отсутствие покрытия каких-либо участков
кода является сигналом к переработке тестов или кода (а иногда – и требований).

К
анализу покрытия программного кода можно приступать только после полного
покрытия требований. Полное покрытие программного кода не гарантирует того, что
тесты проверяют все требования к системе. Одна из типичных ошибок начинающего
тестировщика – начинать с покрытия кода, забывая про покрытие требований.

Тестирование
скорости загрузки системы

Хорошая
скорость загрузки страницы — 0.35–0.38 секунд. Такие результаты показывают
сайты в топе выдачи. Чтобы посчитать это время, нужно измерить так называемую
«скорость ответа сервера» — как быстро он реагирует на запрос клиента
(браузера).

Вебмастеры
измеряют скорость загрузки с помощью различных сервисов — платных и бесплатных.

Google
PageSpeed Insights бесплатно измеряет скорость загрузки и на мобильных, и на
стационарных устройствах. Рейтинг определяется по 100-балльной шкале: чем
больше баллов, тем лучше. Если ваш сайт получил более 85, значит, все хорошо.
Не стремитесь получить 100 баллов. Это не удается даже сервисам Google.

Яндекс.Вебмастер

Посмотреть
скорость ответа сервера на запрос робота «Яндекса» можно с помощью инструмента
webmaster.yandex.ru. Он покажет время ответа в миллисекундах: Если код ответа —
«200 ОК», с сайтом все в порядке. Если какой-то другой («404 Not Found», «301
Moved Permanently»), у вас проблемы. Как и у Google, у «Яндекса» это бесплатный
сервис, которым можно пользоваться без регистрации и глубокого понимания
бекенда.

Pingdom

Сервис
pingdom.com предоставляет более подробную информацию для тестирования сайтов,
чем перечисленные выше. Кроме оценки общей скорости сайта, Pingdom покажет, с
какой скоростью загружается каждый элемент страницы. Если на сайте возникли
неполадки, Pingdom пришлет уведомление. Есть приложения для Android и iOS,
чтобы вы следили за скоростью ресурсов в режиме реального времени. Сервис
собирает статистику скорости за период времени и предоставляет подробный отчет
об ошибках. Самый большой минус Pingdom — то, что сервис платный.

Sitespeed.ru

Еще
один популярный инструмент в рунете — sitespeed.ru. Интерфейс простой и
понятный: пишешь URL, запускаешь тест, получаешь результат. Сервис дает
подробное описание, как справиться с каждой проблемой сайта. Еще одна любопытная
функция — каскадная диаграмма загрузки сайта: вы видите, сколько времени
загружается каждый объект: скорость загрузки сайта speedtest. Если оставить
почту на сайте, вам пришлют красивый подробный отчет по результатам
тестирования. И все это абсолютно бесплатно.

GTmetrix
позволяет легко определить производительность вашего сайта. Просто вставьте URL
на главную страницу и получите данные о скорости загрузки и рекомендации, как
исправить ошибки. Тестировать скорость можно из нескольких регионов. Кроме того,
сервис анализирует эффективность ресурса на мобильных устройствах. До трех URL
можно мониторить бесплатно. Больше сайтов можно подключить на премиум-тарифах
(от $14,95 в месяц). Они включают и другие интересные возможности, например,
брендированные отчеты о скорости сайта и запись видео с загрузкой, чтобы
увидеть узкие места в режиме реального времени.

YSlow

YSlow
анализирует веб-страницы и определяет, что идет не так по правилам Yahoo для
высокопроизводительных сайтов. Это расширение, которое можно установить на
популярные браузеры: Firefox, Chrome, Opera, Safari. Сервис бесплатный сервис и
с открытым кодом. YSlow оценивает веб-страницу, обобщает компоненты и
статистику, предлагает улучшения и предоставляет инструменты для анализа
производительности.

WebPagetest
— еще один бесплатный проект с открытым исходным кодом. Его особенность —
широкий выбор локаций, гаджетов и браузеров для тестирования. Можно подобрать
параметры, которые лучше всего соответствуют вашей целевой аудитории: оценка
скорости загрузки сайта WebPagetest. По результатам тестирования получаем
огромный отчет прямо на странице сервиса.

Тестирование
функциональных требований. Комплексное тестирование

Комплексное
тестирование — процесс поиска несоответствия системы ее исходным целям. В процессе
тестирования участвует система, описание целей продукта и вся документация,
поставляемая вместе с системой.

Следующие
15 пунктов дают некоторое представление о том, какие виды тестов могут
понадобиться.

1.
Тестирование стрессов. Как правило, системы функционируют нормально при слабой
или умеренной нагрузке, но выходят из строя при большой нагрузке и в стрессовых
ситуациях реальной среды. Тестирование стрессов представляет собой попытки
подвергнуть систему крайнему «давлению», например, попытку одновременно
подключить к системе большое количество терминалов, насытить банковскую систему
мощным потоком входных сообщений.

2.
Тестирование объема представляет собой попытку предъявить системе большие
объемы данных в течение более длительного времени, чем п. 1. На вход
компилятора следует подать огромную программу (например, программу обработки
текстов). Очередь заданий операционной системы следует заполнить до предела.
Цель — показать, что система не может обрабатывать данные в количествах,
указанных в их спецификациях.

3.
Тестирование конфигурации. Система должна быть проверена со всяким аппаратным
устройством, которое она обслуживает, или со всякой программой, с которой она
должна взаимодействовать. Если сама программная система допускает несколько
конфигураций, должна быть тестирована каждая из них.

4.
Тестирование совместимости. Как правило, разрабатываемые системы не являются
совершенно новыми; они представляют собой улучшение прежних версий или замену
устаревших. Тогда на систему накладывается дополнительное требование
совместимости, в соответствии с которым взаимодействие пользователя с прежней
версией должно полностью сохраниться и в новой системе.

5.
Тестирование защиты. К большинству систем предъявляются определенные требования
по обеспечению защиты от несанкционированного доступа. Цель тестирования защиты
— нарушить секретность в системе. Один из методов — нанять профессиональную
группу «взломщиков», т. е. людей с опытом разрушения средств обеспечения защиты
в системах. Одним из путей разработки подобных тестов является изучение
известных проблем защиты в этих системах и генерация тестов, которые позволяют
проверить, как решаются аналогичные проблемы в тестируемой системе.

6.
Тестирование требований к памяти. При проектировании многих систем ставятся цели,
определяющие объем основной и вторичной памяти, которую системе разрешено
использовать при различных условиях. С помощью специальных тестов нужно
попытаться показать, что система этих целей не достигает.

7.
Тестирование производительности. Определяются такие характеристики, как время
отклика и уровень пропускной способности при определенной нагрузке и
конфигурации оборудования. Проверка системы в этих случаях сводится к
демонстрации того, что данная программа не удовлетворяет поставленным целям.

8.
Тестирование настройки. Тестирование процесса настройки системы очень важно,
поскольку зачастую покупатель оказывается не в состоянии даже настроить новую
систему.

9.
Тестирование надежности/готовности заключается в попытке доказать, что система
не удовлетворяет исходным требованиям к надежности (среднее время между
отказами, количество ошибок, способность к обнаружению, исправлению ошибок
и/или устойчивость к ошибкам и т. д.). Например, в систему можно намеренно
внести ошибки (как аппаратные, так и программные), чтобы тестировать средства
обнаружения, исправления и обеспечения устойчивости.

10.
Тестирование средств восстановления. Можно намеренно ввести в операционную
систему программные ошибки, чтобы проверить, восстановится ли она после их
устранения. Неисправности аппаратуры, ошибки в данных (помехи в линиях связи и
неправильные значения указателей в базе данных) можно намеренно создать или
промоделировать для анализа реакции на них системы.

11.
Тестирование удобства обслуживания. Все документы, описывающие внутреннюю
логику, следует проанализировать глазами обслуживающего персонала, чтобы
понять, как быстро и точно можно указать причину ошибки, если известны только
некоторые се симптомы.

12.
Тестирование публикаций. Все комплексные тесты следует строить только на основе
документации для пользователя. Любые примеры, приведенные в документации,
следует оформить как тест и подать на вход программы.

13.
Тестирование психологических факторов. Эта сторона не так важна, как другие,
однако мелкие недостатки могут быть обнаружены и устранены при тестировании
системы. Например, может оказаться, что ответы или сообщения системы плохо
сформулированы или ввод команды пользователя требует постоянных переключений
регистров.

14.
Тестирование удобства установки.

15.
Тестирование удобства эксплуатации.

Не
все из перечисленных 15 пунктов применимы к тестированию всякой системы
(например, когда тестируется отдельная прикладная программа), но тем не менее
это перечень вопросов, которые разумно иметь в виду.

По
своей природе комплексные тесты никогда не сводятся к проверке отдельных
функций системы. Они часто пишутся в форме сценариев, представляющих ряд
последовательных действий пользователя.

Тестирование
граничных условий

Граничные
значения — это те места, в которых один класс эквивалентности переходит в
другой.

Техника
анализа граничных значений — это техника проверки поведения продукта на крайних
(граничных) значениях входных данных. Граничное тестирование также может
включать тесты, проверяющие поведение системы на входных данных, выходящих за
допустимый диапазон значений. При этом система должна определённым (заранее
оговоренным) способом обрабатывать такие ситуации. Например, с помощью
исключительной ситуации или сообщения об ошибке.

!!!Граничные
значения очень важны и их обязательно следует применять при написании тестов,
т.к. именно в этом месте чаще всего и обнаруживаются ошибки.

На
каждой границе диапазона следует проверить по три значения:

·       
граничное значение;

·       
значение перед границей;

·       
значение после границы.

Цель
этой техники — найти ошибки, связанные с граничными значениями.

Алгоритм
использования техники граничных значений:

·       
выделить классы эквивалентности;

·       
определить граничные значения этих
классов;

·       
нужно понять, к какому классу будет
относиться каждая граница;

·       
нужно провести тесты по проверке значения
до границы, на границе и сразу после границы.

Количество
тестов для проверки граничных значений будет равен количеству границ,
умноженному на 3. Рекомендуется проверять значения вплотную к границе. К
примеру, есть диапазон целых чисел, граница находится в числе 100. Таким
образом, будем проводить тесты с числом 99 (до границы), 100 (сама граница),
101 (после границы).

Тестирование
утечки памяти

Все
программы в рамках популярных ОС представляют собой определенным образом
структурированный набор данных и инструкций. ОС знает, как работать с этими
наборами данных и инструкций, и делает это в некотором заведенном порядке. В
рамках ОС для этого есть объект — процесс, который подгрузит приготовленные
разработчиком инструкции и данные, будет определенным образом выделять под них
время процессора, порождать другие объекты ядра ОС, которые тоже что-то делают.

Сами
инструкции так же могут взаимодействовать с разными сущностями операционной
системы, файловой системой, порождать потоки, с периферией, выводить что-то на
экран, взаимодействовать при работе с оперативной памятью. Все эти ресурсы, или
многие из них — разделяемые. Например, вывод на экран, т.к. экран один. Или
работа с памятью, т.к. ее конечное количество. И все это делается через API ОС
напрямую, или через какие-то обертки над этим API ОС.

И
раз память можно выделять, ее следует и освобождать, т.е. уведомлять ОС, что
этот участок памяти «свободен», и может быть отдан любому другому
процессу под его нужды. Контроль за тем, нужна ли программе еще та или иная
память остается на усмотрение программы, ОС этим, естественно, не управляет.

И
раз управление выделенной памятью находится на стороне программы, программа
может быть построена так, что иногда будет уведомлять ОС о том, чтобы выделить
ей какую-то память, но не уведомлять об освобождении.

В
цикле это приводит к тому, что со временем объем используемой программой памяти
начинает бесконечно расти.

Явный
признак — наличие ошибки OutOfMemoryError в Java или OutOfMemoryException в
.NET. Ее можно найти в логах сервера или приложения, либо сообщение о нем будет
выведено на экран. В разных языках программирования название ошибки может
выглядеть иначе, но смысл её будет прежним — Недостаточно памяти для завершения
операции.

Утечка
памяти может воспроизвестись по-разному, в зависимости от того в какой части
системы она поселилась, а также самой реализации приложения.

Иногда
причина возникновения OutOfMemoryError — это недостаточное выделение памяти
приложению. Допустим для загрузки всех объектов в память требуется 128Мб, а
приложению выделили только 64Мб.

Если
же с конфигурацией все в порядке, а размер используемой памяти постоянно
увеличивается, то это реальный memory leak.

Для
начала, как и с любым багом его нужно локализовать, т.е. определить в каких
случаях, какая операция вызывает эту проблему. И уже потом её решать.

Наиболее
сложно отлавливаемый memory leak — это тот, который кушает мало и
воспроизводится очень долго. Подобная утечка памяти определима только при
запуске длительных тестов (тестов стабильности).

Тема
3.4 Тестирование отдельных модулей

Инструментарии
анализа качества программных продуктов в среде разработки.

Software
Quality Assurance (SQA) — это комплекс мероприятий по обеспечению качества в
процессах разработки программного обеспечения. Это гарантирует, что
разработанное программное обеспечение соответствует и соответствует
определенным или стандартизированным спецификациям качества. SQA — это
непрерывный процесс в рамках жизненного цикла разработки программного
обеспечения (SDLC), который регулярно проверяет разработанное программное
обеспечение, чтобы убедиться, что оно соответствует требуемым показателям
качества.

Практики
SQA применяются в большинстве типов разработки программного обеспечения независимо
от используемой модели разработки программного обеспечения. SQA включает и
внедряет методологии тестирования программного обеспечения для тестирования
программного обеспечения. Вместо проверки качества после завершения, SQA
обрабатывает тест на качество на каждом этапе разработки, пока программное
обеспечение не будет завершено. С SQA процесс разработки программного
обеспечения переходит в следующую фазу только тогда, когда текущая / предыдущая
фаза соответствует требуемым стандартам качества. SQA обычно работает над одним
или несколькими отраслевыми стандартами, которые помогают в разработке
рекомендаций по качеству программного обеспечения и стратегий реализации.

Включает
в себя следующие виды деятельности:

·       
Определение и реализация процесса

·       
Аудиторская проверка

·       
Повышение квалификации

Могут
проводиться процессы:

·       
Методология разработки программного
обеспечения

·       
Управление проектом

·       
Управление конфигурацией

·       
Разработка требований / Управление

·       
Предварительный расчет

·       
Разработка программного обеспечения

·       
Тестирование и др.

После
того, как процессы определены и внедрены, Контроль качества выполняет следующие
обязанности:

·       
Выявить слабые места в процессах

·       
Исправить эти недостатки, чтобы постоянно
улучшать процесс

Выявление
ошибок системных компонентов.

Одной
из основных причин изменений комплексов программ являются организационные
дефекты при модификации и расширении функций ПС, которые отличаются от
остальных типов и условно могут быть выделены как самостоятельные. Ошибки и
дефекты данного типа появляются из-за недостаточного понимания коллективом
специалистов технологии процесса ЖЦ ПС, а также вследствие отсутствия четкой
его организации и поэтапного контроля качества продуктов и изменений.

Изменения
характеристик системы и внешней среды, принятые в процессе разработки ПС за
исходные, могут быть результатом аналитических расчетов, моделирования или
исследования аналогичных систем. В ряде случаев может отсутствовать полная
адекватность предполагаемых и реальных характеристик, что является причиной
сложных и трудно обнаруживаемых системных ошибок, и дефектов развития проекта.
Ситуация с такими ошибками дополнительно усложняется тем, что эксперименты по
проверке взаимодействия ПС с реальной внешней средой во всей области изменения
параметров зачастую сложны и дороги, а в отдельных случаях, при создании
опасных ситуаций, недопустимы.

Сложность
проявления, обнаружения и устранения ошибок значительно конкретизируется и
становится измеримой, когда устанавливается связь этого понятия с конкретными
ресурсами, необходимыми для решения соответствующей задачи, и возможными
проявлениями дефектов. При разработке и сопровождении программ основным
лимитирующим ресурсом обычно являются допустимые трудозатраты специалистов, а
также ограничения на сроки разработки, параметры ЭВМ, технологию проектирования
корректировок ПС. Показатели сложности при анализе можно разделить на две
большие группы:

·       
сложность ошибок при создании
корректировок компонентов и комплекса программ — статическая сложность, когда
реализуются его требуемые функции, вносятся основные дефекты и ошибки;

·       
сложность проявления ошибок
функционирования программ и получения результатов — динамическая сложность,
когда проявляются дефекты и ошибки, отражающиеся на функциональном назначении,
рисках и качестве применения версии ПС.

Системные
ошибки в ПС определяются, прежде всего, неполной информацией о реальных
процессах, происходящих в источниках и потребителях информации. Кроме того, эти
процессы зачастую зависят от самих алгоритмов и поэтому не могут быть
достаточно определены и описаны заранее без исследования изменений
функционирования ПС во взаимодействии с внешней средой. На начальных этапах не
всегда удается точно и полно сформулировать целевую задачу всей системы, а
также целевые задачи основных групп программ, и эти задачи уточняются в
процессе проектирования. В соответствии с этим уточняются и конкретизируются
спецификации на отдельные компоненты и выявляются отклонения от уточненного
задания, которые могут квалифицироваться как системные ошибки.

Характеристики
внешних объектов, принятые в качестве исходных данных в процессе разработки
алгоритмов, могут являться результатом аналитических расчетов, моделирования
или исследования аналогичных систем. Во всех случаях может отсутствовать полная
адекватность условий получения предполагаемых и реальных характеристик внешней
среды, что является причиной сложных и трудно обнаруживаемых ошибок. Это
усугубляется тем, что очень часто невозможно заранее предусмотреть все
разнообразие возможных внешних условий и реальных сценариев функционирования и
применения версий программного продукта.

При
автономной и в начале комплексной отладки версий ПС относительная доля
системных ошибок может быть невелика (около 10%), но она существенно возрастает
(до 35—40%) на завершающих этапах комплексной отладки новых базовых версий ПС.

Методы
идентификации сбоев и ошибок

Ошибка
(error) — состояние программы, при котором выдаются неправильные результаты,
причиной которых являются изъяны (flaw) в операторах программы или в технологическом
процессе ее разработки, что приводит к неправильной интерпретации исходной
информации, следовательно, и к неверному решению.

Дефект
(fault) в программе — следствие ошибок разработчика на любом из этапов
разработки, которая может содержаться в исходных или проектных спецификациях,
текстах кодов программ, эксплуатационной документация и т.п. В процессе
выполнения программы может быть обнаружен дефект или сбой.

Отказ
(failure) — это отклонение программы от функционирования или невозможность программы
выполнять функции, определенные требованиями и ограничениями, что
рассматривается как событие, способствующее переходу программы в
неработоспособное состояние из-за ошибок, скрытых в ней дефектов или сбоев в
среде функционирования.

Отказ
может быть результатом следующих причин:

·       
ошибочная спецификация или пропущенное
требование, означающее, что спецификация точно не отражает того, что
предполагал пользователь;

·       
спецификация может содержать требование,
которое невозможно выполнить на данной аппаратуре и программном обеспечении;

·       
проект программы может содержать ошибки
(например, база данных спроектирована без средств защиты от
несанкционированного доступа пользователя, а требуется защита);

·       
программа может быть неправильной, т.е.
она выполняет несвойственный алгоритм или он реализован не полностью.

Таким
образом, отказы, как правило, являются результатами одной или более ошибок в
программе, а также наличия разного рода дефектов.

Все
ошибки, которые возникают в программах, принято подразделять на следующие классы:

·       
логические и функциональные ошибки;

·       
ошибки вычислений и времени выполнения;

·       
ошибки ввода/вывода и манипулирования
данными;

·       
ошибки интерфейсов;

·       
ошибки объема данных и др.

Логические
ошибки являются причиной нарушения логики алгоритма, внутренней несогласованности
переменных и операторов, а также правил программирования. Функциональные ошибки
— следствие неправильно определенных функций, нарушения порядка их применения
или отсутствия полноты их реализации и т.д. Ошибки вычислений возникают по
причине неточности исходных данных и реализованных формул, погрешностей
методов, неправильного применения операций вычислений или операндов. Ошибки
времени выполнения связаны с необеспечением требуемой скорости обработки
запросов или времени восстановления программы. Ошибки ввода-вывода и
манипулирования данными являются следствием некачественной подготовки данных
для выполнения программы, сбоев при занесении их в базы данных или при выборке
из нее. Ошибки интерфейса относятся к ошибкам взаимосвязи отдельных элементов
друг с другом, что проявляется при передаче данных между ними, а также при
взаимодействии со средой функционирования. Ошибки объема относятся к данным и
являются следствием того, что реализованные методы доступа и размеры баз данных
не удовлетворяют реальным объемам информации системы или интенсивности их
обработки.

Анализ
типов ошибок в программах является необходимым условием создания планов
тестирования и методов тестирования для обеспечения правильности ПО.

Автоматизация
тестирования в продуктивной среде

Непрерывное
тестирование ускоряет поставку программного обеспечения, делая весь процесс
тестирования более быстрым. А благодаря незамедлительной обратной связи,
которая помогает уже на самых ранних этапах выявлять ошибки и другие проблемы в
приложении, гарантирует, что команды разработки будут создавать
высококачественные и надежные приложения. Кроме того, сама способность
организовать и проводить эффективное тестирование может значительно снизить
затраты в компании, как за счёт экономии времени разработчиков, так и
вследствие создания добротного конвейера поставки, в котором они могут быстро
вносить изменения в код с минимальными рисками нарушения работоспособности
приложения в продуктивной среде.

Главным
элементом непрерывного тестирования является его автоматизация, что даёт
множество преимуществ:

·       
Быстрое получение обратной связи

·       
Аккуратное и тщательное тестирование

·       
Высокое покрытие тестами

·       
Быстрое обнаружение ошибок

·       
Повторное использование тестов

·       
Более короткие сроки поставки

·       
Адаптация для DevOps

·       
Экономия времени и денег

Несмотря
на перечисленные выше преимущества, начальные вложения в автоматизацию
тестирования могут быть очень высоки. Приобретение ПО, затраты на обучение
работе с ним, проектирование и создание автоматизированных тестов — всё это
требует немалых времени и денег. Однако, как только вы начинаете всё активнее
разрабатывать новые функции в своём продукте, ручное тестирование в конечном
итоге выходит дороже, а автоматическое — дешевле.

Перед
планированием автоматизации тестирования нужно учесть несколько факторов. Вот
примеры тестов и сценариев, для которых не нужна автоматизация.

Пользовательский
опыт (UX) — Эта область тестирования не может быть автоматизирована. Многие
аспекты UX-проектирования требуют ручного, долгого и утомительного
тестирования. Например, когда разработчики хотят понять, насколько легко
пользователи могут зарегистрироваться на веб-сайте, или проверить, какие наборы
полей дают лучшую видимость профилей пользователей. Подобные тесты должны быть проведены
вручную.

Стадии
ранней разработки — Когда какая-то функция только-только разрабатывается, в её
код постоянно вносятся изменения, а это может затруднить составление и теста.
На ручное тестирование этих функций уходит меньше времени, поэтому следует дождаться
стабильной версии.

Функциональность,
не имеющая большой важности — Автоматизация тестирования требует времени и
усилий, поэтому следует автоматизировать тестирование не всех функций,
разрабатываемых в рамках проекта, а лишь самых важных функций. Низкоприоритетные
можно оставить в стороне и продолжить тестировать их вручную.

Тесты
без понятных результатов — Командам разработки необходимо знать ожидаемый
результат для каждого входа функции. Если результаты непонятны, то и
автоматизация не предоставит необходимых доказательств того, что функция
работает должным образом.

Тема
3.5 Реинжиниринг бизнес-процессов в информационных системах

Сущность
реинжиниринга бизнес-процессов. Этапы реинжиниринга

Инжиниринг
бизнеса — это набор приемов и методов, которые компания использует для
проектирования бизнеса в соответствии со своими целями.

Реинжиниринг
— это фундаментальное переосмысление и радикальное перепроектирование деловых
процессов для достижения резких, скачкообразных улучшений главных современных
показателей деятельности компании, таких, как стоимость, качество, сервис и
темпы (термин «реинжиниринг» ввел М. Хаммер).

Это
определение содержит четыре ключевых слова: «фундаментальный», «радикальный»,
«резкий (скачкообразный)» и «процесс» (наиболее важное слово).

1.
Фундаментальный. На начальной стадии реинжиниринга необходимо ответить на такие
основные вопросы:

·       
почему компания делает то, что она делает?

·       
почему компания делает это таким способом?

·       
какой хочет стать компания?

Отвечая
на эти вопросы, специалисты должны переосмыслить текущие правила и положения
(зачастую не сформулированные в письменной форме) ведения бизнеса и часто
оказывающиеся устаревшими, ошибочными или неуместными.

2.
Радикальный. Радикальное перепроектирование — это изменение всей существующей
системы, а не только поверхностные преобразования, т.е. входе радикального
перепроектирования предлагаются совершенно новые способы выполнения работы.

3.
Резкий (скачкообразный). Реинжиниринг не применяется в тех случаях, когда
необходимо улучшение либо увеличение показателей деятельности компании на
10-100%, а используются более традиционные методы (от произнесения
зажигательных речей перед сотрудниками до проведения программ повышения
качества), применение которых не сопряжено со значительным риском. Реинжиниринг
целесообразен только в тех случаях, когда требуется достичь резкого
(скачкообразного) улучшения показателей деятельности компании (500-1000% и
более) путем замены старых методов управлении новыми.

Смысл
реинжиниринга бизнес-процессов в двух его основных этапах:

·       
определение оптимального (идеального) вида
бизнес-процесса (в первую очередь основного);

·       
определение наилучшего (по средствам,
времени, ресурсам и т. п.) способа перевода существующего бизнес-процесса в
оптимальный.

Порядок
проведения:

·       
Разработка корпоративной стратегии;

·       
Определение ключевых компетенций, которые
необходимы для внедрения стратегии;

·       
Подробный анализ существующих процессов;

·       
Выявление процессов, требующих изменения;

·       
Определение ключевых показателей
эффективности для бизнес-процессов;

·       
Собственно реинжиниринг;

·       
Контроль и постоянное совершенствование
новых процессов на основе ключевых показателей эффективности.

Изучение
методологии структурного системного анализа

Методология
структурного анализа и проектирования ПО определяет шаги работы, которые должны
быть выполнены, их последовательность, правила распределения и назначения
операций и методов. В настоящее время успешно используются такие методологии,
как SADT (Structure Analysis and Design Technique), структурный системный
анализ Гейна-Сарсона, структурный анализ и проектирование Йодана/Де Марко,
развитие систем Джексона и другие.

Перечисленные
структурные методологии жестко регламентируют фазы анализа требований и
проектирования спецификаций и отражают подход к разработке ПО с позиций
рецептов «кулинарной книги».

Несмотря
на достаточно широкий спектр используемых методов и диаграммных техник,
большинство методологий базируется на следующей «классической»
совокупности:

Диаграммы
потоков данных в нотации Йодана/Де Марко или Гейна-Сарсона, обеспечивающие
анализ требований и функциональное проектирование информационных систем;

Расширения
Хатли и Уорда-Меллора для проектирования систем реального времени, основанные
на диаграммах переходов состояний, таблицах решений, картах и схемах потоков
управления;

Диаграммы
«сущность-связь» (в нотации Чена или Баркера) для проектирования
структур данных, схем БД, форматов файлов как части всего проекта;

Структурные
карты Джексона и/или Константайна для проектирования межмодульных взаимодействий
и внутренней структуры модулей.

Разработка
ПО основана на модели ВХОД-ОБРАБОТКА-ВЫХОД: данные входят в систему,
обрабатываются или преобразуются и выходят из системы. Такая модель
используется во всех структурных методологиях. При этом важен порядок
построения модели. Традиционный процедурно-ориентированный подход
регламентирует первичность проектирования функциональных компонент по отношению
к проектированию структур данных: требования к данных раскрываются через
функциональные требования. При подходе, ориентированном на данные, вход и выход
являются наиболее важными – структуры данных определяются первыми, а
процедурные компоненты являются производными от данных.

Основные
методологии обследования организаций

Понятие
«моделирование бизнес-процессов» пришло в быт большинства аналитиков
одновременно с появлением на рынке сложных программных продуктов,
предназначенных для комплексной автоматизации управления предприятием. Подобные
системы всегда подразумевают проведение глубокого предпроектного обследования
деятельности компании.

Для
решения подобных задач моделирования сложных систем существуют хорошо
обкатанные методологии и стандарты. К таким стандартам относятся методологии
семейства IDEF. С их помощью можно эффективно отображать и анализировать модели
деятельности широкого спектра сложных систем в различных разрезах. При этом
широта и глубина обследования процессов в системе определяется самим
разработчиком, что позволяет не перегружать создаваемую модель излишними
данными.

В
настоящий момент к семейству IDEF можно отнести следующие стандарты:

IDEF0
— методология функционального моделирования. С помощью наглядного графического
языка IDEF0, изучаемая система предстает перед разработчиками и аналитиками в
виде набора взаимосвязанных функций (функциональных блоков — в терминах IDEF0).
Как правило, моделирование средствами IDEF0 является первым этапом изучения
любой системы;

IDEF1
– методология моделирования информационных потоков внутри системы, позволяющая
отображать и анализировать их структуру и взаимосвязи;

IDEF1X
(IDEF1 Extended) – методология построения реляционных структур. IDEF1X
относится к типу методологий “Сущность-взаимосвязь” (ER – Entity-Relationship)
и, как правило, используется для моделирования реляционных баз данных, имеющих
отношение к рассматриваемой системе;

IDEF2
– методология динамического моделирования развития систем. В связи с весьма
серьезными сложностями анализа динамических систем от этого стандарта
практически отказались, и его развитие приостановилось на самом начальном
этапе. Однако в настоящее время присутствуют алгоритмы и их компьютерные
реализации, позволяющие превращать набор статических диаграмм IDEF0 в
динамические модели, построенные на базе “раскрашенных сетей Петри” (CPN –
Color Petri Nets);

IDEF3
– методология документирования процессов, происходящих в системе, которая
используется, например, при исследовании технологических процессов на
предприятиях. С помощью IDEF3 описываются сценарий и последовательность
операций для каждого процесса. IDEF3 имеет прямую взаимосвязь с методологией
IDEF0 – каждая функция (функциональный блок) может быть представлена в виде
отдельного процесса средствами IDEF3;

IDEF4
– методология построения объектно-ориентированных систем. Средства IDEF4
позволяют наглядно отображать структуру объектов и заложенные принципы их
взаимодействия, тем самым позволяя анализировать и оптимизировать сложные
объектно-ориентированные системы;

IDEF5
– методология онтологического исследования сложных систем. С помощью
методологии IDEF5 онтология системы может быть описана при помощи определенного
словаря терминов и правил, на основании которых могут быть сформированы
достоверные утверждения о состоянии рассматриваемой системы в некоторый момент
времени. На основе этих утверждений формируются выводы о дальнейшем развитии
системы и производится её оптимизация.

Особенности
национальной практики применения функционального моделирования

В
последние годы интерес в России к методологиям семейства IDEF неуклонно растет.
Первые Case-средства, позволяющие строить DFD и IDEF0 диаграммы появились на
российском рынке еще в 1996 году.

Тем
не менее, большинство руководителей до сих пор расценивают практическое
применение моделирования в стандартах IDEF скорее, как дань моде, нежели чем
эффективный путь оптимизации существующей системы управления бизнесом.
Вероятнее всего это связано с ярко выраженным недостатком информации по
практическому применению этих методологий.

Не
секрет, что практически все проекты обследования и анализа финансовой и
хозяйственной деятельности предприятий сейчас в России так или иначе связаны с
построением автоматизированных систем управления. Благодаря этому, стандарты
IDEF в понимании большинства стали условно неотделимы от внедрения
информационных технологий, хотя с их помощью порой можно эффективно решать даже
небольшие локальные задачи, буквально при помощи карандаша и бумаги.

При
проведении сложных проектов обследования предприятий, разработка моделей в
стандарте IDEF0 позволяет наглядно и эффективно отобразить весь механизм
деятельности предприятия в нужном разрезе. Однако самое главное – это
возможность коллективной работы, которую предоставляет IDEF0. Построение модели
можно осуществлять с прямой помощью сотрудников различных подразделений. При
разработке IDEF-диаграммы деятельности своих функциональных подразделений
необходимо дать ответы на следующие вопросы:

·       
Что поступает в подразделение “на входе”?

·       
Какие функции, и в какой
последовательности выполняются в рамках подразделения?

·       
Кто является ответственным за выполнение
каждой из функций?

·       
Чем руководствуется исполнитель при
выполнении каждой из функций?

·       
Что является результатом работы
подразделения (на выходе)?

Причины
реинжиниринга информационных систем

Главной
причиной реинжиниринга информационной системы является расхождение между
требованиями к информационной системе со стороны предприятия и ее
действительными характеристиками. Такое расхождение имеет тенденцию к
нарастанию со временем. Относительно небольшое расхождение позволяет говорить о
необходимости модернизации ИС, сильное – о необходимости реинжиниринга
информационной системы.

Основными
причинами, также приводящими к реинжинирингу информационных систем, являются:

·       
моральное устаревание информационной
системы (информационных технологий, пользовательских и программных интерфейсов,
используемых в составе ИС);

·       
физическое устаревание информационной
системы (износ ее аппаратных компонентов);

·       
причины организационного характера
(связанные с окружением информационной системы, бизнес-процессами предприятия,
пользователями системы).

Моральное
устаревание ИС в основном вызвано появлением более эффективных информационных
технологий (ИТ); новых способов организации пользовательского интерфейса; новых
решений в области архитектуры информационной системы; вычислительных устройств
с более высокой производительностью; новых носителей информации (более дешевых,
с большим быстродействием, позволяющих хранить больше информации).

Физическое
устаревание ИС в основном вызвано физическим износом используемого аппаратного
обеспечения (снижением надежности, увеличением количества сбоев); ухудшением
характеристик производительности аппаратного обеспечения (снижение
быстродействия из-за больших объемов накопленной информации).

Основной
причиной организационного характера для реинжиниринга информационной системы
является развитие предприятия (как штатным образом, так и в результате
реинжиниринга бизнес-процессов), совершенствование его бизнес-процессов. Все
это требует обновления и развития информационной поддержки бизнес-процессов
предприятия. Кроме того, постоянно растет квалификация персонала, что позволяет
внедрять более сложные информационные технологии и проводить информатизацию все
новых сфер деятельности.

Часто
причиной реинжиниринга ИС является реинжиниринг бизнес-процессов. И наоборот,
реинжиниринг ИС часто приводит к РБП. В любом случае, реинжиниринг ИС требует
коррекции бизнес-процессов предприятия.

Первой
волной реинжиниринга информационных систем в нашей стране можно считать
массовый перевод систем с морально устаревшей платформы операционной системы MS
DOS (частично также с MS Windows 3.x) на более современные MS Windows 9x, NT во
второй половине 90-х годов прошлого века. Эта волна также вызвана началом
поставки в Российскую федерацию более новых персональных компьютеров.

Вторая
волна, в основном, вызвана бурным развитием веб-технологий, широком
распространении и удешевлении Интернет. Сменилась также парадигма
информационных систем. Получили распространение концепции сервисов
(веб-сервисов) и клиент-серверного взаимодействия (как отдельных подсистем, так
и целых систем).

Список
использованных источников

1.    
Антамошкин, О.А. Программная инженерия.
Теория и практика : учебник /О.А. Антамошкин ; Министерство образования и науки
Российской Федерации, Сибирский Федеральный университет. – Красноярск :
Сибирский федеральный университет, 2012. – 247с. : ил., табл., схем. – Режим
доступа: по подписке. –URL:
http://biblioclub.ru/index.php?page=book&id=363975 – Библиогр.: с. 240. –
ISBN 978-5-7638-2511-4.

2.    
Зубкова, Т.М. Технология разработки
программного обеспечения : учебное пособие / Т.М. Зубкова ; Министерство
образования и науки Российской Федерации, Федеральное государственное бюджетное
образовательное учреждение высшего образования «Оренбургский государственный
университет», Кафедра программного обеспечения

3.    
вычислительной техники и
автоматизированных систем. – Оренбург : ОГУ, 2017. – 469 с. : ил.– Режим
доступа: по подписке. – URL: http://biblioclub.ru/index.php?page=book&id=485553
–Библиогр.: с. 454-459. – ISBN 978-5-7410-1785-2

4.    
Извозчикова, В.В. Эксплуатация и
диагностирование технических и программных средств информационных систем :
учебное пособие / В.В. Извозчикова ; Министерство образования и науки
Российской Федерации, Оренбургский Государственный Университет, Кафедра
программного обеспечения вычислительной техники и автоматизированных систем.–
Оренбург : Оренбургский государственный университет, 2017. – 137 с. : ил. –
Режим доступа: по подписке. – URL: http://biblioclub.ru/index.php?page=book&id=481761
– Библиогр. в кн. –ISBN 978-5-7410-1746-3.

5.    
Ехлаков, Ю.П. Управление программными
проектами : учебное пособие / Ю.П. Ехлаков ; Министерство образования и науки
Российской Федерации, Томский Государственный Университет Систем Управления и
Радиоэлектроники (ТУСУР). – Томск : Эль Контент, 2014. – 140 с. : схем., табл.
– Режим доступа: по подписке. –
URL:http://biblioclub.ru/index.php?page=book&id=480462 – Библиогр.: с.
128-130. – ISBN 978-5-4332-0163-7.

Реферат: Коды с обнаружением и исправлением ошибок

Компьютер при передаче данных между устройствами и при выполнении вычислений может делать ошибки из-за сбоев и отказов аппаратуры. Если компьютер не оснащен средствами для обнаружения и исправления ошибок, то необнаруженные ошибки приводят к сколь угодно серьезным искажениям результатов вычислений, и компьютер становится источником дезинформации пользователей. В связи с этим большинство компьютеров оснащаются средствами, обеспечивающими контроль работоспособности аппаратуры компьютеров за счет увеличения длины байтов, слов и сегментов данных на некоторое число битов, с помощью которых обеспечивается возможность обнаружения и исправления ошибок в передаваемых и обрабатываемых данных, т.е. за счет использования специальным образом представленных данных – кодированных байтов, слов и сегментов.

Наиболее простой способ кодирования данных – присоединение к данным одного бита четности. Например, байт данных представляется двоичной последовательностью

10110011.

Бит четности формируется за счет присоединения к байту одного бита, формируемого следующим образом: если число единиц в байте четно, то бит четности равен 0, если число единиц в байте нечетно, то бит четности равен 1. Таким образом, указанный байт с битом четности имеет следующую структуру:

10110011 1 ,

Байт Бит

четности

где бит имеет значение 1. Ясно, что при указанном правиле вычисления значения бита четности, число битов в кодированном байте всегда четно, в результате чего всякая одиночная ошибка в кодированном байте будет обнаружена. Впрочем, будут обнаружены и 3-, 5-, 7- и 9-кратные ошибки, но не поддаются обнаружению 2-, 4- и 8- кратные ошибки. Бит четности формируется аппаратурой компьютера крайне просто и обеспечивает защиту от многих ошибок.

Для обнаружения и исправления ошибок теория информации предлагает значительное число различных методов. Ясно, что с увеличением длины данных, определяемой длиной битов в данных, должно увеличиваться число контрольных разрядов, присоединяемых к данным для обнаружения и исправления ошибок. Число контрольных разрядов, необходимое для кода, способного обнаруживать и исправлять ошибки по методу Хэмминга, представлено в табл. 3.1.

Таблица 3.1.Число контрольных разрядов кода, способного обнаруживать и исправлять ошибки

Длина данных, бит Количество контрольных разрядов, бит Общая длина данных, бит Увеличение длины данных, %

Из таблицы видно, что для обнаружения и исправления одиночной ошибки к байту данных необходимо добавить четыре контрольных разряда, в результате чего длина кодирование сегмента данных будет равна 12 разрядам при увеличении длины кодирования сегмента на 50%. Из последующих строк таблицы видно, что при увеличении длины сегмента в 2 раза, количество контрольных разрядов увеличивается только на единицу, в результате чего процент увеличения длины данных уменьшается. При длине данных 1024 битов для исправления одиночных ошибок необходимо всего 11 разрядов, что приводит к увеличению длины контрольного сегмента всего на 1%. Естественно, что затраты оборудования для обнаружения и исправления единственной ошибки по методу Хэмминга значительно больше затрат оборудования при использовании бита четности. Однако при этом достигается существенный эффект – возможность исправления одной ошибки в работе компьютера.

Наряду с кодами Хэмминга, обеспечивающими обнаружение и исправление одной, двух и более ошибок в кодированных словах, широкое применение получили циклические коды, имеющие широкие возможности обнаружения и исправления при сложной картине многократных помех и достаточно простых способах построения систем контроля кодированных слов. Кодированные слова используются и для контроля арифметических и логических операций, выполняемых процессором. Таким образом, существует широкая гамма методов защиты устройств компьютеров от всякого рода искажений обрабатываемых и передаваемых данных, но любые системы защиты не дают 100% гарантии в результативности методов защиты.

6

Как уже упоминалось, программные сбои — результат неправильной работы программного обеспечения, а это означает, что от них всегда можно избавиться, причем разными путями.

Какого-то единого или универсального способа избавления от программных сбоев нет и быть не может, поскольку разнообразие этих сбоев ничем не ограничено: чем сложнее программа и используемые устройства, тем сложнее и разнообразнее сбои.

Тем не менее попробовать избавиться от сбоев можно выполнением некоторых действий в такой последовательности.

  • Анализ журнала событий. Любые события, несущие важные сведения, в том числе и ошибки программ, фиксируются в специальном системном журнале событий, который пользователь всегда может просмотреть и проанализировать. Чтобы получить к нему доступ, щелкните правой кнопкой мыши на значке Компьютер и в появившемся меню выберите пункт Управление. Далее откроется окно, в левой части которого необходимо раскрыть ветвь дерева Просмотр событий ► Журналы Windows. Все события отсортированы и разделены на пять групп, названия которых говорят сами за себя. Отследив порядок появления интересующего вас сбоя, можно вычислить его причину, а затем воспользоваться соответствующим способом его устранения.
  • Исправление системного реестра. Чем сложнее программа, тем больше вероятность, что она активно работает с реестром: сохраняет в нем нужные ей данные, а также использует их для своей инициализации и работы. Поэтому, если какая-то из программ «случайно» произвела некорректные изменения в той части реестра, в которой хранились нужные для первой программы данные, это может стать причиной ее неработоспособности или появления непонятных ошибок. Выход из ситуации — запуск специализированной утилиты, которая устранит все ошибки в реестре.
  • Замена драйвера. Немалую часть программных сбоев способны вызвать устаревшие драйверы устройств либо драйверы, которые пытаются расширить стандартную функциональность устройства, например включив возможность разгона видеокарты путем разблокировки механизма управления частотами. Если оборудование довольно новое, «правильный» драйвер всегда можно скачать с веб-сайта производителя этого оборудования.
  • Переустановка программы. Вычислив источник появления программного сбоя, то есть программу, которая его инициирует, можно попробовать ее переустановить. Это действие способно дать эффект, особенно если программа долго работала без сбоев и проблемы начались лишь недавно. Если же программа сбоит постоянно, лучше отказаться от ее использования либо найти ее новую версию или альтернативу.
  • Апгрейд программы. Программа, написанная для работы в операционной системе Windows ХР или даже Windows 98, изначально не подготовлена к работе в Windows 7/8. Поэтому, даже если запуск программы не был отвергнут системой из-за несовместимости, ее правильное функционирование будет под вопросом. Если причина именно в этом, лучшим решением будет переход на более новую версию программы либо замена ее альтернативным по функцио-нальности приложением.
  • Запуск в режиме совместимости. Если вы перешли на операционную систему Windows 7/8, но по какой-то причине не можете купить другую версию программы, которая успешно работала в Windows ХР, а в новой системе отказывается это делать или функционирует со сбоями, можно попробовать запускать ее в специальном режиме. Так, начиная с версии Windows 7, операционная система позволяет запускать программу в режиме совместимости с более ранними операционными системами, вплоть до Windows 95, хотя полной совместимости добиться невозможно. Чтобы выбрать режим совместимости, щелкните правой кнопкой мыши на ярлыке с программой, перейдите на вкладку Совместимость и выберите из списка нужную позицию.
  • Изменение прав доступа. Часто программные сбои и разного рода ошибки возникают в процессе работы программ в составе сети с доменом, когда у пользователя имеется самый простой набор прав доступа к ресурсам компьютера и сети. Большая часть программ, особенно непрофессионального уровня, не рассчитаны на подобное стечение обстоятельств и требуют максимального доступа к ресурсам. Выходом из этой ситуации является расширение прав доступа, например перевод пользователя в группу Опытные пользователи. Это может сделать только администратор сети или человек, знающий пароль администратора сети или локального администратора. Иногда Windows преднамеренно блокирует доступ к системному разделу диска, особенно к его корневой структуре. В этом случае в качестве рабочей папки программы можно использовать папку в любом другом, несистемном разделе диска.
  • Перезапуск программы. Да, как ни странно, но закрытие программы с последующим ее открытием может устранить возникшую проблему. Например, при просмотре интернет-страниц, особенно активно использующих flash-технологии, браузер Internet Explorer (до 8-й версии программы) может настолько раздуть файл подкачки, что это будет мешать не только его работе, но и функционированию остальных запущенных программ.

В этом случае можно закрыть браузер и открыть его снова — должно помочь. Если же программа не реагирует на любые действия, в том числе на нажатия кнопки закрытия окна, следует открыть Диспетчер задач, найти проблемное приложение в списке программ на вкладке Процессы и нажать кнопку Завершить процесс, тем самым принудительно выгрузив его из памяти и освободив все ресурсы, которые программа на себя перетянула. К сожалению, другие интернет-браузеры также страдают подобным поведением, хотя и в меньшей степени.

Это далеко не полный список способов обнаружения и устранения причины, а следовательно, и самого программного сбоя. Решение той или иной проблемы часто возникает само собой, поскольку многие программы сами предлагают такие пути решения. Кроме того, элементарное закрытие и открытие программы также способно помочь. Не стоит забывать и об Интернете: форумные сообщества и просто любители пообщаться обязательно помогут решить возникшую проблему.
 

Понравилась статья? Поделить с друзьями:
  • Метро ласт лайт ошибка при запуске
  • Методы защиты информации от ошибок пользователя
  • Метро ласт лайт ошибка msvcp110 dll
  • Методом проб и ошибок я научился
  • Метро ласт лайт ошибка 0xc000007b