Цитата:
Сообщение от
Андре
А я вообще не понял, что тебе сдались эти параметры по умолчанию. Что нового они приносят в плане тестирования?
ничего.
кроме того, что это фишка аксапты, если я правильно понимаю.
поэтому ответ на вопрос не гуглится на стековерфлоу )))
Цитата:
Сообщение от
Андре
должны возникать и в том случае, если метод и без дефолтных параметров. Более того, и ответы на них вроде будут те же самые.
угу.
Цитата:
Сообщение от
Андре
Здравый смысл.
понятно.
Цитата:
Сообщение от
Андре
Многие фреймворки для тестирования позволяют все возможные case-ы для проверки записывать в лаконичном табличном виде в виде комментариев и по ним уже генерить вызовы методов тестирования. Есть фреймворки, которые позволяют случайно генерить данные для тестирования (
https://github.com/fscheck/FsCheck). Но я не сторонник таких подходов.
А почему не сторонник?
есть такие фреймоврки.
но в аксапте их нет.
стоит ли добавлять в аксапту?
стоит ли писать свой велосипед для подобных случаев?
Цитата:
Сообщение от
Андре
Попробую объяснить. Этой мой unit test и это мой код, который я тестирую. Я его знаю. Я могу быть не уверен, работает ли он корректно, но подразумевается, что я достаточно хорошо его понимаю
А вот тут похоже и есть корень.
В аксапте чаще наоборот. И об этом писал fed выше.
Мой код использует что-то из стандартного функционала аксапты.
как правило, я не до конца понимаю как работает стандарт на всех граничных значениях.
как правило, я не понимаю нафига сделано именно так.
мало того, как правило, мой код всего лишь расширяет поведение какого-то стандартного метода.
мало того, с Аксаптой работают разные команды людей. причем могут работать одновременно. у разных команд может быть свое представление о происходящем.
причем это не только в мс. на проектах абсолютно то же самое.
и в этих условиях я должен изобразить что-то "сторожевое". )))
ну, т.е. понятно, что завсегда можно использовать "тяп-ляп и продакшн".
понятно, что каждую конкретную задачу решить можно.
вопрос то: как правильно? )))
пока есть ответ "Здравый смысл"
=================
не уверен, что понадобиться, но вот полный код метода.
повторюсь, что это очень и очень давний метод, который можно проследить до самых первых версий аксапты, в которых он был простым как пареная репа.
X++:
private boolean findDisc(PriceType _relation,
InventDimId _inventDimId,
TableGroupAll _itemCode = 0,
ItemId _itemRel = '',
TableGroupAll _accountCode = 0,
CustVendAC _accountRel = '',
UnitOfMeasureSymbol _unitID = '',
Qty _quantityAmount = 0,
CurrencyCode _currency = CompanyInfoHelper::standardCurrency(),
AgreementHeaderExtRecId_RU _agreementHeaderExtRecId = 0,
CustVendAC _agreementPartnerCode = '')
{
PriceDiscTable priceDiscTable;
boolean discExist;
container key;
container cacheValue;
int i;
FromDate localFromDate;
ToDate localToDate;
AmountQty localQuantityAmountFrom;
AmountQuantityTo localQuantityAmountTo;
RecId localRecid;
boolean cacheMode;
// <GEERU>
CustVendAC accountRelation = _accountRel;
// </GEERU>
void reselectBuffer()
{
if (cacheMode)
{
priceDiscTable = PriceDiscTable::findRecId(localRecid);
}
}
void findDisc()
{
if ((discDate >= localFromDate || ! localFromDate)
&& (discDate <= localToDate || ! localToDate))
{
if (_relation == PriceType::EndDiscPurch ||
_relation == PriceType::EndDiscSales )
{
// for end discounts, the QuantiyAmountField field contains order total amounts, not quantities
if (this.calcCur2CurPriceAmount(localQuantityAmountFrom, priceDiscTable) <= qty &&
((qty < this.calcCur2CurPriceAmount(localQuantityAmountTo, priceDiscTable)) || !localQuantityAmountTo))
{
reselectBuffer();
discExist = true;
discAmount += this.calcCur2CurPriceAmount(priceDiscTable.Amount, priceDiscTable)/ this.priceUnit();
percent1 += priceDiscTable.Percent1;
percent2 += priceDiscTable.Percent2;
actualDiscTable = priceDiscTable.data();
quantityAmount += priceDiscTable.QuantityAmountFrom;
}
}
else
{
if (localQuantityAmountFrom <= qty
&& (qty < localQuantityAmountTo || !localQuantityAmountTo))
{
reselectBuffer();
discExist = true;
discAmount += this.calcCur2CurPriceAmount(priceDiscTable.Amount, priceDiscTable)/ this.priceUnit();
percent1 += priceDiscTable.Percent1;
percent2 += priceDiscTable.Percent2;
actualDiscTable = priceDiscTable.data();
quantityAmount += priceDiscTable.QuantityAmountFrom;
this.mcrPriceDiscTableFound(priceDiscTable);
}
else
{
// If quantity does not qualify, but calculation potential then add as found
if (this.parmMCRPriceHistoryPotentialCalc())
{
reselectBuffer();
this.mcrPriceDiscTableFound(priceDiscTable);
}
}
}
}
}
// <GEERU>
if (countryRegion_RU)
{
if (_accountCode == TableGroupAll::Table &&
_agreementHeaderExtRecId &&
_agreementPartnerCode)
{
accountRelation = _agreementPartnerCode;
}
}
// </GEERU>
if (!_inventDimId)
{
return false;
}
// To avoid flooding the cache the most granualated setup isn't cached.
cacheMode = (_itemCode != TableGroupAll::Table
|| _accountCode != TableGroupAll::Table)
&& !this.parmMCRPriceHistoryPotentialCalc();
cacheValue = conNull();
if (cacheMode)
{
key = this.makeKey(_relation,
_itemCode,
_itemRel,
_accountCode,
// <GEERU>
accountRelation,
// </GEERU>
_unitID,
_currency,
_inventDimId
// <GEERU>
,_agreementHeaderExtRecId
// </GEERU>
);
cacheValue = PriceDisc::getPriceDiscCacheValue(#cacheScope_FindDisc, key);
}
qty = abs(_quantityAmount);
if (cacheValue == conNull())
{
if (_itemCode != TableGroupAll::Table)
{
_unitID = '';
}
while select priceDiscTable
order by QuantityAmountFrom, FromDate
where priceDiscTable.Relation == _relation
&& priceDiscTable.ItemCode == _itemCode
&& priceDiscTable.ItemRelation == _itemRel
&& priceDiscTable.AccountCode == _accountCode
// <GEERU>
&& priceDiscTable.AccountRelation == accountRelation
// </GEERU>
&& priceDiscTable.UnitId == _unitID
&& (priceDiscTable.Currency == _currency
|| (priceDiscTable.GenericCurrency
&& priceDiscTable.Currency == genericCurrency))
// <GEERU>
&& (!countryRegion_RU || priceDiscTable.AgreementHeaderExt_RU == _agreementHeaderExtRecId)
// </GEERU>
&& (priceDiscTable.InventDimId == _inventDimId || this.parmMCRPriceHistoryPotentialCalc())
{
if (cacheMode)
{
cacheValue += [[priceDiscTable.FromDate, priceDiscTable.ToDate, priceDiscTable.QuantityAmountFrom, priceDiscTable.QuantityAmountTo, priceDiscTable.RecId]];
}
else
{
localFromDate = priceDiscTable.FromDate;
localToDate = priceDiscTable.ToDate;
localQuantityAmountFrom = priceDiscTable.QuantityAmountFrom;
localQuantityAmountTo = priceDiscTable.QuantityAmountTo;
localRecid = priceDiscTable.RecId;
findDisc();
if (discExist
&& !priceDiscTable.SearchAgain)
{
searchAgain = false;
break;
}
}
}
if (cacheMode)
{
//We also want to cache the absence of discounts.
if (cacheValue == conNull())
{
cacheValue = [[0]];
}
PriceDisc::insertPriceDiscCache(#cacheScope_FindDisc, key, cacheValue);
}
}
if (cacheMode
&& cacheValue)
{
discExist = false;
for (i=1;i<=conLen(cacheValue);i++)
{
[localFromDate, localToDate, localQuantityAmountFrom, localQuantityAmountTo, localRecid] = conPeek(cacheValue, i);
if (localRecid)
{
findDisc();
if (discExist
&& !priceDiscTable.SearchAgain
&& !this.parmMCRPriceHistoryPotentialCalc())
{
searchAgain = false;
break;
}
}
}
}
return discExist;
}