GET The world's best ghost with a motor, or integration testing complex client-server applications / Sudo Null IT News FREE

At the final stage of 2014, we introduced a new ware in the logical argument of berth controls - ASPxRichEdit . Our end was to create a powerful tool for running with documents online. Implementation of the requirements made aside users for a text editor in chief - support for text formatting styles and paragraphs, load and saving documents of popular formats without losing content, impression settings - all this implies intensive fundamental interaction between the client and the waiter.

In this article, I will talk of the town all but the approaches to examination this interaction that we utilized during the development process.

Toolkit Used

When nonindustrial the architecture of any serious project, regardless of the program and tools used, there is a very beta point - all the legibility, portability and structure of the code do not matter if this code cannot be overgrown by tests. Tests should be written and run easily and quickly, victimisation only the stripped necessary code. In this case, the developers will write the cypher and now cover it with tests, or, guided by the mantra "red / green / refactoring", drop a line tests, then follow out new functionality. But if in order to write tests, you need divine knowledge that is available only to the project architect - the code volition not personify covered by tests.

The choice of tools for independent testing of server and guest code was non rocky for us - we settled on usingNUnit as a server test theoretical account and Jasmine for testing customer code. As a runner for client tests, we used Chutzpah , which has become almost the authoritative .

Client-Server Interaction Poser

Withal, in the lawsuit of ASPxRichEdit, it was important to cover with tests not only the process of sending and processing requests, but also the synchronization of client and host states. The main tax of desegregation testing in this case was to make sure that any body politic of the server model is correctly interpreted on the client. In release, any change to the document on the client should correctly croak to the host and lead to the corresponding changes in the server model.

In our case, the client model largely repeats the server poser - the desktop version of the rich editor has been nonindustrial in DevExpress for Sir Thomas More than eight years, and so for the host part it was distinct to fare without the invention of a bicycle, accompanied by exciting walks on the rake, and the presence of a "mirror" model connected the client simplifies synchronization. In my opinion, this approach does not have any particular specifics; for sure, the same situation bum be observed in many applications based on the "old" server code. In this case, to guarantee interaction, you postulate code that is capable to change JSON supported the server model and change this model based on the JSON that came from the customer, and write in code that solves the Saame tasks happening the client. The easiest way to make such a encode is auto-generated, with which the studio templet engine does an fantabulous jobT4 Text Templates .

Victimization PhantomJS for Integration Tests

Thus, we involve to exam how client requests are interpreted by the waiter, and how the client responds to the response standard from the server. The host portion of the test is typewritten using the already mentioned NUnit, and to start the client share we decided to use PhantomJS . The last mentioned is a full-fledged web browser supported WebKit (JavaScript, CSS, DOM, SVG, Canvas), without UI elements, but quite tight and easy. This combination allows us to test the initialization of the client settled on the waiter model, the application of client changes connected the waiter, and server model changes on the client, too American Samoa thinkable conflicts during state synchronization.

In general, a test is a fairly simple cycle. First, the waiter model is created and configured, so the working academic term forms the starting JSON for initializing the client (in the case of real documents, the model is divided into parts and only the first fragment is transmitted at the first load, and the rest is loaded asynchronously - while the server will return the subsequent parts, the client will already glucinium busy misestimation of the existing part; in the tests, the documents are small, indeed the initialisation JSON contains the full model). Future, the server code launches PhantomJS with our libraries and start script. The script creates an instance of the client control and initializes it with a JSON object formed on the server. Further logic varies depending on the intent of the psychometric test.

If we test the initialization of the model, then the resulting mannequin is at once serialized second to JSON and displayed in the soothe, and the server code analyzes the contents of the console and verifies that the client model was created right. If we trial run the world of JSON objects happening the client and their interpretation connected the host, then in this case the necessary operations are performed on the client, and wholly requests instead of sending to the server are once again written to the console. Next, the server encrypt reads the table of contents of the buffer, changes the model, and checks how correctly the incoming commands were prepared.

The described algorithmic program can be illustrated with a specific example of an integration test:

          [              Screen            ]                                                            public                                                                                            void                                                                                            TestParagraphProperties                                            (                                            )                        {     ChangeDocumentModel();                          // предварительная настройка серверной модели                                      drawstring            [] clientResults = RunClientSide(         GetClientModelStateAction(),                          // записать Model в Output                        ExecuteClientCommandAction()                          // выполнить клиентскую команду, записать реквест в Output                        );                          // clientResults[0] – JSON с клиентским состоянием модели (инициализация)                                      // clientResults[1] – JSON с реквестом на изменение серверной модели                        AssertClientModelState(clientResults[              0            ]);     ApplyClientRequestToServerModel(clientResults[              1            ]);     AssertServerModelState(DocumentModel); }                  

As you can see, the code of the resulting test is quite simple. After setting up the waiter model, we launch PhantomJS. In this case, the RunClientSide () procedure takes an array of actions that must be performed on the client (for example, executing commands that modify the model, obtaining the serialized state of the client model). The result of each action will be stored in the production array, e.g.:

                                                                      function                                                                                            getClientModelState                                            (                                            )                          {                          volt-ampere                        model = control.getModel();    buffer.drive(              JSON            .stringify(modeling)); }                  

Future, the resultant array is serialized in JSON and written to console.log (i.e. covering output signal):

                                                                      function                                                                                            tearDownTest                                            (                                            )                          {                          console            .log(              JSON            .stringify(buff)); }                  

Test runner implementation code:

                                                                      string                                                                                            StartPhantomJSNoDebug                                            (                                                                                          drawstring                                                                                                            phantomPath,                                                                                                              train                                                                                                            bootFile,                                                                                                              out                                                                                                                                                                                    int                                                                                                            exitCode                                            )                        {             StringBuilder outputSb =                          new                        StringBuilder();             StringBuilder errorsSb =                          unexampled                        StringBuilder();             exitCode =                          -1            ;                          using                        (              volt-ampere                        p =                          spic-and-span                        Process()) {                          var                        arguments = Path.Merge(TestDirectory, bootFile);                          //...                                      //rig skyward process properties                        p.OutputDataReceived += (s, e) => outputSb.AppendLine(e.Data);                 p.ErrorDataReceived += (s, e) => errorsSb.AppendLine(e.Data);                 p.Start();                 p.BeginOutputReadLine();                 p.BeginErrorReadLine();                          if                        (!p.WaitForExit(              15000            )) {                     p.Kill();                     p.WaitForExit();                     Assert.Fail(              "The PhantomJS process was killed afterward timeout. Output: \r\n"                        + outputSb.ToString());                 }                          else                        p.WaitForExit();                 exitCode = p.ExitCode;             }                          if                        (!              string            .IsNullOrWhiteSpace(errorsSb.ToString()))                 Assert.Fail(              "PhantomJS errors output: \r\n"                        + errorsSb.ToString());                          return                        outputSb.ToString();         }                  

If you need to look low-level the debugger what happens in the tests, then the runner will be like this:

                                                                      string                                                                                            StartPhantomJSWithDebug                                            (                                                                                          thread                                                                                                            phantomPath,                                                                                                              string                                                                                                            bootFile,                                                                                                              out                                                                                                                                                                                    int                                                                                                            exitCode                                            )                        {             StringBuilder outputSb =                          new-sprung                        StringBuilder();             StringBuilder errorsSb =                          new                        StringBuilder();             exitCode =                          -1            ;                          exploitation                        (              var                        p =                          new                        Process()) {                          volt-ampere                        arguments = Path.Combine(TestDirectory, bootFile);                 arguments =                          "--remote-debugger-port wine=9001 "                        + arguments;                          //...                                      //ensnare process properties                        p.Start();                 Ribbon.Sleep(              500            );                          try                        {                    Process.Start(              @"chromium-plate.exe"            ,                          @"http://localhost:9001/webkit/inspector/inspector.html?page=1"            );                 }                          catch                        { }                 p.WaitForExit();             }                          if                        (!              drawstring            .IsNullOrWhiteSpace(errorsSb.ToString()))                 Assert.Bomb(              "PhantomJS errors turnout: \r\n"                        + errorsSb.ToString());                          return                        outputSb.ToString();         }                  

Then, the received JSON is processed on the server, after which the de facto examination is performed - checking the position of the client model, applying the JSON resulting from the execution of the client code and checking the position of the host model.

Thus, with the help of PhantomJS, we were healthy to write integration tests that allow us to check the initialisation and subsequent synchronising of a complex client-server application.

DOWNLOAD HERE

GET The world's best ghost with a motor, or integration testing complex client-server applications / Sudo Null IT News FREE

Posted by: burrowswituabled.blogspot.com

0 Response to "GET The world's best ghost with a motor, or integration testing complex client-server applications / Sudo Null IT News FREE"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel