Original in Russian: http://programmingmindstream.blogspot.ru/2015/09/blog-post.html
The previous series was here – Introduction. Let’s create tests for script words.
I separated “words in dictionary” from tests there.
Now I will put them together:
string.ms.dict:
String.ms.script:
The result of the tests:
String.ms.script.out
In order to put it together I introduced the word TestsFor and RunTests.
TestsFor – determines tests for the word.
RunTests – launches tests for the word.
These look as follows:
Testing.ms.dict:
Nothing “exorbitant”.
The test just “moved” closer to the code for testing.
Yet, this is actually not so bad.
It is sort of “encapsulation of code and its contracts”.
The code and the tests are together now.
After all, tests are “the contracts to the code” in some way.
They work when “static typing” fails.
I’ll remind you the right words of Roman Yankovsky:
http://programmingmindstream.blogspot.ru/2013/11/tdd_28.html?showComment=1386063749826#c6337489882377572276
Actually, the idea was developed there.
The idea is not new.
Barbara Liskov developed a similar one.
In one separate case I “lived the idea out”.
In closing, I’ll refer to a simple thought I like.
If the code may be tested easily, it has to be tested.
It is great when tests are put together with the code or encapsulated in it.
In this case tests are not only used for checking, but also as examples of code use as well as the real demonstration of boundary conditions.
If you make “one more step”, than you will see the base requirements in the combination of code, tests and specification.
Let me also recommend you a book by Barbara Liskov and John Guttag – “Abstraction and Specification in Program Development”.
This is one of my favorite books.
The previous series was here – Introduction. Let’s create tests for script words.
I separated “words in dictionary” from tests there.
Now I will put them together:
string.ms.dict:
// string.ms.dict.web USES Documentation.ms.dict params.ms.dict core.ms.dict map.ms.dict Testing.ms.dict io.ms.dict ; : (string) ^ IN aValue aValue DO ToPrintable ; // (string) STRING FUNCTION string:CatWihAny STRING IN aString IN aValue aString aValue ToPrintable Cat =: Result ; // string:CatWihAny STRING FUNCTION any:Cat ARRAY IN anArray anArray .map> ToPrintable strings:Cat =: Result ; // any:Cat TestsFor any:Cat Test T1 [ 'A' 123 'B' ] any:Cat Print ; Test T2 [ 'A' 124 'B' ] any:Cat Print ; ; // TestsFor any:Cat STRING FUNCTION (+)? STRING in aPrefix STRING right aSuffix %SUMMARY 'If aSuffix is not empty, it returns the sum of aPrefix and aSuffix, otherwise or returns a blank string' ; Result := '' STRING VAR l_Suffix aSuffix =: l_Suffix if ( l_Suffix =/= '' ) then ( aPrefix l_Suffix Cat =: Result ) ; // (+)? TestsFor (+)? Test T1 '' (+)? 'B' Print ; Test T2 'A' (+)? 'B' Print ; Test T3 'A' (+)? '' Print ; Test T4 'A' (+)? 'D' Print ; Test T5 'A' (+)? '123' Print ; ; // TestsFor (+)? STRING FUNCTION ?(+) STRING in aPrefix STRING right aSuffix %SUMMARY 'If aPrefix is not empty, it returns the sum of aPrefix and aSuffix, otherwise or returns a blank string ' ; Result := '' if ( aPrefix =/= '' ) then ( aPrefix aSuffix Cat =: Result ) ; // ?(+) TestsFor ?(+) Test T1 '' ?(+) 'B' Print ; Test T2 'A' ?(+) 'B' Print ; Test T3 'A' ?(+) '' Print ; ; // TestsFor ?(+) STRING FUNCTION strings:CatSep> STRING right aSep ARRAY right aValues aValues aSep strings:CatSep =: Result ; // strings:CatSep> TestsFor strings:CatSep> Test T1 strings:CatSep> ' ' [ 'A' 'B' ] Print ; Test T2 strings:CatSep> ' ' [ 'A ' 'B' ] Print ; Test T3 strings:CatSep> ' ' [ 'A ' ' B' ] Print ; Test T4 strings:CatSep> ' ' [ 'A' ' B' ] Print ; Test T5 strings:CatSep> ' ' [ '' 'B' ] Print ; Test T6 strings:CatSep> ' ' [ 'A' '' ] Print ; ; // TestsFor strings:CatSep> WordAlias CatSep> strings:CatSep>
String.ms.script:
USES Documentation.ms.dict string.ms.dict Testing.ms.dict ; RunTests (+)? %REMARK 'Launch the “standard tests” for the word (+)?' RunTests ?(+) %REMARK 'Launch the “standard tests” for the word ? (+)' RunTests strings:CatSep> %REMARK 'Launch the “standard tests” for the word strings:CatSep>' RunTests any:Cat %REMARK ' Launch the “standard tests” for the word any:Cat'
The result of the tests:
String.ms.script.out
Testing: (+)? T1 B T2 AB T3 T4 AD T5 A123 Testing end: (+)? ------------------ Testing: ?(+) T1 T2 AB T3 A Testing end: ?(+) ------------------ Testing: strings:CatSep> T1 A B T2 A B T3 A B T4 A B T5 B T6 A Testing end: strings:CatSep> ------------------ Testing: any:Cat T1 A123B T2 A124B Testing end: any:Cat ------------------
In order to put it together I introduced the word TestsFor and RunTests.
TestsFor – determines tests for the word.
RunTests – launches tests for the word.
These look as follows:
Testing.ms.dict:
// Testing.ms.dict USES axiom_push.ms.dict macro.ms.dict params.ms.dict io.ms.dict EngineTypes.ms.dict Documentation.ms.dict ; CONST cTests 'Tests:' MACRO TestsFor ENGINE_WORD RIGHT LINK IN aName %REMARK 'aName link to the word at the right of TestsFor' %SUMMARY 'Determines the tests set for word aName' ; axiom:PushSymbol VOID axiom:PushSymbol axiom:operator cTests aName |N Cat Ctx:Parser:PushSymbol ; // TestsFor PRIVATE PROCEDURE DoRunTestsFor STRING IN aTestedWordName ENGINE_WORD IN aTestsHolder %SUMMARY 'Executes tests for aTestsHolder' ; [ 'Testing: ' aTestedWordName ] strings:Cat Print aTestsHolder MembersIterator ==> ( IN aTest %REMARK 'aTest – embedded element aTestsHolder' if ( ( aTest %ST |N ) = ( NameOf Test ) ) then %REMARK '- filtrates tests only.' begin aTest |N Print %REMARK 'Print the test name' aTest DO %REMARK 'Launch the test' end // ( ( aTest %ST |N ) = 'Test' ) ) [ 'Testing end: ' aTestedWordName ] strings:Cat Print '------------------' Print ; // DoRunTestsFor MACRO RunTests ENGINE_WORD RIGHT LINK IN aName %REMARK 'aName link to the word at the right of RunTests' %SUMMARY 'Executes tests for aName' ; STRING VAR l_Name aName |N >>> l_Name STRING VAR l_TestsHolderName cTests l_Name Cat >>> l_TestsHolderName l_Name Ctx:Parser:PushString axiom:PushSymbol @ l_TestsHolderName Ctx:Parser:PushSymbol axiom:PushSymbol DoRunTestsFor ; // RunTests
Nothing “exorbitant”.
The test just “moved” closer to the code for testing.
Yet, this is actually not so bad.
It is sort of “encapsulation of code and its contracts”.
The code and the tests are together now.
After all, tests are “the contracts to the code” in some way.
They work when “static typing” fails.
I’ll remind you the right words of Roman Yankovsky:
"To some extend, unit-tests and static typing solve the same tasks. This is probably the reason why tests were adopted in areas where static typing is not available.
What is static typing? This is the code requirements description the conformity to which the code is checked by the compiler. What are unit tests? Again, these are the requirements the code should confirm with.
This understanding of unit tests eliminates the antilogies. What is the starting point of developing on languages with static typing? Types description! What is the starting point of developing on TDD? Tests writing! Thus, architecture first is suitable in both cases.
It looks not obvious and confusing, but this is due to underdeveloped means of language we use. However, the way how we describe the requirements to the input and output data of some function makes no difference, since we only describe the TYPE."
http://programmingmindstream.blogspot.ru/2013/11/tdd_28.html?showComment=1386063749826#c6337489882377572276
Actually, the idea was developed there.
The idea is not new.
Barbara Liskov developed a similar one.
In one separate case I “lived the idea out”.
In closing, I’ll refer to a simple thought I like.
If the code may be tested easily, it has to be tested.
It is great when tests are put together with the code or encapsulated in it.
In this case tests are not only used for checking, but also as examples of code use as well as the real demonstration of boundary conditions.
If you make “one more step”, than you will see the base requirements in the combination of code, tests and specification.
Let me also recommend you a book by Barbara Liskov and John Guttag – “Abstraction and Specification in Program Development”.
This is one of my favorite books.
Комментариев нет:
Отправить комментарий