📜 ⬆️ ⬇️

Unit tests in Caché are just

Most of all, programmers love programs that don’t need to fix bugs. A step on the way to this unrealistic dream is writing unit tests. In Caché, as in any modern DBMS, there is an implementation of a framework for automatic execution of tests.



For a detailed description of the philosophy and methodology of writing unit tests, I refer you to the Internet - to Habr and to the wonderful book “Growing Object-Oriented Software Guided by Tests”. It is not translated into Russian, but English is simple and understandable there.

As an example, we will write a thoroughly tested method that takes a last name, first name and position at the entrance, stores them in a table and returns the id of the created object. The table will be called Tutorial.Person .
')
According to all TDD canons, we first create a test:

Class Tutorial.Test.Person Extends% UnitTest.TestCase
{
Method TestNewPerson () {
set surname = "John"
set name = "Doe"
set job = "quality assurance developer"
set id = ## class ( Tutorial.Person ). AddPerson ( surname , name , job ,. Ec )
do $$$ AssertStatusOK ( ec )

set p = ## class ( Tutorial.Person ). % Openid ( id )
do $$$ AssertTrue ( $ IsObject ( p ))

do $$$ AssertEquals ( p . Surname , surname )
do $$$ AssertEquals ( p . Name , name )
do $$$ AssertEquals ( p . Job , job )
}
}

The class containing the tests must inherit from the % UnitTest.TestCase class. All methods of this class that begin with the word Test are considered tests. Macros and methods available to the heirs of % UnitTest.TestCase are described in the documentation .

The tests runs the ## class method (% UnitTest.Manager). RunTest (subdir, spec) . This method loads and executes all classes with tests from the subdir subdir of the directory that is specified in the global ^ UnitTestRoot . Spec - additional keys to run. By default, after execution, classes with tests are deleted. We will not allow this, of course, by adding the second argument to the RunTest line with the key " / nodelete ".

So, create a folder c: \ unittests \ habr and export our class with a test to it (it is clear that you can name the folder as you like and that it would be better to call the subfolder tutorial, denoting the package that we will check; but to emphasize that these names do not have to match, I called the subfolder habr). Export the test to this folder (I called the file tutorial.test.person.xml ) and go to the terminal!

USER>set ^UnitTestRoot="c:\UnitTests" USER>do ##class(%UnitTest.Manager).RunTest("habr","/nodelete/noload") ================================================================== Directory: C:\UnitTests\habr\ ================================================================== habr begins ...      07/26/2015 00:59:23 '*.xml;*.XML'   C:\UnitTests\habr\tutorial.test.person.xml  xml   . Tutorial.Test.Person begins ... TestNewPerson() begins ... LogStateStatus:0:TestNewPerson: #5002: : <CLASS DOES NOT EXIST>zTestNewPerson+4^Tutorial.Test.Person.1 *Tutorial.Person <<==== **FAILED** habr:Tutorial.Test.Person:TestNewPerson: TestNewPerson failed Tutorial.Test.Person failed Skipping deleting classes habr failed Use the following URL to view the result: http://192.168.1.6:57772/csp/sys/%25UnitTest.Portal.Indices.cls?Index=2&$NAMESPACE=USER Some tests FAILED in suites: habr 

Please note - I have specified two keys in the RunTest method: / nodelete — do not delete the class with tests after launch, / noload — do not load and do not compile the class itself.

As you can see, our test successfully ended with an error. At the end of the output, the URL for the web interface of the results of the test and the launch history is printed. Note that this URL refers to the web application / csp / sys , indicating the desired area by the argument. If you change the area to USER in the Management Portal and then follow the links System Explorer> Tools> UnitTest Portal , you will probably see a Forbidden error when you try to open the following URL:

 http://<yourhost>:<yourport>/csp/user/%25UnitTest.Portal.Home.zen?$NAMESPACE=USER 

This error is caused by the fact that Caché by default prohibits accessing system (percentage) pages from web applications that do not begin with / csp / sys. To allow opening of pages related to unit tests in the USER area, execute the following command in the terminal in the% SYS area:

 %SYS>Set ^SYS("Security","CSP","AllowPrefix","/csp/user/","%UnitTest.")=1 

Since there are almost always a lot of classes with tests, I create a separate class with a method that first uploads all classes with tests to the directory, and then calls RunTest:

Class Tutorial.Test.All [ Abstract ]
{
ClassMethod runall ()
{
do $ system .OBJ . Export ( "Tutorial.Test.Person.cls" , ^ UnitTestRoot_ "\ habr \" _ "tutorial.test.person.xml" )
; here you can add export of new classes with tests.

do ## class ( % UnitTest.Manager ). RunTest ( "habr" , "/ nodelete / noload" )
}
}

The last thing left is to create the Tutorial.Person class and the AddPerson method, run the tests and see the long-awaited “ ALL PASSED ”:

 USER>do ##class(Tutorial.Test.All).runall()   XML   07/26/2015 01:25:12  : Tutorial.Test.Person   . ================================================================== Directory: C:\UnitTests\habr\ ================================================================== habr begins ...      07/26/2015 01:25:12 '*.xml;*.XML'   C:\UnitTests\habr\tutorial.test.person.xml  xml   . Tutorial.Test.Person begins ... TestNewPerson() begins ... AssertStatusOK:ec (passed) AssertTrue:$IsObject(p) (passed) AssertEquals:p.Surname== surname (passed) AssertEquals:p.Name== name (passed) AssertEquals:p.Job== job (passed) LogMessage:Duration of execution: .000503 sec. TestNewPerson passed Tutorial.Test.Person passed Skipping deleting classes habr passed Use the following URL to view the result: http://192.168.1.6:57772/csp/sys/%25UnitTest.Portal.Indices.cls?Index=7&$NAMESPACE=USER All PASSED 

At this point, an inquisitive reader (hello, tsafin ) will be indignant : “ Why are there so many perversions to run a simple test ?! Could it be any simpler? ". Of course you can not ! But not much easier. If the c: \ UnitTests \ habr folder is present and the path “c: \ UnitTests” is specified in ^ UnitTestRoot, then you can start a separate class with tests (without first unloading) as follows:

 do ##class(%UnitTest.Manager).DebugRunTestCase("habr","Tutorial.Test.Person") 

Don't forget, Caché is a DBMS. All test results are saved and available for SQL queries. Open Portal window for SQL input. Check the box next to System to show the system classes. Select the% UnitTest_Result scheme from the drop-down list. For example, in the Duration column of some tables in this scheme, the duration of an individual test (or a method inside a test) is stored. By running tests regularly, you can watch not only so that they do not fall, but also so that the time to complete them does not increase.

In conclusion, I recommend to go through a small tutorial on unit tests, which is in the Caché documentation, and also to look at the class descriptions of the% UnitTest package in the class reference book.

Source: https://habr.com/ru/post/263677/


All Articles