I have been asked to find a way to measure the volatility of requirements for the program. This volatility would be based upon the following: Total number of requirements changed before review I wonder if anyone knows a way to accomplishment this? thanks for your help! DOORSUser - Mon Jan 25 16:20:12 EST 2010 |
Re: Requirement Volatility - how to get it? I think this says: ReqVolatility = (#Reqs Changed After Review)/(#Reqs changed before Review).
|
Re: Requirement Volatility - how to get it? string inFile = "c:/temp/input.txt" string outFile = "c:/temp/output.txt" string strModuleName string strStartDate string strEndDate Module m int totCnt=0 // initialize counters int newCnt=0 int modCnt=0 int delCnt=0 Object o Date cd, ld, ed, sd // create, last modified, end, start Regexp Findshall = regexp "shall" // regular expression to find "shall" in text Stream input = read inFile input >> strModuleName input >> strStartDate input >> strEndDate close input if (exists module strModuleName) { m = read(strModuleName,false) showDeletedObjects(true) ed = strEndDate sd = strStartDate Stream out = write outFile for o in m do { string text = o."Object Text" if (Findshall text){ // if "shall" is in the object text cd = o."Created On""" ld = o."Last Modified On" string on = number o "" if ((on0:0 == "3") && (cd<=ed)) { // if section 3 and created before end date totCnt++ if (isDeleted(o)) { // if deleted delCnt++ } else { if (cd>=sd) newCnt++ // if created after start date if ((ld>=sd) && (cd<sd)) modCnt++ // if modified, but not created, after start date } } } } close m out << "Total Requirements=" totCnt "\n" out << "Requirements Changed:Modified=" modCnt "\n" out << "Requirements Changed:Added=" newCnt "\n" out << "Requirements Changed:Deleted=" delCnt "\n" close out } else { ack "Module '" strModuleName "' doesn't exist!" } |
Re: Requirement Volatility - how to get it? I forster through history and I count (addition+deletions+modifications)/TotalNumberOfObjects per WEEK. Whenever the same object is changed 20 time in one week, it is counted as one modification. Goal of this time-box is to eleminate "editorial changes" like three history-records just to write a sentence to its end. I do also differentiate "Requirements only" and "all object" ; you need a convention for that (we have an attribute "Object Type" which can be Req, Info, Heading). Another important thing is to consider only "official changes", I mean to ignore changes like editing the comment column. I do this by looknig at the attribute property "affects change date" and ignores them if it is not set. I would be VERY interested to knwow what do you going to do with your "Volatility number", once you have calculated it ? |
Re: Requirement Volatility - how to get it? I haven't thought about the situation that one requirement was changed multiple times just for editing purpose. I would have to think about it when implementing the solution. I will report my progress... Thanks again!!! |
Re: Requirement Volatility - how to get it? SystemAdmin - Tue Jan 26 07:30:02 EST 2010
|
Re: Requirement Volatility - how to get it? Chris Annal SW Test Engineer / DOORS Database Administrator Sensis Corporation, East Syracuse, New York chrisa@sensis.com |
Re: Requirement Volatility - how to get it? ChrisAnnal - Mon Jun 13 16:14:11 EDT 2011 MyModule 2011, 06 jun 2011, 13 jun Thanks!! Chris Annal SW Test Engineer / DOORS Database Administrator Sensis Corporation, East Syracuse, New York chrisa@sensis.com |
Re: Requirement Volatility - how to get it? ChrisAnnal - Mon Jun 13 16:31:21 EDT 2011
OK. For what it's worth, I put together a script that goes through a module looking for "shall" and counts the objects (Req_Total), then looks for objects that were modified, added, or deleted between two dates (selected by the user in a dialog box).
// Exports Volatility Metrics to the Requirement_Volatility_Metrics.xls file
/*
Volatility Metrics are calculated and then exported to the Requirement_Volatility_Metrics.xls File
This requires that the Requirement_Volatility_Metrics.xls template file exists so that the export
can locate it. (Create an empty Excel file for starters).
*/
pragma runLim,0
#include <utils/ole.inc>
checkPlatform "Microsoft Excel"
const string cMethodOpen = "Open"
const string columnTitles[] = {"Date","Total_Reqs","Num_Added","Num_Deleted","Num_Modified","Total_Changes"}
const int NumOfTitles = 6
int Total_Reqs = 0 //Total Requirements = (Object Text CONTAINS 'shall') AND (NOT(Object Text CONTAINS 'DELETE')))
int Num_Added = 0 //Num of added reqs =(((Object Text CONTAINS 'shall') AND (NOT(Object Text CONTAINS 'DELETE'))) AND (Created On > xx/xx/xx) AND (NOT(Allocation is empty)
int Num_Deleted = 0 //Num of deleted reqs = (Object Text CONTAINS "shall") AND (Object Text CONTAINS "DELETE") AND (Last Modified On >= xx/xx/xx)
int Num_Modified = 0 //Num of Changed Reqs = ((Object Text CONTAINS 'shall') AND (NOT(Object Text CONTAINS 'DELETE'))) AND (Last Modified On >= xx/xx/xx) AND (Clarity includes Modified)
int Total_Changes = 0 //Total Number of changes Made within this period
real Volatility = 0.00 //Will be calculated as Total_Changes / Total_Reqs
string dataSheetName = "Sheet1" //Has the name of the worksheet that will hold the data.
Date DateToTest = "03/04/2005" //This will be changed when the user inputs the actual date. This is just used as a "default" date.
Date startDate = "02/03/2004" //This will be changed when the user inputs the actual date. This is just used as a "default" date.
//--------------------------------------------------------------
OleAutoObj objExcel = null
OleAutoObj objWorkbooks = null
OleAutoObj objWorkbook = null
OleAutoObj objWorksheets = null
OleAutoObj objSheet = null
OleAutoObj objCell = null
OleAutoArgs args = create
//--------------------------------------------------------------
Module ThisModule = current
//initialize the OLE Application (Excel)
bool excelInit()
{
string ExcelFileName = "C:\\Temp\\Requirement_Volatility_Metrics.xlt"
// print ExcelFileName
objExcel = connectToApp(cObjExcelApplication, "Excel")
if (null objExcel) return false
makeVisible objExcel
// get workbooks collection
checkRes(oleGet(objExcel,cPropertyWorkbooks,objWorkbooks))
if (null objWorkbooks)
{
ack "Unable to get workbooks collection"
return false
}
// Open existing Excel file
clear( args )
put( args, cParamFileName, ExcelFileName )
checkRes( oleMethod( objWorkbooks, cMethodOpen, args ) )
// get active workbook
checkRes(oleGet(objExcel,cPropertyActiveWorkbook,objWorkbook))
if (null objWorkbook)
{
ack "Unable to get active workbook"
return false
}
//get the worksheets
checkRes(oleGet(objWorkbook, "Worksheets", objWorksheets))
if (null objWorksheets)
{
ack "Unable to get worksheets"
return false
}
clear(args )
put(args, dataSheetName)
checkRes( oleGet(objWorksheets,"Item", args , objSheet) )
if (null objSheet)
{
ack "Unable to get Sheet"
return false
}
// Activate selected sheet
checkRes( oleMethod(objSheet, "Activate") )
return true
}
//for creating the Excel Columns
string intToCol(int i) {
int p
if (i < 26) {
char a = `A'
p = intOf a
p = p + (i-1)
a = charOf p
return a ""
} else {
ack "Too many columns"
halt
}
}
void setCell(int row, int col, string s) {
closeIfNonNull objCell
clear(args)
put(args, (intToCol col) row "")
checkRes(oleGet(objSheet, cMethodRange,args, objCell))
if (null objCell) {
ack "Unable to get cell object"
halt
}
checkRes(olePut(objCell, cPropertyValue, s))
}
void doExcel()
{
Object o
Column c
string s = ""
int row = 1
int col = 0
if (!excelInit)
{
return
}
row++
col=0
s = startDate ""
col++
setCell(row, col, s)
s = DateToTest ""
col++
setCell(row, col, s)
s = Total_Reqs ""
col++
setCell(row, col, s)
s = Num_Added ""
col++
setCell(row, col, s)
s = Num_Deleted ""
col++
setCell(row, col, s)
s = Num_Modified ""
col++
setCell(row, col, s)
s = Total_Changes ""
col++
setCell(row, col, s)
s = Volatility ""
col++
setCell(row, col, s)
disconnectFromApp objExcel
}
// Dialog box variables
DB dbDates = null // this is the dialog box definition
DBE dbeStartDate = null
DBE dbeEndDate = null //holds the string to search for
startDate = null
Date endDate = null
bool datesAreValid = false
Buffer outBuf = create
outBuf = ""
void GenerateMetrics (DB db)
{//GenerateMetrics
string ThisString
Object ThisObject
int offset,len
Link OutLink
Date ThisObjLastModDate //Last Date this was modified on.
Date ThisObjDateCreated //Date this Object was created
Date TestDate = getDate(dbeEndDate) //Get the Date to Test for from the user, for some reason this can't be assigned to a global
DateToTest = TestDate
startDate = getDate(dbeStartDate)
Date LastMetricDate = getDate(dbeStartDate)
if (DateToTest <= LastMetricDate)
{
ack "Metric Date must be after last Metric Date"
halt
}
//Get Total_Reqs
for ThisObject in ThisModule do //loop through entire module
{
ThisString = ThisObject."Object Text"
ThisObjLastModDate= ThisObject."Last Modified On"
ThisObjDateCreated= ThisObject."Created On"
//Get Total_Reqs
if (findRichText(ThisString , "shall", offset, len, false))
{
Total_Reqs++
//Get the number of shalls that were added since the last metric update
if (ThisObjDateCreated > LastMetricDate) Num_Added++
//Get the number of shalls that were modified (not including those that were deleted) since the last metric update
if ( (ThisObjLastModDate > LastMetricDate) && (!isDeleted(ThisObject)) ) Num_Modified++
//Get the number of shalls deleted since the last metric update
if (isDeleted(ThisObject)) Num_Deleted++
// else //shall wasn't added, modified or deleted between selected dates
// {
//Get the number of shalls deleted since the last metric update
// if (isDeleted(ThisObject)) Num_Deleted++
// } // end else
} // end Get Total Req
} //end for ThisObject in ThisModule
//Get Total Changes
Total_Changes = Num_Added + Num_Deleted + Num_Modified
//Get Volatility
//DXL doesn't allow good casting so had to use "real" variables to convert ints to reals before calculating
real TR = Total_Reqs
real TC = Total_Changes
Volatility = TC/TR
//Build an Information Box to display results to user, clicking OK will export to Excel
string MessageString = ""
MessageString = MessageString "Start Date = " startDate "\n"
MessageString = MessageString "End Date = " DateToTest "\n"
MessageString = MessageString "Total_Reqs = " TR ", "
MessageString = MessageString "Num_Added = " Num_Added ", "
MessageString = MessageString "Num_Deleted = " Num_Deleted ", "
MessageString = MessageString "Num_Modified = " Num_Modified ","
MessageString = MessageString "Total_Changes = " TC "\n"
MessageString = MessageString "Volatility = " Volatility "\n"
// notify the user that the script is complete
infoBox MessageString
doExcel
}//GenerateMetrics
void getKey() {
dbDates = centered "Requirement Volatility"
label(dbDates, "!!! NOTE YOU MUST BE IN STANDARD VIEW UNFILTERED !!!")
label(dbDates, "Enter the start and end dates that you want the metrics from.")
dbeStartDate = date(dbDates, 20, today, true)
dbeEndDate = date(dbDates, 20, today, true)
ok(dbDates, "Generate Volatility Metrics", GenerateMetrics )
show dbDates
} // getKey
load view "ShowDeletions"
getKey
|
Re: Requirement Volatility - how to get it? ChrisAnnal - Fri Jun 17 14:34:49 EDT 2011
OK. For what it's worth, I put together a script that goes through a module looking for "shall" and counts the objects (Req_Total), then looks for objects that were modified, added, or deleted between two dates (selected by the user in a dialog box).
// Exports Volatility Metrics to the Requirement_Volatility_Metrics.xls file
/*
Volatility Metrics are calculated and then exported to the Requirement_Volatility_Metrics.xls File
This requires that the Requirement_Volatility_Metrics.xls template file exists so that the export
can locate it. (Create an empty Excel file for starters).
*/
pragma runLim,0
#include <utils/ole.inc>
checkPlatform "Microsoft Excel"
const string cMethodOpen = "Open"
const string columnTitles[] = {"Date","Total_Reqs","Num_Added","Num_Deleted","Num_Modified","Total_Changes"}
const int NumOfTitles = 6
int Total_Reqs = 0 //Total Requirements = (Object Text CONTAINS 'shall') AND (NOT(Object Text CONTAINS 'DELETE')))
int Num_Added = 0 //Num of added reqs =(((Object Text CONTAINS 'shall') AND (NOT(Object Text CONTAINS 'DELETE'))) AND (Created On > xx/xx/xx) AND (NOT(Allocation is empty)
int Num_Deleted = 0 //Num of deleted reqs = (Object Text CONTAINS "shall") AND (Object Text CONTAINS "DELETE") AND (Last Modified On >= xx/xx/xx)
int Num_Modified = 0 //Num of Changed Reqs = ((Object Text CONTAINS 'shall') AND (NOT(Object Text CONTAINS 'DELETE'))) AND (Last Modified On >= xx/xx/xx) AND (Clarity includes Modified)
int Total_Changes = 0 //Total Number of changes Made within this period
real Volatility = 0.00 //Will be calculated as Total_Changes / Total_Reqs
string dataSheetName = "Sheet1" //Has the name of the worksheet that will hold the data.
Date DateToTest = "03/04/2005" //This will be changed when the user inputs the actual date. This is just used as a "default" date.
Date startDate = "02/03/2004" //This will be changed when the user inputs the actual date. This is just used as a "default" date.
//--------------------------------------------------------------
OleAutoObj objExcel = null
OleAutoObj objWorkbooks = null
OleAutoObj objWorkbook = null
OleAutoObj objWorksheets = null
OleAutoObj objSheet = null
OleAutoObj objCell = null
OleAutoArgs args = create
//--------------------------------------------------------------
Module ThisModule = current
//initialize the OLE Application (Excel)
bool excelInit()
{
string ExcelFileName = "C:\\Temp\\Requirement_Volatility_Metrics.xlt"
// print ExcelFileName
objExcel = connectToApp(cObjExcelApplication, "Excel")
if (null objExcel) return false
makeVisible objExcel
// get workbooks collection
checkRes(oleGet(objExcel,cPropertyWorkbooks,objWorkbooks))
if (null objWorkbooks)
{
ack "Unable to get workbooks collection"
return false
}
// Open existing Excel file
clear( args )
put( args, cParamFileName, ExcelFileName )
checkRes( oleMethod( objWorkbooks, cMethodOpen, args ) )
// get active workbook
checkRes(oleGet(objExcel,cPropertyActiveWorkbook,objWorkbook))
if (null objWorkbook)
{
ack "Unable to get active workbook"
return false
}
//get the worksheets
checkRes(oleGet(objWorkbook, "Worksheets", objWorksheets))
if (null objWorksheets)
{
ack "Unable to get worksheets"
return false
}
clear(args )
put(args, dataSheetName)
checkRes( oleGet(objWorksheets,"Item", args , objSheet) )
if (null objSheet)
{
ack "Unable to get Sheet"
return false
}
// Activate selected sheet
checkRes( oleMethod(objSheet, "Activate") )
return true
}
//for creating the Excel Columns
string intToCol(int i) {
int p
if (i < 26) {
char a = `A'
p = intOf a
p = p + (i-1)
a = charOf p
return a ""
} else {
ack "Too many columns"
halt
}
}
void setCell(int row, int col, string s) {
closeIfNonNull objCell
clear(args)
put(args, (intToCol col) row "")
checkRes(oleGet(objSheet, cMethodRange,args, objCell))
if (null objCell) {
ack "Unable to get cell object"
halt
}
checkRes(olePut(objCell, cPropertyValue, s))
}
void doExcel()
{
Object o
Column c
string s = ""
int row = 1
int col = 0
if (!excelInit)
{
return
}
row++
col=0
s = startDate ""
col++
setCell(row, col, s)
s = DateToTest ""
col++
setCell(row, col, s)
s = Total_Reqs ""
col++
setCell(row, col, s)
s = Num_Added ""
col++
setCell(row, col, s)
s = Num_Deleted ""
col++
setCell(row, col, s)
s = Num_Modified ""
col++
setCell(row, col, s)
s = Total_Changes ""
col++
setCell(row, col, s)
s = Volatility ""
col++
setCell(row, col, s)
disconnectFromApp objExcel
}
// Dialog box variables
DB dbDates = null // this is the dialog box definition
DBE dbeStartDate = null
DBE dbeEndDate = null //holds the string to search for
startDate = null
Date endDate = null
bool datesAreValid = false
Buffer outBuf = create
outBuf = ""
void GenerateMetrics (DB db)
{//GenerateMetrics
string ThisString
Object ThisObject
int offset,len
Link OutLink
Date ThisObjLastModDate //Last Date this was modified on.
Date ThisObjDateCreated //Date this Object was created
Date TestDate = getDate(dbeEndDate) //Get the Date to Test for from the user, for some reason this can't be assigned to a global
DateToTest = TestDate
startDate = getDate(dbeStartDate)
Date LastMetricDate = getDate(dbeStartDate)
if (DateToTest <= LastMetricDate)
{
ack "Metric Date must be after last Metric Date"
halt
}
//Get Total_Reqs
for ThisObject in ThisModule do //loop through entire module
{
ThisString = ThisObject."Object Text"
ThisObjLastModDate= ThisObject."Last Modified On"
ThisObjDateCreated= ThisObject."Created On"
//Get Total_Reqs
if (findRichText(ThisString , "shall", offset, len, false))
{
Total_Reqs++
//Get the number of shalls that were added since the last metric update
if (ThisObjDateCreated > LastMetricDate) Num_Added++
//Get the number of shalls that were modified (not including those that were deleted) since the last metric update
if ( (ThisObjLastModDate > LastMetricDate) && (!isDeleted(ThisObject)) ) Num_Modified++
//Get the number of shalls deleted since the last metric update
if (isDeleted(ThisObject)) Num_Deleted++
// else //shall wasn't added, modified or deleted between selected dates
// {
//Get the number of shalls deleted since the last metric update
// if (isDeleted(ThisObject)) Num_Deleted++
// } // end else
} // end Get Total Req
} //end for ThisObject in ThisModule
//Get Total Changes
Total_Changes = Num_Added + Num_Deleted + Num_Modified
//Get Volatility
//DXL doesn't allow good casting so had to use "real" variables to convert ints to reals before calculating
real TR = Total_Reqs
real TC = Total_Changes
Volatility = TC/TR
//Build an Information Box to display results to user, clicking OK will export to Excel
string MessageString = ""
MessageString = MessageString "Start Date = " startDate "\n"
MessageString = MessageString "End Date = " DateToTest "\n"
MessageString = MessageString "Total_Reqs = " TR ", "
MessageString = MessageString "Num_Added = " Num_Added ", "
MessageString = MessageString "Num_Deleted = " Num_Deleted ", "
MessageString = MessageString "Num_Modified = " Num_Modified ","
MessageString = MessageString "Total_Changes = " TC "\n"
MessageString = MessageString "Volatility = " Volatility "\n"
// notify the user that the script is complete
infoBox MessageString
doExcel
}//GenerateMetrics
void getKey() {
dbDates = centered "Requirement Volatility"
label(dbDates, "!!! NOTE YOU MUST BE IN STANDARD VIEW UNFILTERED !!!")
label(dbDates, "Enter the start and end dates that you want the metrics from.")
dbeStartDate = date(dbDates, 20, today, true)
dbeEndDate = date(dbDates, 20, today, true)
ok(dbDates, "Generate Volatility Metrics", GenerateMetrics )
show dbDates
} // getKey
load view "ShowDeletions"
getKey
Got some bad news. You don't want to hit an Object Text that says "Following are the shallow water requirements."
Regexp = re_HasShall = regexp2("[^A-Za-z][sS][hH][aA][lL][lL][^A-Za-z]")
bool HasShall(Object obj)
{ string Text = obj."Object Text"
return(re_HasShall text)
}
|
Re: Requirement Volatility - how to get it? |
Re: Requirement Volatility - how to get it? llandale - Fri Jun 17 16:53:46 EDT 2011
Got some bad news. You don't want to hit an Object Text that says "Following are the shallow water requirements."
Regexp = re_HasShall = regexp2("[^A-Za-z][sS][hH][aA][lL][lL][^A-Za-z]")
bool HasShall(Object obj)
{ string Text = obj."Object Text"
return(re_HasShall text)
}
You're right, Louie. This script only works if "shall" appears in the text. so it would count an object as a requirement if it contained "shallow" in the text. There may be some better options than what I had used in the original script, for instance the user might want to "filter" the module and create a specific view that only contained those requirement objects, prior to running the rest of the script. Something like this...
/*
NOTE - This script assumes the module has been filtered for only displaying objects that contain the word "shall" in the text. Using Tools-->Filter-->Define, from the top menu in an open module, then selecting "Any string or text attribute...contains...shall" and unchecking the boxes for "Match Case" and "Regular Expression" as needed. Save the resulting filtered view as Only_Shalls.
*/
//Prior to any scripts used for calculations, user would apply a view as described above
View v = view("Only_Shalls")
ack "Metric Date must be after last Metric Date" //should read... ack "End Date must be after Start Date"
int Total_Reqs = 0 //Total Requirements = (Object Text CONTAINS 'shall') AND (NOT(Object Text CONTAINS 'DELETE'))) int Num_Added = 0 //Num of added reqs =(((Object Text CONTAINS 'shall') AND (NOT(Object Text CONTAINS 'DELETE'))) AND (Created On > xx/xx/xx) AND (NOT(Allocation is empty) int Num_Deleted = 0 //Num of deleted reqs = (Object Text CONTAINS "shall") AND (Object Text CONTAINS "DELETE") AND (Last Modified On >= xx/xx/xx) int Num_Modified = 0 //Num of Changed Reqs = ((Object Text CONTAINS 'shall') AND (NOT(Object Text CONTAINS 'DELETE'))) AND (Last Modified On >= xx/xx/xx) AND (Clarity includes Modified) //should be..... int Total_Reqs = 0 //Total Requirements int Num_Added = 0 //Num of added reqs int Num_Deleted = 0 //Num of deleted reqs int Num_Modified = 0 //Num of Changed Reqs
|
Re: Requirement Volatility - how to get it? jsarkic - Mon Jun 20 09:09:21 EDT 2011 {code} /* This script looks for "Shall" or "shall" in the object text and increments the count integer for each one it finds, whether the shall is in plain or boldfaced font. WARNING! If the Object Text attribute contains text with a "shall" AND an OLE object, this script will ignore the "shall". Developed in DOORS 7.1 p12 Chris Annal SW Test Engineer / DOORS Database Administrator Sensis Corporation, East Syracuse, New York chrisa@sensis.com |
Re: Requirement Volatility - how to get it? ChrisAnnal - Mon Jun 20 11:41:07 EDT 2011
(Sorry, hit the "tab" and "spacebar" while typing and it "posted" the above) /* This script looks for "shall" in the object text and increments the count integer for each one it finds, whether the shall is in plain or boldfaced font. WARNING! If the Object Text attribute contains text with a "shall" AND an OLE object, this script will ignore the "shall". WARNING! If the Object Text attribute contains text with more than one "shall" it will only count the 1st "shall" and move on to the next object. Developed in DOORS 9.3 p1 Chris Annal */
|