2057

Создание автоматизированной системы для оптимизации процесса создания надежного программного обеспечения на языке JAVA

Контрольная

Информатика, кибернетика и программирование

Разработать программное обеспечение, реализующее возможность комплексного тестирования программ на языке Java. Программная система должна быть представлена в виде десктопного приложения и обладать интуитивно понятным графическим интерфейсом пользователя(ГИП).

Русский

2013-01-06

373.85 KB

7 чел.

Министерство образования и науки Украины

Севастопольский национальный технический университет

Кафедра кибернетики и

вычислительной техники

Итоговый отчет по НИРС

«Создание автоматизированной системы для оптимизации процесса создания надежного программного обеспечения на языке JAVA»

Выполнил:

ст. гр. М-43д

Трошин С.В.

Научный руководитель:

Сергеев Г.Г.

Севастополь

2012


Оглавление

ВВЕДЕНИЕ 3

1 ПОСТАНОВКА ЗАДАЧИ 4

2 ОПИСАНИЕ ПОДХОДА К РЕШЕНИЮ ЗАДАЧИ 7

2.1 ПРИНЦИПЫ РАБОТЫ РАЗРАБАТЫВАЕМОЙ СИСТЕМЫ 16

2.2 ИСПОЛЬЗУЕМЫЕ СТРУКТУРЫ 16

2.3 ОПИСАНИЕ ПАРСЕРА ИСХОДНОГО КОДА 16

3 ТЕКСТ ПРОГРАММЫ 17

4 РЕЗУЛЬТАТЫ РАБОТЫ ПРОГРАММЫ 22

ЗАКЛЮЧЕНИЕ 24

ПЕРЕЧЕНЬ ССЫЛОК 25


ВВЕДЕНИЕ

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

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

1 ПОСТАНОВКА ЗАДАЧИ

Разработать программное обеспечение, реализующее возможность комплексного тестирования программ на языке Java. Программная система должна быть представлена в виде десктопного приложения и обладать интуитивно понятным графическим интерфейсом пользователя(ГИП). Функционально, необходимо организовать возможность юнит-тестирования исходного кода программ и анализа полноты покрытия кода по критериям  С1 и Ср, а также реализовать возможность анализа пакетов программ с учетом особенностей систем, привлеченных для их сборки(Ant, Maven, NetBeans, Eclipse).  Результаты тестирования: степень покрытия графа управления методов классов тестовыми воздействиями, время выполнения методов классов и отдельных частей кода в частности, - необходимо отображать на ГИП.

2 вариант . Зря написал, теперь не могу определиться какой лучше.

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

В разработанной программе предусмотреть следующие особенности:

1). Реализовать разрабатываемый программный модуль в виде десктопного приложения, с удобным пользовательским интерфейсом;

2). Разбивать исходный код обрабатываемого проекта на карты классов, методов, операторов ветвления и прямого кода;

3). Использовать базу данных как хранилище для карт, промежуточных данных и результатов работы модуля;

4). Предусмотреть возможность прямой и обратной сборки текста из карт, соответствующих обрабатываемому проекту.

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

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


2 ОПИСАНИЕ ПОДХОДА К РЕШЕНИЮ ЗАДАЧИ

 

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

Пусть P - множество программных систем, T - множество тестов, а Σ - множество тестовых наборов, то есть множество всех конечных подмножеств множества T . Тогда задача генерации тестов может быть сформулирована следующим образом: для заданной тестируемой системы SP построить тестовый набор , удовлетворяющий заданному критерию полноты тестового покрытия. Тестовый набор для системы S удовлетворяет критерию полноты тестового покрытия F, если каждый элемент тестового покрытия из множества QSF покрывается хотя бы одним тестом из тестового набора .

Наиболее часто упоминаемые критерии полноты тестового покрытия: каждый оператор в исходном коде выполняется хотя бы один раз; каждая ветвь графа потока управления выполняется хотя бы один раз; каждый путь графа управления исполняется хотя бы один раз; каждое логическое выражение хотя бы один раз вычисляется со значением «истина» и хотя бы один раз - со значением «ложь». [2]

2.1 ПРИНЦИПЫ РАБОТЫ И ИПОЛЬЗУЕМЫЕ СТРУКТУРЫ.

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

Ключевые моменты, которые определяют особенности разработки системы:

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

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

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

Рисунок 1 - Структура карт программы

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

  1.  guid – уникальный идентификатор сформированный на основе исходного кода (число целого типа);
  2.  name – имя класса/метода  (строка);
  3.  text - модифицированный текст (строка);
  4.  textToShow - исходный текст класса (строка);

Помимо вышеуказанных полей в карте класса содержатся:

  1.  access –уровень доступа: public, private,  protected (число целого типа);
  2.  static - статичность (число целого типа);

Карта метода:

  1.  access –уровень доступа: public, private,  protected (число целого типа);
  2.  static - статичность (число целого типа);
  3.  guidClass – содержит  идентификатор класса-родителя.

Операторная карта:

  1.  type – тип операторной карты: if, if-else, while, do-while, for, switch, try-catch, вызов метода, оператор без ветвления;
  2.  method – содержит идентификатор метода-родителя.

Одной из особенностей разработанной системы является: работа с  базами данных, которая позволяет хранить карты, а также результаты исполнения всех проведенных тестовых испытаний над фрагментами кода. В программе используется СуБД MySQL. Доступ к инструментарию производится непосредственно из тестового модуля.

С точки зрения структурного подхода программу можно разделить на: классы, методы, участки прямого кода, операторы ветвления(if, if-else,while,switchи т.д.), вызовы методов. Каждый из перечисленных участков интерпретируем как отдельную вершину в графе управления (ГУ) программы. Таким образом, мы получаем последовательность вершин выстроенных по принципу доминирования (предок-потомок).

Результаты тестирования получают путем запуска модифицированного кода тестируемой программы. Механизм модификации состоит во внедрении в пользовательскую программу контрольных точек, с помощью,  которых происходит фиксация события пребывания программы в конкретной точке – вершине ГУ. По завершении работы метода (или при переполнении временного хранилища) вся собранная информация переносится в отдельную таблицу базы данных. Таким образом, при завершении тестирования из БД можно извлечь следующую  информацию :

  1. количество прохождений вершины в целом,
  2. количество прохождений вершины при выполнении или невыполнении условия (для операторов ветвления),
  3. время выполнения методов  и проекта в целом,
  4. статистическая информация о полноте тестирования, как на конкретном тесте, так и на последовательности тестовых наборов.

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

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

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

Рисунок 1 – структурная схема алгоритма работы программы

2.3 ОПИСАНИЕ ПАРСЕРА ИСХОДНОГО КОДА

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

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

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

Будем считать, что программа абсолютно надежна, если unit-тесты покрывают все пути в графах управления всех методов классов пакетов. Количество путей (цикломатическая сложность графа), согласно [2], определяется как

где  E – количество ребер в графе, N - количество вершин, Z - количество компонентов связности. Таким образом,  надежность кода можно оценить как

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

В настоящее время, инструментальный пакет позволяет выполнить более слабую оценку надежности  по критериям C1:

где  L – число пройденных ребер в графе, pv – вероятность ошибки при прохождении ребра, и Ср:

где L’ – число пройденных пар ребер в графе, Е’ – число всех пар ребер, опраделяется как 2n если n – число ветвлений.

С точки зрения реализации процесса оценки полноты покрытия используется следующий алгоритм:

  1.  Анализ графа управления и генерация таблиц отношения каждый с каждым ребер ГУ для каждого метода.
  2.  Анализ возможной достижимости ребер относительно друг друга. Учет пользовательских предпочтений на влияние определенных пар рветвей на надежность программы.
  3.  Анализ результатов тастирования: наполнения графа управления и таблиц отношений.
  4.  Вычисление надежности исходного кода тестируемой программы по критериям для каждого метода и для программы в целом.

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

3 ТЕКСТ ПРОГРАММЫ

package Troshin_and_Hidoyatov.MyTreeParser;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.HashSet;

import java.util.LinkedList;

import java.util.List;

import com.puppycrawl.tools.checkstyle.api.DetailAST;

import com.puppycrawl.tools.checkstyle.api.FileText;

import com.puppycrawl.tools.checkstyle.api.TokenTypes;

public class MyParsing

{

 

/**

 * Initial text of parsed file.

 */

private final FileText mInitialText;

 

//dominy table

private ArrayList<DominityCard> mDominityTable = new ArrayList<DominityCard>();

//topCards table

private ArrayList<MyKardInterface> mTopCardTable = new ArrayList<MyKardInterface>();

//methodCard table.

private ArrayList<MyKardInterface> mMethodCardTable = new ArrayList<MyKardInterface>();

//classCard table.

private ArrayList<MyKardInterface> mClassCardTable = new ArrayList<MyKardInterface>();

 

   private LinkedList <PathCard> mClassPath = new LinkedList<PathCard>();

 

private final HashSet<Integer> mParsingTops = new HashSet<Integer>(Arrays.asList(

  TokenTypes.FOR_INIT, TokenTypes.DO_WHILE, TokenTypes.LITERAL_IF,

  TokenTypes.LITERAL_WHILE, TokenTypes.LITERAL_FOR,

  TokenTypes.LITERAL_TRY, TokenTypes.LITERAL_SWITCH,

  TokenTypes.SLIST, TokenTypes.LITERAL_DO));

 

private TopCard mTempTopParent = null;

 

private int mCurrentParentMethodID;

 

/**

 * Amount of methods in the class.

 */

private int mMethodsCount;

 

public MyParsing (FileText aInitialText)

{  

 mInitialText = aInitialText;

 

 mMethodsCount = 0;

}

 

/**

 * getter classPath

 */

public LinkedList<PathCard> getClassPath () {

 return mClassPath;

}

 

/**

 * Getter.

 * @return

 */

public ArrayList<MyKardInterface> getClassCardTable () {

 return mClassCardTable;

}

 

/**

 * Getter.

 * @return

 */

public ArrayList<MyKardInterface> getMethodCardTable () {

 return mMethodCardTable;

}

 

/**

 * Getter.

 * @return

 */

public ArrayList<MyKardInterface> getTopCardTable () {

 return mTopCardTable;

}

 

/**

 * Getter.

 * @return

 */

public ArrayList<DominityCard> getDominyCardTable () {

 return mDominityTable;

}

 

/**

 * Returns an DominyCard.

 *

 * @param aIndex

 * @return

 */

public DominityCard getDominityCard (int aIndex) {

 

 return ( aIndex >= mDominityTable.size() )? null : mDominityTable.get(aIndex);

}

 

/**

 * Begin the automatic parsing.

 * @param aRootAst - a root of AST.

 */

public void startFileParsing (DetailAST aRootAst, String aFilePath, String aDefaultPath) {

 

 DetailAST tempNode = aRootAst;

 

 String correctPath = getCorrectPath(aFilePath, aDefaultPath);

 

 while ((tempNode != null) && (tempNode.getType() != TokenTypes.RCURLY )) {

  if ( tempNode.getType() == TokenTypes.CLASS_DEF ) {

   MyKardInterface classCard = getClassKard(tempNode, aFilePath, correctPath);

   

   mClassPath.add(new PathCard(correctPath, classCard.getID()));

   

   mClassCardTable.add(classCard);

  }

  tempNode = tempNode.getNextSibling();

 }

}

 

public String getCorrectPath (String aFilePath, String aDefaultPath) {

 

 String rezult = "";

 

 if (aDefaultPath.equals(aFilePath)) {

  String []tempStrings = aFilePath.split("/");

  

  rezult = tempStrings[tempStrings.length-1];

 } else {

  rezult = aFilePath.substring(aDefaultPath.length());

 }

 

 return rezult;

}

 

/**

 * Returns an card view of class.

 * @param ClassDefAST - class definition.

 * @return a new card of class.

 */

public MyKardInterface getClassKard (DetailAST aClassDefAST,

  String aFilePath, String aCorrectPath) {

 

 final int beginLineIndex = aClassDefAST.getLineNo();

 //last line - rCurly of class.

 final int beginColumnIndex = aClassDefAST.getColumnNo();

 

 DetailAST rCurly = aClassDefAST.findFirstToken(TokenTypes.OBJBLOCK).

   findFirstToken(TokenTypes.RCURLY);

 

 final int endLineIndex = rCurly.getLineNo();

 

 final int endColumnIndex = rCurly.getColumnNo();

 

 final int classId = getID(beginLineIndex, endLineIndex,

   beginColumnIndex, endColumnIndex, 0);

 

 final String className = aClassDefAST.findFirstToken(TokenTypes.IDENT).

   getText();

 //needed later

 final int access = 0;

 //needed later

 final int extend = 0;

 //needed later

 final int implement = 0;

 

 final String modifiedText = getClassModifiedText (aClassDefAST,

   beginLineIndex, classId, aFilePath, aCorrectPath);

 

 final MyKardInterface classKard = new ClassKard(classId, className, access,

   extend, implement, modifiedText, beginLineIndex, endLineIndex, aFilePath);

 

 return classKard;

}

 

/**

 * Return an card view of class.

 * @param aMethodDefAST - method definition.

 * @return a new card of class.

 */

public MyKardInterface getMethodCard (DetailAST aMethodDefAST, int aParentClassID) {

 

 final int beginLineIndex = aMethodDefAST.getLineNo();

 

 final int beginColumnIndex = aMethodDefAST.getColumnNo();

 

 final DetailAST sibling = aMethodDefAST.getNextSibling();

 

 int lastLineIndex = sibling.getLineNo();

 int lastColumnIndex = sibling.getColumnNo();

 

 final int methodId = getID(beginLineIndex, lastLineIndex,

   beginColumnIndex, lastColumnIndex, 0);

 

 final String methodName;

 

 if (aMethodDefAST.findFirstToken(TokenTypes.IDENT) != null ) {

  methodName = aMethodDefAST.findFirstToken(TokenTypes.IDENT).

    getText();

 } else {

  //instanse init block.

  methodName = "instance init";

 }

 

 final int access = 0;

 

 final int statics = 0;

 

 final String returnType = null;

 

 mCurrentParentMethodID = methodId;

 

 final StringBuffer modifiedText = getMethodModifiedText(aMethodDefAST, methodId);

 

 final MyKardInterface methodCard = new MethodCard(methodId, methodName, access,

    statics, returnType, modifiedText, beginLineIndex, lastLineIndex,

    aParentClassID, beginColumnIndex, lastColumnIndex);

 

 return methodCard;

}

 

/**

 * Return an ID of text ranged in (aBeginIndex, aEndIndex).

 *

 * @param aBeginIndex - index of first line in initialText.

 * @param aEndIndex - index of last line in initialText.

 * @return - ID of node.

 */

private int getID (int aBeginLineIndex, int aEndLineIndex,

   int aBeginColumnIndex, int aEndColumnIndex, int trueFalse) {

 

 int beginLine = aBeginLineIndex-1;

 int endLine = aEndLineIndex-1;

 int beginColumn = aBeginColumnIndex;

 int endColumn = aEndColumnIndex;

 

 List<String> subList = new LinkedList<String>() ;

 

//  if (endColumn == 0) {

//   endLine -= 1;

//   System.out.println(mInitialText.get(endLine));

//   endColumn = mInitialText.get(endLine).length()-1;

//  }

 

 if ((endLine - beginLine) > 1) {

  subList.addAll(mInitialText.subList(beginLine+1, endLine-1));

  

  subList.add(0, mInitialText.get(beginLine).substring(beginColumn));

  subList.add(subList.size()-1,

    mInitialText.get(endLine).substring(0, endColumn));

 } else {

  if ((endLine - beginLine) == 1) {

   subList.add(0, mInitialText.get(beginLine).substring(beginColumn));

   subList.add(1, mInitialText.get(endLine).substring(0, endColumn));

  } else {

   subList.add(mInitialText.get(beginLine).substring(

     beginColumn, endColumn));

  }

 }

 

 if (trueFalse == 22) {

  subList.add("_True_Card_");

 } else {

  if (trueFalse == 23) {

   subList.add("_False_Card_");

  }

 }

 

 return subList.hashCode();

}

 

/**

 *

 * @param aClassDefAST

 * @param parentId - id of parent class.

 * @return

 */

private String getClassModifiedText (DetailAST aClassDefAST, int aBeginIndex,

  int aParentClassId, String aFilePath, String aCorrectPath ) {

 

 StringBuffer modifiedText = new StringBuffer();

 //define header block

 modifiedText.append(getInitialSubText(aClassDefAST.getLineNo(),

   aClassDefAST.findFirstToken(TokenTypes.OBJBLOCK).getLineNo(),

   aClassDefAST.findFirstToken(TokenTypes.OBJBLOCK).getColumnNo(),

   aClassDefAST.getColumnNo()));

 

 //for defining fields blocks.

 DetailAST objBlock = aClassDefAST.findFirstToken(TokenTypes.OBJBLOCK);

 

 int counter = 0;

 

 int beginIndex = objBlock.getLineNo();

 int beginColumn = objBlock.getColumnNo();

 int endColumn = 0;

 

 DetailAST tempNode = objBlock.getFirstChild();

 

 if (tempNode.getType() == TokenTypes.LCURLY)

  tempNode.getNextSibling();

 

 boolean defineFields = false;

 

 int type = tempNode.getType();

 

 while (type != TokenTypes.RCURLY) {

  

  if (type == TokenTypes.CLASS_DEF) {

   MyKardInterface classCard = getClassKard(tempNode, aFilePath, aCorrectPath);

   

   mClassPath.add(new PathCard( aCorrectPath, classCard.getID()));

   

   mClassCardTable.add(classCard);

   

   //Set dominate of class - subclass.

    mDominityTable.add(new  DominityCard(aParentClassId, classCard.getID(), counter));

    counter++;

   

    if (defineFields) {

     //append the fields.

     String correctText = getCorrectText(getInitialSubText(beginIndex, classCard.getStartLine(),

       classCard.getStartColumn()-1 , beginColumn+1));

     

     modifiedText.append( correctText);

      

     defineFields = false;

    }

    

   modifiedText.append("_myTest_value\n");

   

   beginIndex = classCard.getLastLine();

    

   beginColumn = classCard.getLastColumn()+1;

   

  }

  

   if (methodType(tempNode) != 0 ) {

    

    MyKardInterface tempKard = getMethodCard(tempNode, aParentClassId);

    

    mMethodCardTable.add(tempKard);

    

    //Set dominate of class - method.

    mDominityTable.add(new  DominityCard(aParentClassId, tempKard.getID(), counter));

    counter++;

    if (defineFields) {

    //append the fields.

     String correctText = getCorrectText(getInitialSubText(beginIndex, tempKard.getStartLine(),

       tempKard.getStartColumn()-1 , beginColumn+1));

     

     modifiedText.append( correctText);

     

    defineFields = false;

    }

    //for next fieldsAppending.

    beginIndex = tempKard.getLastLine();

    

    beginColumn = tempKard.getLastColumn();

    

    modifiedText.append("_myTest_value\n");

   } else {

    defineFields = true;

   }

   

   tempNode = tempNode.getNextSibling();

   

   type = tempNode.getType();

 }

 

 

 modifiedText.append("static _myTest_tester mtt = new _myTest_tester ();\n"+

   "static int _myTest_nesting[] = new int["+ mMethodsCount+"];\n");

 //append text between the last methodDef and rCurly.

 

 mMethodsCount = 0;

 

 modifiedText.append(getInitialSubText(beginIndex, tempNode.getLineNo(),

   tempNode.getColumnNo(), beginColumn));

 

 return modifiedText.toString();

}

 

/**

 * Return field class text without }

 */

public String getCorrectText (String aText) {

 

 for (int i = 0; i < aText.length (); i++) {

        if (aText.charAt(i) != ' ') {

         if (aText.charAt(i) == '}') {

          aText = aText.substring(i+1);

         }

         break;

        }

       }

 

 return aText;

}

 

/**

 *  Opasnoste !!! Onotole 1111ADINADIN!!!!

 * @param aBeginIndex

 * @param aLastIndex

 * @param aEndColumn

 * @param aStartColumn

 * @return

 */

private String getInitialSubText (int aBeginIndex,int aLastIndex,

  int aEndColumn, int aStartColumn) {

 

  String rezult = "";

 

   int beginLine = aBeginIndex-1;

  int endLine = aLastIndex-1;

  int beginColumn = aStartColumn;

  int endColumn = aEndColumn+1;

  

  

//   if (endColumn == 0) {

//    endLine -= 1;

//    endColumn = mInitialText.get(endLine).length()-1;

//   }

  

 if ((endLine - beginLine) > 1) {

  rezult += mInitialText.get(beginLine).substring(beginColumn);

  rezult += mInitialText.subList(beginLine+1, endLine).toString()+"\n";

  rezult += mInitialText.get(endLine).substring(0, endColumn);

 } else {

  if ((endLine - beginLine) == 1) {

   rezult += mInitialText.get(beginLine).substring(beginColumn);

   rezult += mInitialText.get(endLine).substring(0, endColumn);

  } else {

   rezult += mInitialText.get(beginLine).substring(

     beginColumn, endColumn);

  }

 }

 

 return rezult;

}

 

/**

 * Define the type of classDef child, measure the amount of methods.

 *

 * @param aMethodBlockAST - current methodDefAST

 * @return - blockType ....

 */

private int  methodType (DetailAST aMethodBlockAST) {

 final int blockType;

 

 switch (aMethodBlockAST.getType()) {

  case TokenTypes.METHOD_DEF:

   blockType = 1;

   mMethodsCount++;

   break;

  case TokenTypes.CTOR_DEF:

   blockType = 2;

   mMethodsCount++;

   break;

  case TokenTypes.INSTANCE_INIT:

   blockType = 3;

   break;

  default:

   blockType = 0;

   break;

 }

 

 return blockType;

}

 

/**

 * Fullfill the dominity table.

 *

 * @param aDominatorID - id of parent node.

 * @param aPostDominatorID - id of child node.

 */

private void setDominity (int aDominatorID, int aPostDominatorID,

  int aDominyType)

{

 mDominityTable.add(new DominityCard(aDominatorID,

   aPostDominatorID, aDominyType));

}

 

/**

 * Returns a modifiedMethodText.

 *

 * @param aMethodDefAST

 * @param aParentMethodId - id of parsed method.

 * @return

 */

private StringBuffer getMethodModifiedText (DetailAST aMethodDefAST,

  int aParentMethodId) {

 

 DetailAST methodSlist = aMethodDefAST.findFirstToken(TokenTypes.SLIST);

 

 int lastLine;

 int lastColumn;

 

 boolean appentDominyCard = true;

 

 StringBuffer methodModifiedText = new StringBuffer();

 

 if (aMethodDefAST.getType() != TokenTypes.INSTANCE_INIT) {

 

  methodModifiedText.append(getInitialSubText(aMethodDefAST.getLineNo(),

   methodSlist.getLineNo(), methodSlist.getColumnNo(),

   aMethodDefAST.getColumnNo()));

 } else {

  methodModifiedText.append("{\n");

 }

 

 methodModifiedText.append("\nlong _myTest_timeMethod = System.nanoTime();\n");

 

 DirectCode directCode = new DirectCode();

 

 MyKardInterface topCard;

 

 int counter = 0;

 

 DetailAST tempAST = methodSlist.getFirstChild();

 

 int firstLine = tempAST.getLineNo();

 int firstColumn = tempAST.getColumnNo();

 

 boolean addDirectCode = false;

 

 DetailAST saveState = null;

 

 while (tempAST.getType() != TokenTypes.RCURLY) {

  

  saveState = tempAST;

  

  int type = tempAST.getType();

  

  if (type == TokenTypes.SEMI) {

   if (directCode.getConstructorType() == true) {

    tempAST = tempAST.getNextSibling();

    

    firstLine = tempAST.getLineNo();

    firstColumn = tempAST.getColumnNo();

    

    type = tempAST.getType();

    

    if (type == TokenTypes.RCURLY)

     break;

   }

  }

  

  //define direct code (false)

  if (mParsingTops.contains(type)) {

   

   if (addDirectCode) {

    if (type == TokenTypes.EXPR) {

     int [] tempArray = getExprLines(tempAST);

     

     lastLine = tempArray[0];

     lastColumn = tempArray[1];

    } else {

     lastLine = tempAST.getLineNo();

     lastColumn = tempAST.getColumnNo()-1;

    }

   directCode.appendText(getInitialSubText(directCode.getBeginIndex(),

     lastLine, lastColumn, directCode.getStartColumn()));

   

   directCode.setLastIndex(lastLine);

   directCode.setLastColumn(lastColumn);

   

   TopCard topAst = createDirectTopAST(directCode, false);

   

   methodModifiedText.append(topAst.getModifiedText());

   

   mTopCardTable.add(topAst);

   

  // if (appentDominyCard) {

    mDominityTable.add(new DominityCard(aParentMethodId, topAst.getID(),

      counter));

    counter++;

  //  appentDominyCard = false;

  // }

   addDirectCode = false;

   }

   

   topCard = getTopCard (tempAST);

   

   mTopCardTable.add(topCard);

   

   //if (appentDominyCard) {

    mDominityTable.add(new DominityCard(aParentMethodId, topCard.getID(),

      counter));

    counter++;

  //  appentDominyCard = false;

  // }

   

   methodModifiedText.append(topCard.getModifiedText());

   

   firstLine = topCard.getLastLine();

   firstColumn = topCard.getLastColumn();

   directCode = new DirectCode();

   

  } else {

   if ((type != TokenTypes.SEMI) && (type == TokenTypes.EXPR)) {    

   if  (isDirectCode(tempAST.getFirstChild())) {

    

    fullfillTheDirectCodeTop(directCode, firstLine, tempAST,

      aParentMethodId, firstColumn);

    

    addDirectCode = true;

    

   } else {

    //define method call

    if (addDirectCode) {

     if (type == TokenTypes.EXPR) {

      int [] tempArray = getExprLines(tempAST);

      

      lastLine = tempArray[0];

      lastColumn = tempArray[1]-1;

     } else {

      lastLine = tempAST.getLineNo();

      lastColumn = tempAST.getColumnNo()-1;

     }

    directCode.appendText(getInitialSubText(directCode.getBeginIndex(),

      lastLine, lastColumn, directCode.getStartColumn()));

    

    directCode.setLastIndex(lastLine);

    directCode.setLastColumn(lastColumn);

    

    TopCard topAst = createDirectTopAST(directCode, false);

    

    methodModifiedText.append(topAst.getModifiedText());

    

    mTopCardTable.add(topAst);

    

    if (appentDominyCard) {

     mDominityTable.add(new DominityCard(aParentMethodId, topAst.getID(),

       counter));

     counter++;

     appentDominyCard = false;

    }

    addDirectCode = false;

    }

     

    topCard = getTopCard (tempAST);

    

    mTopCardTable.add(topCard);

    

    if (appentDominyCard) {

     mDominityTable.add(new DominityCard(aParentMethodId, topCard.getID(),

       counter));

     counter++;

     appentDominyCard = false;

    }

    

    methodModifiedText.append(topCard.getModifiedText());

    

    firstLine = topCard.getLastLine();

    firstColumn = topCard.getLastColumn();

    directCode = new DirectCode();

   }

   } else {

    if (type == TokenTypes.VARIABLE_DEF) {

     int []tempArray = getVariableFirstIndexes(tempAST);

     

     firstLine = tempArray[0];

     firstColumn = tempArray[1];

     

     fullfillTheDirectCodeTop(directCode, firstLine, tempAST,

       aParentMethodId, firstColumn);

    

     addDirectCode = true;

    }

    

   }

  }

  

  tempAST = tempAST.getNextSibling();

  if (tempAST == null){

   tempAST = saveState;

   break;

  }

 }

 

 if (addDirectCode) {

  

  directCode.appendText(getInitialSubText(directCode.getBeginIndex(),

    tempAST.getLineNo(), tempAST.getColumnNo()-1, directCode.getStartColumn()));

  

  TopCard topAst = createDirectTopAST(directCode, false);

  

  methodModifiedText.append(topAst.getModifiedText());

  

  mTopCardTable.add(topAst);

  

  if (appentDominyCard) {

   mDominityTable.add(new DominityCard(aParentMethodId, topAst.getID(),

     counter));

   counter++;

   appentDominyCard = false;

  }

 }

 

 methodModifiedText.append("_myTest_timeMethod=System.nanoTime()-_myTest_timeMethod;\n");

 methodModifiedText.append("mtt._myTest_kesh+=\\\",("+aParentMethodId+",\\\"+_myTest_timeMethod+\\\","

   + mMethodsCount+")\\\";\n");

 methodModifiedText.append("mtt._myTest_length++;\n");

 methodModifiedText.append("mtt._myTest_loadAtDataBase();\n}");

 

 return methodModifiedText;

}

 

/**

 * Return a first line and first column of Variable Def.

 * @return

 */

private int[] getVariableFirstIndexes (DetailAST aTopAst) {

 

 DetailAST tempAst = aTopAst.findFirstToken(TokenTypes.TYPE);

 

 DetailAST secondAst = tempAst;

 

 while (tempAst != null) {

  secondAst = tempAst;

  

  tempAst = tempAst.getFirstChild();

 }

 

 return new int [] {secondAst.getLineNo(), secondAst.getColumnNo()};

}

 

/**

 * Create or fullfill a direct top card.

 */

private void fullfillTheDirectCodeTop (DirectCode aDirectCode, int aFirstLine,

  DetailAST aTempAst, int aParentMethodId, int aFirstColumn) {

 

 if (aDirectCode.getConstructorType()) {

  //append new direct code object

  aDirectCode.setAll(aFirstLine, "", aParentMethodId, aFirstColumn);

 }

 

}

 

/**

 * Define a direct code and methods call.

 * @return

 */

private boolean isDirectCode (DetailAST aTempAst) {

 boolean rezult = true;

 

 int type = aTempAst.getType();

 

 if (type == TokenTypes.METHOD_CALL) {

   rezult = false;

 } else {

  if (type == TokenTypes.LITERAL_NEW) {

   

   DetailAST ident = aTempAst.getFirstChild();

   

   while (ident.getType() != TokenTypes.IDENT) {

    ident = ident.getFirstChild();

   }

   

    rezult = false;

  }

 }

 

 return rezult;

}

 

/**

 * Return a new top card.

 *

 * @param aTopCard

 * @param directCodeType

 * @return

 */

private TopCard createDirectTopAST (DirectCode aTopCard,

  boolean directCodeType) {

 

 String rezult = "";

 

 TopCard topCard = null;

 

 if (aTopCard != null) {

  

  int topID = 0;

  

  if (directCodeType) {

   //for top direct code ?

   topID = getInitialSubText(aTopCard.getBeginIndex(), aTopCard.getLastIndex(),

     aTopCard.getLastColumn(), aTopCard.getStartColumn()+1).hashCode();

  

   rezult = "mtt._myTest_proverka(true,"+topID+ ");\n"

     +aTopCard.getText().toString();

  

  } else {

   //for method direct code ?

   topID = aTopCard.getText().toString().hashCode();

   

   rezult = "mtt._myTest_proverka(true,"+topID+ ");\n"

     +aTopCard.getText().toString();

   

  }

  

  topCard = new TopCard(topID, aTopCard.getTopType(),

    aTopCard.getBeginIndex(), aTopCard.getLastIndex(),

    aTopCard.getParentMethodID(), rezult, aTopCard.getStartColumn(),

    aTopCard.getLastColumn());

  

  topCard.setHeader(getTopHeader(16, null));

 }

 

 

 return topCard;

}

 

/**

 * Return a new top card.

 *

 * @param aTopAST

 * @param aParentID

 * @return

 */

private MyKardInterface getTopCard (DetailAST aTopAST) {

 

 int beginLineIndex = 0;

 int beginColumnIndex = 0;

 

 if (aTopAST.getType() == TokenTypes.EXPR) {

  

  int []tempArray = getExprLines(aTopAST);

  

  beginLineIndex = tempArray[0];

  beginColumnIndex = tempArray[1];

  

 } else {  

  beginLineIndex = aTopAST.getLineNo();

  beginColumnIndex = aTopAST.getColumnNo();

 }

  

 final int topType = getTopType(aTopAST);

 

 int lastLineIndex;

 int lastColumnIndex;

 

 int [] tempArray = getLastLineAndColumn(aTopAST);

 

 lastLineIndex = tempArray[0];

 lastColumnIndex = tempArray[1];

 

 final int topId = getID(beginLineIndex, lastLineIndex,

   beginColumnIndex, lastColumnIndex, 0);

 

 

 TopCard topCard = new TopCard(topId, topType, beginLineIndex,

   lastLineIndex, mCurrentParentMethodID, beginColumnIndex, lastColumnIndex,

   aTopAST);

 

 topCard.setHeader(getTopHeader(topType, aTopAST));

 

 mTempTopParent = (TopCard)topCard;

 

 StringBuffer topModifieText = new StringBuffer();

 

 switch (topType) {

 case 16:

  topModifieText.append("mtt._myTest_proverka (true,"+topId+");\n");

  topModifieText.append(getInitialSubText(beginLineIndex, lastLineIndex,

    lastColumnIndex, beginColumnIndex));

  break;

  

 case 9:

  topModifieText.append("mtt._myTest_proverka (true,"+topId+");\n");

  topModifieText.append("{\n"+myTraversal(aTopAST, topId)+"\n}\n");

  break;

  

 case 17:

  topModifieText.append("mtt._myTest_proverka (true,"+topId+");\n");

  topModifieText.append(getInitialSubText(beginLineIndex, lastLineIndex,

    lastColumnIndex, beginColumnIndex));

  break;

 

 default:

  topModifieText.append(getTopModifiedText(topType,

    aTopAST, topId));

  break;

 }

 

 topCard.setModifiedText (topModifieText.toString());

 

 return topCard;

}

 

/**

 * Return a top header.

 */

private String getTopHeader (int aTopType, DetailAST aTopAst) {

 

 String rezult = "";

 

 switch (aTopType) {

 case 10:

  rezult = getConditionalNormalHeader(aTopAst);

  break;

  

 case 22:

  rezult = "if_FALSE_NODE";

  break;

  

 case 23:

  rezult = "if_TRUE_NODE";

  break;

  

 case 11:

  rezult = getConditionalNormalHeader(aTopAst);

  break;

  

 case 12:

  rezult = getConditionalNormalHeader (aTopAst);

  break;

  

 case 17:

  rezult = "Method_call";

  break;

  

 case 19:

  rezult = getCaseHeader(aTopAst.getFirstChild());

  break;

  

 case 13:

  rezult = getConditionalNormalHeader(aTopAst);

  break;

  

 case 16:

  rezult = "DiReCt_CoDe =)";

  break;

  

 case 18:

  rezult = "try_catch";

  break;

  

 case 14:

  rezult = getConditionalNormalHeader(aTopAst);

  break;

 case 15:

  rezult = getConditionalNormalHeader(aTopAst);

  break;

  

 case 9:

  rezult = "Instance_init";

  break;

  

 default:

  System.out.println("Unexpected top type_normalheader !!!");

  break;

 }

 

 return rezult;

}

 

/**

 * Return case header.

 *

 * @param aTopAst

 * @return

 */

private String getCaseHeader (DetailAST aTopAst) {

 

 DetailAST tempAst = aTopAst.findFirstToken(TokenTypes.COLON);

 

 return getInitialSubText(aTopAst.getLineNo(), tempAst.getLineNo(),

   tempAst.getColumnNo(), aTopAst.getColumnNo());

}

 

/**

 *

 */

private String getConditionalNormalHeader (DetailAST aTopAst) {

 

 String rezult = "";

 

 final int beginLine;

 final int beginColumn;

 

 if (aTopAst.getType() == TokenTypes.LITERAL_DO) {

  DetailAST tempAst = aTopAst.findFirstToken(TokenTypes.DO_WHILE);

  

  beginLine = tempAst.getLineNo()-1;

  beginColumn = tempAst.getColumnNo();

 } else {

  beginLine = aTopAst.getLineNo()-1;

  beginColumn = aTopAst.getColumnNo();

 }

 final DetailAST rParen = aTopAst.findFirstToken(TokenTypes.RPAREN);

 final int endLine = rParen.getLineNo()-1;

 final int endColumn = rParen.getColumnNo()+1;

 

 if (beginLine == endLine) {

  rezult = mInitialText.get(beginLine).substring(beginColumn, endColumn);

 } else {

  if ((beginLine - endLine) > 1) {

   rezult += mInitialText.get(beginLine).substring(beginColumn);

   rezult += mInitialText.subList(beginLine+1, endLine-1).toString();

   rezult += mInitialText.get(endLine).substring(0, endColumn);

  } else {

   rezult += mInitialText.get(beginLine).substring(beginColumn);

   rezult += mInitialText.get(endLine).substring(0, endColumn);

  }

 }

 

 return rezult;

}

 

/**

 * Define a type of top.

 *

 * @param aTopAst

 * @return

 */

private int getTopType (DetailAST aTopAst) {

 

 int type = 0;

 

 switch (aTopAst.getType()) {

 case TokenTypes.LITERAL_IF:

  type = getIfType(aTopAst);

  break;

  

 case TokenTypes.LITERAL_WHILE:

  type = 12;

  break;

  

 case TokenTypes.LITERAL_DO:

  type = 13;

  break;

  

 case TokenTypes.LITERAL_TRY:

  type = 18;

  break;

  

 case TokenTypes.LITERAL_FOR:

  type = 14;

  break;

 case TokenTypes.CASE_GROUP:

  type = 19;

  break;

  

 case TokenTypes.LITERAL_SWITCH:

  type = 15;

  break;

  

 case TokenTypes.SLIST:

  type = 9;

  break;

  

 case TokenTypes.EXPR:

  type = 17;

  break;

  

  

 default:

  type = 16;

  break;

 }

 

 return type;

}

 

/**

 * Define if and if - else blocks.

 * @param aIfAst

 * @return

 */

private int getIfType (DetailAST aIfAst) {

 

 return (aIfAst.findFirstToken(TokenTypes.LITERAL_ELSE) == null)? 10:11 ;

}

 

/**

 * Returns a top modified text.

 *

 * @return

 */

private StringBuffer getTopModifiedText (int aTopType, DetailAST aTopAst,

   int aParentId) {

 

 StringBuffer topModifiedText = new StringBuffer();

 

 switch (aTopType) {

 case 10:

  topModifiedText = getIfModifiedText(aTopAst, aParentId, true);

  break;

  

 case 11:

  topModifiedText = getIf_ElseModifiedText (aTopAst, aParentId);

  break;

  

 case 12:

  topModifiedText = getWhileModifiedText (aTopAst, aParentId, aTopType);

  break;

  

 case 13:

  topModifiedText = getDo_WhileModifiedText (aTopAst, aParentId);

  break;

  

 case 18:

  topModifiedText = getTryModifiedText (aTopAst, aParentId);

  break;

  

 case 14:

  topModifiedText = getWhileModifiedText (aTopAst, aParentId, aTopType);

  break;

 case 15:

  topModifiedText = getSwitchModifiedText (aTopAst, aParentId);

  break;

  

 default:

  System.out.println("Unexpected top type !!!");

  break;

 }

 

 return topModifiedText;

}

 

/**

 * Return do_while card.

 *

 * @return

 */

private StringBuffer getDo_WhileModifiedText (DetailAST aTopAst, int aParentId) {

 

 StringBuffer modifiedText = new StringBuffer();

 

 int firstLine;

 int firstColumn;

 

 int counter = 0;

 

 MyKardInterface topCard;

 

 DetailAST slist = aTopAst.findFirstToken(TokenTypes.SLIST);

 

 modifiedText.append("\ndo {\n");

 

 if (slist == null) {

  

  DetailAST tempNode = aTopAst.getFirstChild();

  

  if ((tempNode.getType() == TokenTypes.EXPR) &&

    (tempNode.getFirstChild().getType() != TokenTypes.METHOD_CALL)) {

       

   int [] firstIndexes = getExprLines(tempNode);

   

   firstLine = firstIndexes[0];

   firstColumn = firstIndexes[1];

   

   int []tempArray = getLastLineAndColumn(tempNode);

   

   DirectCode directCode = new DirectCode(firstLine, getInitialSubText(firstLine,

     tempArray[0], tempArray[1], firstColumn), mCurrentParentMethodID,

     firstColumn, tempArray[0], tempArray[1]);

   

   topCard = (TopCard)createDirectTopAST(directCode, false);

  } else {

   

   topCard = getTopCard(tempNode);

   

  }

  

  mDominityTable.add(new DominityCard(aParentId, topCard.getID(), counter));

  counter++;

  mTopCardTable.add(topCard);

  

  modifiedText.append(topCard.getModifiedText());

  

  modifiedText.append("}\n");

 } else {

  

  modifiedText.append(myTraversal(slist, aParentId));

  

  modifiedText.append("}\n");

 }

 

 modifiedText.append(getIfModifiedHeader(aTopAst, aParentId));

 

 modifiedText.append(";\n");

 

 return modifiedText;

 }

 

 

4 РЕЗУЛЬТАТЫ РАБОТЫ ПРОГРАММЫ

Графический интерфейс программы с разобранным тестовым примером представлен на рисунке 3.

Слева на рисунке 3 изображен граф управления для классов из пакета quicksort (исходный текст ниже).

public class Analiz2 {

   int [][]a={{2,1,1},{5,1,1},{5,3,3},{9,2,2},{2,1,1}};

   char []r;

   LinkedList <String> list=new LinkedList<String>();

   int curLecs=0;

   int next;

   int x=0;

   public Analiz2 (String s) {

       r=s.toCharArray();

       next=0;

       go();

       addition();

   }//konstructor

   public void go (){

       boolean b=true;

       while ((b)&&(r[next]!='$')){

           switch (r[next]){

               case '.':curLecs=x; x=a[x][0];break;

               case '1':curLecs=x; x=a[x][2];break;

               case '0':curLecs=x; x=a[x][1]; break;

               default: System.out.println("OSHIBKA:    "+"Nevernaya bykva  "+r[next]+"  v posizii № - "+next);b=false; break;

           }//switch

           if ((!b)||(x==9)){

               System.out.println("OSHIBKA:    "+"Oshibka v napisanii leksemi № - "+curLecs+"  v posizii № - "+next);

               next++;

               break;

           }//if

           else {

               if (x==5){

                   list.add("lecsema"+curLecs);

                   x=0;

               }

           }//else

           next++;

       }//while

       System.out.println("");

       if ((next!=r.length-1)&&(b)){

           System.out.println("OSHIBKA:  "+"Znak konca stroki v seredine stroki!!!!! ");

       }//if esli $ ranshe vremeni FAIL!!!

       for (int i = 0; i < list.size(); i++) {

           System.out.println("Raspoznana leksema:  "+list.get(i));

       }//fori

   }//void go

   public void addition() {

          System.out.println("param pam");

   }//void addition

}//Analiz2

Рисунок 2 – Графический интерфейс программы.


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

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

 Окно справа отображает время выполнения методов и классов, а также процент выполнения каждого метода относительно общего времени выполнения программы.

ЗАКЛЮЧЕНИЕ

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

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

ПЕРЕЧЕНЬ ССЫЛОК

  1.  Владимиров М.А. Критерии полноты тестового покрытия в генетических алгоритмах генерации тестов // Критерии полноты тестового покрытия в генетических алгоритмах генерации тестов. URL: http://citforum.univ.kiev.ua/SE/testing/completeness_criterion.
  2.  Encyclopedia of Computer Science and Technology. — CRC Press, 1992. — P. 367–368.


 

А также другие работы, которые могут Вас заинтересовать

62287. Словарная работа на уроках русского языка в начальной школе 26.47 KB
  Овладение словарным составом литературного языка является необходимым условием освоения учащимися родного языка: его орфоэпии орфографии грамматики правильного словоупотребления и наконец связной речи вообще.
62291. Содержание и структура урока физической культуры в общеобразовательной школе 25.72 KB
  В практике работы общеобразовательных школ довольно часто говорят о содержании урока. Вместе с тем в работах посвященных теории урока данное понятие не выделено в качестве аспекта заслуживающего специального внимания и анализа.