📜 ⬆️ ⬇️

Integration of scenario testing in the development of solutions based on the 1C platform

This article is a practical guide to the introduction of scenario-based testing into the software development process based on the 1C: Enterprise 8.3 platform. The document is distinguished by an applied focus, it contains a lot of code, approaches and specifics. All considered examples are based on the use of a free Tester configuration.


Introduction


Regardless of which philosophy the company adheres to, one thing remains unchanged - the process of programming applications with a user interface includes program launch, emulation of user actions, visual analysis of the situation, return to code refinement, and so on, followed by iteration. Basically, in this scheme we can distinguish two periods of time: programming and testing. The time spent on programming turns into code. The time spent on checks is irretrievable. Due to the specifics of the development process, when we run the application again and again, repeating iterations, compensation for lost time is achieved by reducing the second time interval, or shifting all checks to a certain “final” iteration or running the BDD test. The inability to repeat the experience of inspections adversely affects the quality of the software product.

In many ways, these issues are solved by the introduction of special techniques, for example, TDD, BDD, the organization of additional testing processes. However, there are nuances everywhere.
')
For example, TDD substantially revises the programmer’s view of development, and in the case of interactive applications with a deep tie in business logic on the database, especially when creating configurations with a flexible system of rights and functional options, the technique is not easy to apply.

BDD, at the expense of the human scripting language Gherkin, ideologically stitches in one place the specialists of the applied and technical fields, and the used construction of the given-when-then script description is universal. However, BDD is more about the process of creating a product, and not just about testing it. BDD is based on the role-based interaction of the company's employees, which makes it demanding (and to some extent fragile) to all links of the development chain. Another important problem is not the high efficiency of the Gherkin language in the development of complex (from the point of view of BDD) scripts. To automatic documentation, as a bonus BDD, also, a lot of questions. User manuals for products of well-known vendors are not built on the principle of Given - When - Then, but with technical documentation, many people choose the approach “Outdated but understandable than actual, but incomprehensible (or understandable only to the author of the script) approach.

Historically, TDD, BDD and others, came from the world where the 1C system is not as a class, where there is a very clear specialization, and the gap between the tasks understood by the technical specialist and the business, as a rule, is great. For example, in a typical 1C-franchisee, very often tasks go along a pipeline, can be received by phone, Skype or email. The organization of meetings for each revision in the format of three friends (Three Amigos) looks frivolous, which means almost the whole BDD methodology is distorted or even broken.

At the same time, on large projects, these negotiations are necessary. Ideally, there will be an analyst, tester and developer (BA + QA + Developer), but there will not be an entire programmers department. And they, ultimately, write code, conduct testing, often much more profound, with boundary values, deviations, and other implementation features, the occurrence of which is born in the code and cannot be described in the acceptance test or problem statement. And this will not be TDD, but real scenario tests that programmers do not usually automate, but perform manually as part of the encoding process.

Another example from the life of a 1C programmer: a typical scenario is considered (the example is described not for Russian legislation): Calculation of leave to an employee, where you need to take into account previous charges for the past three months, including the number of holidays for the calculation period, holidays that fell on weekends, if they it provides for its work schedule, quarterly, annual and fixed amount of bonuses that may not be accrued during the period of their calculations, change of position and / or work schedule, consideration of the direct tabulation system or the off method neny, as well as the period of the leave should be cleaned from the holidays. If the employee is part of the vacation sick - the next extension should take into account previous charges, in addition, it is necessary to provide for the intersection of the accrual periods (week / two weeks / month / shift) with the leave period and other characteristics. The scenario in this case is usually a legislative act or an article from accounting periodicals, which in most cases is considered to be a task for the 1C programmer. Attempting to organize (and not just write) scenario testing in the Gherkin language for this completely standard script can be a real challenge.

Despite the popularity of various approaches to the struggle for the quality of programs, developed technologies for the rapid development of 1C applications require their adaptation. The question is not whether it is possible or impossible to use this or that technique in the programmers department, the question is how effective it is, and if 1C programmers start writing BDD scripts themselves, most likely something went wrong.

Anyway, with the right approach, any kind of testing, as per the method, degree of automation, and place of use is very useful. For example, testing performed by testers is a very important filter for catching errors in the program development life cycle, and not just because more is better, but because testing specialists are not predisposed to making mistakes peculiar to developers.

In reality, one has to deal not only with the choice of testing methods, but also with the problem of the final cost of the achieved quality, efficiency. Unfortunately, due to the prevalence of theoretical materials with success stories over practical methods, quite a few teams almost rightly consider automated testing a luxury or indulgence that big companies or enthusiastic enthusiasts can afford.

About Configuration Tester


Free solution for conducting scenario testing of applications based on 1C: Enterprise 8.3, managed forms. The tester is designed to preserve and reproduce the experience of the programmer, the time for the acquisition of which was spent on manual checks and testing. The main profit from the use of Tester is to improve the quality of programs, without significant organizational changes, changes in programming principles, and other long-term investments of time for the release of regular product versions. The tester can be used as an independent tool, or in conjunction with BDD, acting as a platform for developing complex tests.

Opportunities:



Features:



Other uses:


The tester can be used as an automator of routine operations, both in the development process and in the real operation mode of the product bases. Among these tasks are:
Latest updateshttps://github.com/grumagargler/tester
Depot General Testshttps://github.com/grumagargler/CommonTests
Depot demo tests for ERP2 (demo)https://github.com/grumagargler/ERP2
Project websitehttp://www.test1c.com
TongueInterface: English, Russian
Reference: English (partially), Russian

Basic definitions


The process of testing applications using the Tester is based on the interaction of the Tester with the running 1C configuration in 1C: Enterprise mode.

In this case, it is considered that the Tester acts as a Testing Manager, and the configuration under test is considered as a Testing Client.

Tester is a scenario testing system. This means that interaction with the application under test occurs in the emulation mode of user actions.

All that is required to be tested should be described by the algorithm in the 1C programming language. The set of programmable logic defines the notion of scenario. All scenarios are developed and stored in Tester.

The tester can interact with the application under test only in the way that the user can do, on behalf of which the scenario tests are performed. Hence, an important note is formulated: the mechanisms under development for the application under test must be verifiable. For example, if there is a task to check the correctness of document movements, and there is no report on document movements in the system and there is no report / processing / form through which the user could check the records, the Tester will not be able to verify the correctness of movements (in this case, this is the concept However, technically, the Tester can start external processing, in the code of which the programmer can execute arbitrary software verification code).

A tester is an environment where tests are developed, stored and executed. The tester can be used as a cloud application with multi-user access, in which an unlimited number of users, tests and applications under test can be created.

The tester is not a TDD system, and strictly speaking, is not an ideologically pure BDD. The tester tries not to become attached to religion in development, it solves the problems that absolutely software developers face. The tester tries to solve these problems as efficiently as possible.

The tester is intended for testing configurations developed on managed forms of version 1C: Enterprise 8.3.x. Normal forms are not supported.

Prospective Tester users are:
UsersTasks
ProgrammersUsing the system in the development process. The evolution of the manual testing process
Testers with basic knowledge of programming in 1CWriting scripts as close as possible to user scenarios. These scenarios are usually not as deep as those of programmers, but more pronounced in terms of the business process.
Business analytics. ConsultantsRunning tests, analyzing results. Through reading tests, understanding the functionality of the system

Concept


The source of work for the programmer can serve as a technical task, communication tools, BDD-script, inner inspiration and much more. Regardless of the methods of formalization of processes in the company, or lack thereof, any task adapts to the internal specifics of the work of programmers.

Having the information on the task at the entrance, we mentally break the whole encoding process into small transactions, jerks. This is for us a kind of short-term work plan (even if there is a BDD script at the entrance). Then, we begin to work methodically according to the scheme “writing code - launching an application — checking expected behavior — returning to finalizing the code.” The number of such transactions and the degree of their completion are very fragile entities, because they rely on the ability and ability of the programmer to be focused.

Even under ideal conditions for performing work on coding, the experience of these transactions without special tools will not be restored. In addition, if in the middle of the intended path, an unintended situation arises, an error in the associated code or a defect in the mechanism used, the programmer has to switch to another context to parse the problem, often doing so in a hurry, because the intended work plan begins to slip away from the working memory of our brain . When changing the accompanying code, we try to keep the trigger “in mind, then we need to test this code”.

You can use special labels in the code, development environment tools, take screenshots, audio recordings, but these are only return points to problems, the mental context for those moments of time cannot be rolled back. TDD can be applied, but the resulting effect of changes on the behavior of the system as a whole will be very difficult to verify. For example, you changed the request to fill out the document Accrual of the RFP, which is highly dependent on the conditions of hiring employees, vacations, sick leave, changes in personnel conditions, and this affects the calculation of taxes based on these accruals. The involvement of dozens of database tables, a huge number of initial values, can make TDD very difficult, and the falling tests in such cases are not always clear due to the lack of a full scripted context.

Integration into the work of the testing tool will require the programmer to develop the skill of translating a mentally composed work plan into the script program code. This gives him the opportunity to unload by serializing into the test code. Accumulated scenarios can always be reproduced, which allows you to focus on the quality of work performed. The increase in the number of tests gives freedom of action not only for refactoring, but also for other significant changes in the functionality of the application being developed, which is one of the important concepts of the tool.

Fast start


To quickly deploy the testing infrastructure, it is enough to perform the following steps (it is assumed that the Tester has been downloaded and registered in the list of information databases):
  1. Configuration The tester should be launched in 1C: Enterprise mode with the / TESTMANAGER key.
    This parameter can be registered directly in the Tester information base profile, for example:

  2. The tested configuration should be launched in 1C: Enterprise mode with the / TESTCLIENT key.
    This parameter can be registered directly in the profile of the information database being tested, for example:
  3. Version 1C used for testing should be the same for both the Tester and the tested configuration.
  4. Testing and testing configuration should be launched on one computer. To run programs on different computers, you must configure the port and address of the application under test in the Application directory.
From a technical point of view, nothing more is needed to start developing tests and tests.

The first script


Consider an example of creating a test for the configuration of the BSP 2.2.
We write an elementary test that simply opens the form of the list of the directory Partners.
  1. We start the Tester with the / TESTMANAGER key.
  2. Run the BSP with the / TESTCLIENT key.
  3. Switch to Tester, open the quick functions menu and create a new application:

  4. Through the menu of quick functions, open the scripts and create a new script:
    1. In the ID field we write Test1
    2. In the text of the script write:
    3.  (); //      ( " / : " ); //      
    4. Switch to the Properties tab, and in the Application field enter the BSP
    5. Press the button on the panel Main
    6. The test is ready. Now click the Run button (or F5) and run it.
As a result, the list of the Demo: Partners directory should open in the BSP. If during the opening of the directory, there was some kind of error, the tester would have reported it.

Second script


Add to the first test the creation of a new partner, for this we make the following changes to the script:
 //      (); //       (); //       ( " / : " ); //  ,          ( ": " ); //     ( "" ); //  ,          ( ":  ()" ); //     ( "", "  " ); //      ( "" ); //       ( "  " ); 

After completing the test, the base partner should have a new partner.
After the test has been completed, the following message will appear in the Tester message window:
 14:  ""    :  (   /   ),  (   /   ) {1[14]} 

The message says that in the 14th line of the code, the Click method found several places where you can click Create.
In order to uniquely define objects with which interaction is required, it is possible to use identifiers, or the full path.
For example, in line 14 you can write this:
 //  1  ( "!" ); //  2  ( "! / " ); 

For identifiers and the internal content of the forms of the application under test, see the Fields tab .
The following sections are devoted to a complete overview of Tester functions.

Interface


The Tester interface is organized from the standpoint of convenient writing and running tests. When you first start, the system help is displayed on the home page (it is downloaded from the Internet) and the main script opens, if it is set. In the left part of the system there is a text editor for entering the script code, on the right - the script tree.
Unfortunately, at the time of the preparation of this documentation, the system does not yet support the syntactic color scheme of the program modules. Only at first this may seem like a serious problem, but after a short time, you will stop paying attention to it, because initially, the script code is much simpler than the standard configuration code.
Some specialists for a short while preferred using Visual Studio Code with the Language 1C (BSL) extension or the usual 1C configurator for typing the script, then copying or loading into the Tester. However, practice has shown that the value of color design is significantly lower than the programmer's ability to interact with the fields and structure of the application under test, the script tree, the helper, and other functions accessible only from the Tester.

Script Tree


The tester comes with a demo base. The demo database contains a small set of universal tests, as well as special tests for the configuration of ERP2. I suggest using the demo database as a starting base for building your own test infrastructure.
When you start Tester, there is a script tree on the right side of the screen. This tree allows you to organize scripts in a hierarchy. Each tree node has a type. The type specifies the meaning of the scripts inside the node, the sort and the icon. In 1C terminology, this tree is a common hierarchical directory.
The picture below shows an example of a test tree from the demo database, and then a description of each marker is given:


Types of scenarios, Marker 1


To the left of the marker, in green and a special icon, there are such nodes as Recycle Bin, General, Table and others.
This design means that it is a library of tests. The sign that the node is a library is set when creating / editing a test:

The picture shows that in addition to the library, the test can be a folder, script or method.
There is no strict technical binding and control of the script type in the Tester. The main purpose of the types is the organization of the visual logic of the relationship of scenarios.
In case this is a library, it is assumed that only library scripts-methods will be stored inside this folder. A method is a script that should not be tied to the specific logic of the application being tested. Methods can usually take parameters, they work like procedures / functions. Methods should not be run as separate, independent scripts (see the launch of scripts here ).
Example method: CheckError record.
An example of using the script in code:
  ( ".", "  " ); 

Script Groups, Marker 2


This marker shows the Documents folder. A folder is a logical grouping of scripts. Grouping can be arbitrary. You can create test folders on the principle of tested subsystems, user roles or technical tasks. If you do not feel what kind of test structure you need, then a universal approach is to project the test structure onto the metadata objects of your configuration. You can safely create groups of directories, documents, and so on. Inside these groups, create groups with the names of metadata objects, and the next level, have specific scenarios. In the future, if required, you will be able to regroup.

Regular Script Marker 3


Marker marked the standard script. In this case, this is a script called Start. Please note that the pictogram to the left has a small yellow ball on the right, while the script on marker 5 does not have such a ball. The presence of a yellow ball means that inside this script, besides the script of the script, there is also a template. Templates are used to verify the business logic of the application under test. Read more about validating business logic here .

Scenario-method, Marker 4


This marker marks the script method. In this case, the method is inside a normal script group, not in a library. In this case, it is assumed that the method is used by the main scenarios for unloading logic. For example, the Start script will call the Debt Provider Method script, which in turn will generate a report and check the accuracy of the indicators. The tester, in the tree, has the scripts above the methods so that they do not mix.

Main script Marker 5


This marker marks the usual scenario. The underscore indicates that this script is currently current (primary). The main scenario is the one the programmer is currently working on. Any script can be set as the main one (right click on the tree / Main). Each user of the Tester system can have its own main script. The main script differs from the others in that it is easy to find in the tree (right click in the tree / Find the main script) and easy to run (see Running Tests ). Also, the main script automatically opens when you start a new Tester session.

Applications, Marker 6


Under marker 6, there is a column with the name of the application to which the corresponding script belongs.
The application is installed in the script editing form, for any type of script:

The field Application can not be set, leave blank. In this case, the script is assumed to be universal and can work for all applications in the system.
Please note that for library tests and first-level groups (see the picture with the test tree), the application is not specified, and for the group Order Provider, TestCreation, etc. application set. The logic is as follows: library tests can work for any configuration, so when creating them, the application was not specified. The test group Documents will also be in any configuration, the application is also not specified. For the group OrderProvider, TestCreation, etc. the application is set because they have a clear binding to the application under test.
To set an application for scripts:
  1. For logical grouping of scenarios and the possibility of selecting scenarios in the test tree, see the picture:
  2. To control the uniqueness of script names. For example, there may be several tests with the name Order Supplier for each of them if a separate application is specified. It is impossible to create another group of tests called Documents, because it is set as general, without specifying a specific application.

Store, Marker 7


To the right of the marker, there is a column that defines, in the form of an icon, the status of scripts in the test repository.
The scenario editing strategy in Tester is organized according to the principle of working with the standard 1C storage. In order to start editing the script, you need to capture it (right click in the tree / Capture). In order for the script to be saved in the test repository, it must be placed there (right click in the tree / Place). At the time of placing the test in the repository (or creating a new test), its version is created. While the script is captured for editing, the rest of the test participants may use the captured script, but they cannot change it. When using a captured script, programmers will receive from the Tester the latest version of the script, rather than the current one, which is currently being edited.
For example, if you captured and edited the Debt Provider method script and another programmer launched the Start script, which in turn from the code will cause the Debt Provider method you blocked, Tester will give this programmer the latest version of the Debt Provider test that was in storage before you started editing it. Thus, your current script changes will not affect the work of other developers.
When placing changes in the repository, your changes are available to all users. If you are developing a specific functionality, and your test changes may affect the performance of other related tests, it is recommended to use the MyVersion () method.

Running tests


Any test from the test tree can be run for execution, regardless of its type. However, as mentioned above, it is assumed that only tests with the Script type should be run, and method scripts should be called from the script code.
The main way to run tests is the F5 button or the Run command:

When you run a test using the F5 button (or the Run command), the tester always runs the script set as the main one . Thus, regardless of whom, what script you are currently editing, only the main one will be launched.
This approach allows you to edit a group of interrelated tests, and quickly run the entire script for execution, without unnecessary switching tabs. In addition to running the main script, it is possible to run the current script. For a complete set of features, see the Tester context menus.

Fields tab


In the process of writing a script, it may be necessary to analyze the internal structure of the windows of the application under test.
Such an analysis is needed to isolate field identifiers and accurately refer to them from the test code. Also, such an analysis can be the only way to understand the composition of the fields of the tested form in cases where the fields are formed dynamically.
For such a task, there is a Fields tab on the script form (for new scripts, the tab is hidden, the script must exist):

In the order of the markers:
  1. Allows you to get the structure of all the windows of the application being tested, which are now open on the screen.
  2. Allows you to get only the current window of the application under test.
  3. It allows you to quickly find in the element tree the current active element of the application under test. Very handy feature when writing tests. For example, you can open the desired form and stand on the desired element, then, in Tester, get this form (p.2) and click Sync. After that, Tester will try to find and activate a string in the tree with this element. In case of failure, an error is generated.
  4. When navigating the tree, Tester tries to activate the selected items in the application under test. Be careful, the focus may “jump” from the tree to the application under test.
  5. For the selected field, you can run a method or get a property. The set of methods and properties depends on the type of the selected element and is applied according to the object model of the tested application of the 1C platform. For example, in the picture, the Selection State field is of the Type Tested Field. In the 1C helper syntax, you can see which methods and properties are available to objects of this type. One of them, the Text Header property, the result of which is displayed in the picture above.

Before implementation


Despite the ease of use of the Tester, the introduction of testing requires some effort. In practice, on average, you need from a week to two in order to adapt to the development with Tester.
Before diving into details, let's decide on when it is ineffective to use automated testing:
  1. You create a mockup, a prototype of an application for demonstration to the customer.
  2. You make point corrections to the old code, to those mechanisms, to which there are no scripts and there will not be, and all this work without the prospects of module evolution.
  3. You feel the future implementation, when there is no clear understanding yet that this should be, a document or reference book, a report or a dynamic list. In this case, the programmer often switches to the “flow” mode and quickly throws in metadata objects in order to prove or disprove to himself the attainability of the result in the chosen way. In such situations, it is almost impossible to develop a scenario, but this is not necessary. Strictly speaking, until a complete understanding of the way the task is performed, scenario testing should not be used.

The implementation process needs to begin smoothly. Initially, this can be a single programmer or analyst and a small project, then, when someone already owns this technique in a team, and can quickly answer questions, you can gradually extend the scope of Tester.

Installation


If you are engaged in customer service privately, Tester makes sense to install the file option locally on your computer or laptop. If you work in a team, regardless of whether all programmers are working on one project or each has its own, it is advisable to install the Tester in a local network or cloud. If your team is more than 3 programmers, I would recommend installing the client-server version of the platform.
Even if your team is highly distributed, with ping up to ~ 125ms you can still work comfortably via the Internet, Tester development was carried out taking into account the distance of programmers. If for some reason, the cloud solution cannot be organized, you can install the program locally on each specialist computer, the file option. To organize a common test repository, you can use Git. The tester has the ability to incrementally upload / download tests to the file system.

In addition, to organize nightly testing, you will need to install a 1C: Enterprise thin client on a dedicated server or virtual machine, with the possibility of connecting it to the cloud where the tests are being developed. In the case of using Git to store tests, you will need to ensure that tests are first uploaded to the testing server, using the utilities from Git. In more detail, night testing is described in the section Running Tests on a Schedule .
The tester allows you to work with tests for an unlimited number of applications (configurations) in one database. You should not create a separate database with Tester for each project / configuration / client. In Tester, it is possible to configure user access restrictions to applications.

Database


Testing with the help of Tester assumes the presence of two databases: working and initial.

The working base is the database in which the programmer works and in which all tests are performed. Accordingly, each programmer has his own working base.

The initial base is a base filled with initial data. The initial base is needed in order to periodically create / overload working bases. The fullness of the initial database depends on the type of work performed. The initial base is common to all programmers.

Creating and updating the initial database


If you are developing a typical configuration, you can take the initial base as the basis for the initial base, which you will ship with your configuration. In this database (prepared for testing, but not deliveries in a solution), it is recommended to include all functional options, add several users with different roles, fill in standard reference information, create at least one organization, warehouse, division and another, depending on specifics of your decision.

If you are finalizing a typical configuration, the initial base may be the customer base, or the sample solution base of the standard solution, updated and customized by the specifics of your customer.

In addition to the very existence of initial data, I recommend developing and maintaining a test that will check the initial database for data consistency.For example, you need a certain exchange rate to run the tests, or a five-day work schedule, or the business processes addressing register should be filled with typical roles and executors, etc. With the growth of the functionality of your system, and possible, in this regard, the expansion of the initial data - the finalization of the initial database verification test will always guarantee an understanding of the basic conditions.

It is convenient to use such a test in the following cases:
: , . , - .
The initial database needs to be connected to the repository where the final configuration updates merge. This is necessary to update the initial database with new functionality, update and / or fill the database with new initial data.

If a team is working on a solution, it’s necessary to place the initial base in a publicly accessible place so that each specialist can “reset” his work base at any time by loading the initial one into it.

If the new functionality requires updating / adding initial data, this task can be solved in two ways:
  1. Responsible developer, opens the updated initial database, manually completes the necessary data, completes the initial data verification test, runs this test, makes sure the data is consistent, and uploads the resulting database to a publicly accessible place
  2. .1 , , , .

The second option is longer, but preferable, because it will allow all team members to update their working bases without resetting them by initial data unloading.

Initial data is desirable to use in the “read only" mode with respect to the tested functionality. For example, if you define the default organization in the initial data, and you have a test that checks the mechanism for entering a new / modifying / deleting organization, then this is better. test, do not use the existing organization in the initial database as a test organization. Even if your test provides for rollback of changes to the initial state, there is no guarantee at what stage your test will fall. When this happens, it will leave After the initial data itself damaged, which can result in a chain reaction test fall performed night schedule.

If your tests need to change the initial data, then at the beginning of such tests, check and, if necessary, set their initial state. After working out the script, return these settings to their original position. If such a test falls, then another test, depending on the same settings, will restore the initial values ​​to their original state before their start.

For example, if your test checks the operation of the residue control mechanism depending on the system settings of the application, your test will have to change this setting. If your test fails, the setting will not be returned to its original position and the next launch of this test is unlikely to work correctly, even if from a functional point of view everything is in order. Thus, at first it is advisable to go to the settings in the test, set the required value and then continue the main scenario. By the way, such checks are not always required in operational work, so it makes sense to start them by condition, for example, by the user name of the night tester, or by the global settings flag (see Tester API ).

Reference base


The reference database is used to test the business logic of the application.
Using the reference base when integrating testing into the development process is not efficient and is not used by the Tester for the following reasons:
  1. Requires special care for the reference data, their adjustment in accordance with changes in the functionality of the solution
  2. Reference data is inert: new functionality requires new reference data that may intersect with existing reference data. The resulting caution when manipulating reference data limits or slows down the development of the spectrum of the tested functional.
  3. The quick run of tests is almost impossible; it is a long time to upload / update / load reference databases. Efficiency refers to testing each time the programmer starts the application for execution, rather than increasing the number of releases and downloading the schema on the CI server with a test run during the day.
  4. The number of reference databases tends to grow, which complicates their maintenance and the entire testing process.

Instead of storing reference data in the reference database, the business logic to be checked should be stored in the Tester itself. From the point of view of Tester, the verification of business logic is a combination of the program code of the script, in which the values ​​of the tested fields are checked, and the resulting reporting according to the information system data. Learn more about testing business logic here .

Data for testing


Test data is input to the scripts information required to successfully pass them. If your test opens the form of the product reference list and installs a filter for the manufacturer, your test data will at least be: an entry in the manufacturer's reference book, an entry in the product reference guide, with the factory requisite filled. In this case, the test data will be the user, under which the information base was launched, the unit of measurement for the product, and other entities.

The test data consists of two layers:
  1. Initial data that is stored in the initial database and provide a minimum set of typical, rarely modified information
  2. Created data that is needed to test specific functionality

Of greatest interest is the second layer. There are many approaches to creating test data, but in their totality two strategies can be distinguished:
  1. Uploading harvested data from pre-prepared bases or templates, and their subsequent loading before or during testing. There are many options for upload / download in this approach. It can be data conversion, universal data exchange, layouts with data, uploading to dt-files or the usual serialization of application objects in JSON or XML.
    Consider the pros and cons of this approach:
    prosMinuses
    Evidence of the approach, , , , .
    . , . , , .
    , , .
    . .
    .
  2. . , , . . , , , .
    :
    prosMinuses
    . .
    . , , , .
    , - . : . “”, . , , ( ).
    -
    , , , — .
    . , ( ) -, .
    . - , .
    , . , - / (. () )
Tester professes the second strategy in the preparation of test data. From the point of view of Tester, the formation of test data should not be in isolation from target testing, test data should be mobile, and they should not be prepared separately from the test development system.

Script structure


Before writing tests, you need to think and identify scenarios that will fit your short-term planning. It is important not to be distracted at this moment and not to mentally throw in possible deviations. For each deviation, it will then be possible to prioritize and develop a separate test. Even if you are able to present a large script, it is recommended to divide it into several small and interrelated tests.

For successful implementation of testing, it is very important that the speed of creating and running tests was high. To quickly create tests, we need two components: training of thinking, for quick selection of a script template for a task and a library of ready-made test methods for creating everything needed during the testing. These things come with time.

To quickly run tests, they need to be of the following structure:
  1. Environment definition
  2. Creating the environment
  3. Target part

An environment definition is a function in your script module that sets test parameters as a structure. Examples of test parameters: list of goods received, with prices and quantities, supplier name, contract currency, etc.

Creating an environment is a procedure in the test module that, using the parameters passed, will create the environment necessary for the test. In the same procedure, there should be a check of the environment already created before, so that it will not be created when the script is run again.

The target part is the actual code that will check what you have planned to do and nothing more.

The test run speed is achieved by performing only the target part by the test, that is, in fact, the one that is executed manually each time the application is started after the programmer modifies. Of course, the creation of the environment will also take some time, and at least once, the test should execute this part of the script, but this is exactly what the programmer would have done manually. Technically, manually creating an environment can be faster, but only for a short period of the application’s life.

Clearer by example. Let's imagine that you are working on the finalization of the Write-off Inventory document, which must be supplemented with special movements on registers. For testing (no matter how manually or not) you will need material in stock, the cost of which you know, the established accounting policy parameters you rely on, and other system settings, for example, the option of controlling balances. Thus, you will need to manually check at least once that the system settings are in order. Then, you will need to create several materials, perhaps a separate warehouse and at least one receipt of inventories, and you will not forget to make the date of receipt the day before. Thus, you define and create the environment, then to perform the target part — to write off and check that the special movements have appeared and they are correct.In other words, all three structural actions described above are performed to develop an automated script.

Such a simple approach does not simply shift the manual actions to the code, it allows you to make significant progress in the development of new features, and testing deviations.

Example.Add to the described task the need to check the error message when writing off the amount of material that is larger than what is in stock. I won’t be mistaken if I predict the work of the programmer’s ingenuity: he will simply open the write-off already done (after adding it to the favorites for maximum “speed”), cancel it, enter 999999 in the quantity column, write the document, and then conduct it and analyze error message. If there is no message, the programmer will return to the code, make the necessary improvements and will repeat the iteration until the error message appears.

And here the problems begin.First of all, it’s not so easy to check the normal behavior of a write-off. It will be necessary to put the data in order, remove 999999 and return the amount that was at the time when we checked the correctness of the modified movements. And we are unlikely to be able to quickly recall exactly how the original number was. Secondly, even if the programmer first copies the document before changing the data, he will then be able to check the maximum for the absence of errors, but he will not be able to check the calculated figures, the result of the changes.

In other words, we have a classic picture: the subsequent refinement of the mechanism is potentially dangerous for the previous functional. And in the absence of the possibility of quickly restoring the environment of the test and its operational run (and not at night), the potential danger will sooner or later turn into a kinetic, real error.
It's not just when we find a problem, now, after a night test, or testing by testers, but when we are deep in the code, it is often necessary here and now to check the mechanisms to determine the chosen direction, to understand that stackable functionality does not conflict and does not distort other algorithms.
I would like to note that even if the programmer’s tests pass, they may contain methodological errors or errors in understanding the task. Such errors can catch a separate department, special testers or eventually the customer. But this does not mean that the whole story of testing programmers does not make sense. On the contrary, on the basis of ready-made tests, it will be enough for a programmer to correct the target part (the third part of the scenario), and the system will perform all other work on preparing the data and verifying them.

Practice


Let us turn to the practical part: let's work with Tester in the mode of creating a new functional for the configuration of the UT11 based on the formulation of the problem from the business analyst.

Formulation of the problem


The company sells cigars. It is necessary to finalize the document Sales of goods and services (hereinafter referred to as Sales) in order to be able to indicate the date of approval of the next sales for the selected items.
The following scenario is assumed:
- The manager enters the implementation document, for the selected items, at his discretion, he sets the date when he would need to call the customer back and clarify how well the cigars are sold. For example, from the entire list, he is interested only in menthol-flavored cigars.
- The manager has a list that he opens every day and sees when, for which clients and which positions he needs to negotiate with the client for the organization of the following deliveries of his positions of interest.
- The manager selects the desired position from the list, calls the client, and enters the result of negotiations into the system.

Document Implementation

It is necessary to add a field to the Implementation document, in the table part, to enter the approval date (without time).
The field is not required. If the field is set, then this position is considered marked for approval. For such positions, it is necessary to provide separate accounting on the basis of the register of information Negotiation. Entries in this register to produce when carrying out the document. When you re-run the document, the existing information register entries do not update, just add new ones.

Register of Information Approval

This is a new, independent register of information, with the possibility of editing.
The register must store the following data:
  1. , , , , , –
  2. –
  3. – . = .

For the register it is necessary to develop a list form and element form In the form of the list should be provided for the selection of the manager, client and product.
Forbid the user to enter new entries in this register online. Note: the prohibition on entering a new one is done programmatically with the output of a corresponding message. Do not use customization of user commands and roles instead.
The object is located in the Sales / Wholesale sales subsystem.

Tests

It is necessary to develop the following test:
  1. Entering one implementation with two positions, one of which will be marked for approval
  2. Opening the list for approval, selection by client, opening the register form for editing, setting a tick, saving and closing
  3. Make sure the position is out of the list.

Note: this test is required by the author of the technical specification. The contractor (programmer) is free to develop as many additional tests as he needs to ensure the proper quality of work.

Development


For this task, we can estimate the course of development and the tests that we need. We will agree that we already have the initial base, we have made the necessary settings in it, prompting windows, checking counterparties and so on are disabled (see the initial base here ). In my case, the initial base will be the UT11 demo base.

We can distinguish at least four steps:

Step 1: Add props Date of agreement in the tabular part in the procedure ObrabotkaProverkiZapolneniya implement checks to date harmonization has been greater than the date of the document

Step 2: modify the procedure ObrabotkaProvedeniya, add back on the register logic form records information

Step 3: Implement list form with filters as required by business analyst

Step 4: implement a register entry edit form for entering data on agreed positions.

Stage 1


In the table below we will do the work on coding and testing:
ProgrammingTesting
In the Configurator:
  1. Add the properties of the DateAccordance to the tabular part Goods of the document Implementation
  2. In the procedure ProcessingPerformFilling, we implement date validation.
In Tester:
We will create a TestDataTo Matching test, where:
  1. We introduce a new implementation, add a line, enter an incorrect date in the line
  2. We will try to conduct, and in the list of messages we find the required error message.
  3. Then we change the date to the correct one, check it out and make sure that the error message is gone.
Since this will be our first test for the configuration of the UT11, we need to make a one-time application setup in the Tester.
You need to create an application UT11, see the Feature menu / Applications. For the application being created, you need to set the current version at the time of writing the test, for example:

Then, you need to install this application as default application, switch to the script tree, open Options, select UT11 in the Application field and click the button on the right:

The next step is creating a folder ImplementingGoodsServices inside the Documents folder, and then creating our test CheckDataToordination.
In the end, it should turn out like this:

Open the script highlighted in the picture, switch to the text editor and enter this text:
 // : // -     // -    ,    // -   ,     ();  (); //     ( "e1cib/data/Document." );  ( " *" ); //    =  (  ( "!" ) );  =  (  - 86400, "DLF=D" );  =  (  + 86400, "DLF=D" ); //     ( "!" );  ( "!",  ); //    ( "!" );  (  ( " *" ). () = 0 )   ( "      " ); ; //     =  ( "!" );  ( "! [1]", ,  ); //    ( "!" );  (  ( " *" ). () > 0 )   ( "       " ); ; //      ();  ( "", "1*" ); 

Comments on the code:
  1. , . , , ,
  2. , , . , , , - , . , , , . , - , , , - ()
  3. In this test, there is no all three-step structure that I described earlier (see here ), but here it is not necessary because of the simplicity of the script and, as a result, the speed of its run.

It's time to launch the script. To do this, make sure that the application is configured in the configurator in the test client mode:

(this setting is saved and you don’t have to install it every time)
Start the application, then switch to Tester, set our script as basic and click the Start button:

If at the time you start the test have not yet implemented the procedure for checking the date of approval, our test will fall.
We now implement in the implementation module, in the Handler ProcessingPerform Fill, the following check:
  =  ( 1, 1, 1 );        = .;  (  =  )  ;  (  <  )   ( "   " );  = ; ; ; 

We launch applications for execution, switch to Tester and click F5 there. As a result, the test should complete without errors.

Stage 2


We turn to the second planned jerk. In the table below we will do the work on coding and testing:
ProgrammingTesting
In the Configurator:
  1. Add register information Negotiate
  2. We finalize the processing of carrying out for the formation of entries in the register
In Tester:
Let's create a test for sale with a match agreement, where:
  1. Define the environment:
    1. Supplier name
    2. Buyer Name
    3. Product1 with price and quantity
    4. Product2 with price, quantity and date of approval
  2. Create an environment
    1. Create a supplier, buyer and goods
    2. Make a receipt
    3. Create and implement
  3. Target part
    1. Open the list of implementations and find the created implementation there.
    2. Open the implementation and run
    3. Open the register of approvals and check our record
This test is more difficult, because before checking the target part, we need to create an environment. Let me remind you that the environment will be created only once, when you first run the script, and then only its target part will be run. This trick will be clear from the script code that will be developed at the end of this stage.

To create the environment, we will need the following objects:
  1. Provider
  2. Product
  3. Stock
  4. Customer
  5. Arrival

In real projects, creating an environment is a simple operation, but we do everything from scratch, we still do not have library tests, so before writing the environment logic, we need test methods for creating objects (see test methods here ).

Method to create a supplier


Almost all test methods have the same structure: they are created in a group of tests corresponding to the applied model of 1C objects. This is not a hard and fast rule. In your projects you can create test methods in your own way, but the proposed approach has already proven itself.
Create the first test method. In the script tree, in the References folder, we will create the Suppliers folder, the Create method inside it, and the Parameters method next, so that we get the following structure:

As a result, we have the Create method and the Parameters method subordinate to it. In order to use this method in any scenario, we only need to write the following code:
 //   -     =  ( "..." ); //   . = " "; //        ( "..",  ); 

Help on all Tester functions is available in the Tester API section .
To create scripts-methods, in the form of a script element, on the Properties tab, you need to assign the appropriate type:

For more information about the tree and properties of the scripts, see here .
Let's go to the Parameters script code editor, enter the following text:
 //     // // : //    = ;  =   (); . ( "" ); . ( "", "" );  ; 

Then, open the script editor Directories. Suppliers. Create and enter:
 //       // // : //  ,   "..." // // : //     ( "e1cib/data/." );  =  ( " (*" ); // ********************************************* //   // *********************************************  ( "!", _. );  ( "" );  ( "!", _. ); // ********************************************* // ,   // *********************************************  ( "!" );  =  ( "!" ); // ********************************************* //   // *********************************************  ( "",  () );  =  ( "*" );  ( "!" );  ( " (*" );  ( "!", _. );  ( "!" );  (  );  ; 

The parameterized method of creating a new supplier is ready. We proceed to the creation of the remaining methods.

Method to create a buyer


Let's do the same actions in the scenario tree for developing a customer creation scenario:

Then we enter the script code, Directories. Buyers. Create . Parameters:
 //     // // : //    = ;  =   (); . ( "" ); . ( "", "" ); . ( "", " " );  ; 

and Directories. Buyers. Create:
 //       // // : //  ,   "..." // // : //     ( "e1cib/data/." );  =  ( " (*" ); // ********************************************* //   // *********************************************  ( "!", _. );  ( "!" );  ( "!", _. ); // ********************************************* // ,   // *********************************************  ( "!" );  =  ( "!" ); // ********************************************* //   // *********************************************  ( "",  () );  =  ( "*" );  ( "!" );  ( " (*" );  ( "!", _. );  ( "!" );  (  );  ; 

Method to create products



Directories. Nomenclature. Create. Parameters
 //     // // : //    =   (); . ( "" ); . ( "", "" ); . ( "", "" ); . ( "", "18%" );  ; 

Directories. Nomenclature. Create
 //       // // : //  ,   "..." // // : //     ( "e1cib/data/." );  =  ( " (*" ); // ********************************************* //   // ********************************************* // ( , _. );  ( "!", _. );  ( " ", _. );  ( " ", _. );  ( " ", _. ); // ********************************************* // ,     // *********************************************  ( "!" );  =  ( "!" );  ();  ; 

Method to create warehouses



Directories. Warehouses. Create. Parameters
 //     // // : //    =   (); . ( "" );  ; 

Directories. Warehouses. Create
 //       // // : //  ,   "..."  ( "e1cib/data/." );  =  ( "* (*" ); // ********************************************* //   // *********************************************  ( "!", _. );  ( "!", " " ); // ********************************************* // ,     // *********************************************  ( "!" ); 

Method to create a document Goods Receipt Services



Documents. Receipt of the GoodsServices.Create.Parameters
 //     // // : //    = ;  =   (); . ( "" ); . ( "", __. ); . ( "" ); . ( "" ); . ( "",   ); //  ... . ( "",  ); //         ; 

Documents. ReceiptGoodsServices.Create.Goods
 //      // // : //    = ;  =   (); . ( "" ); //     . ( "" ); . ( "" );  ; 

Documents. Receipt of the Goods Services. Create
 //           // // : //  ,   "..." // // : //     ( "e1cib/data/." );  =  ( "    (*" ); // ********************************************* //   // *********************************************  = _.;  (  <>  )   ( "!",  ( , "DLF=DT" ) ); ;  ( "!", _. );  ( "!", _. );  = _.;  (  <>  )   ( "!",  ); ; // ********************************************* //   // *********************************************  =  ( "!" );     _.   ( "!",  );  ( "!", . );  ( "!", . );  ( "!", . ); ; // ********************************************* //  ,   // *********************************************  ( "!" );  =  ( "!" ); // ********************************************* //      // *********************************************  ( "!" );  =  _.;  (  )   (); ;  ; 

Method for creating a document ImplementingGoodsServices



Documents. Realization of Goods Services. Create. Parameters
 //     // // : //    = ;  =   (); . ( "" ); . ( "", __. ); . ( "" ); . ( "" ); . ( "",   ); //  ... . ( "",  ); //        . ( "" );  ; 

Documents. Realization of the Goods Services. Create. The Goods
 //      // // : //    = ;  =   (); . ( "" ); //     . ( "" ); . ( "" ); . ( "" );  ; 

Documents. Sales of Goods Services. Create
 //           // // : //  ,   "..." // // : //     ( "e1cib/data/." );  =  ( "    (*" ); // ********************************************* //   // *********************************************  = _.;  (  <>  )   ( "!",  ( , "DLF=DT" ) ); ;  ( "!", _. );  ( "!", _. );  = _.;  (  <>  )   ( "!",  ); ;  = _.;  (  <>  )   ( "!",  ); ; // ********************************************* //   // *********************************************  =  ( "!" );  =  ( 1, 1, 1 );     _.   ( "!",  );  ( "!", . );  ( "!", . );  ( "!" );  ( "!", . );  = .;  (  <>  )   ( "!",  ( , "DLF=D" ) ); ; ; // ********************************************* //  ,   // *********************************************  ( "!" );  =  ( "!" ); // ********************************************* //      // *********************************************  ( "!" );  =  _.;  (  )   (); ;  ; 

At this, the preparation of methods is complete.

Creating a Test for Sale with Approval


We proceed to writing the final test for the second stage. To do this, in the script tree, create the following test:

Let's make it basic, and enter the following code:
 // : // -         //    ,       // -    // -     ()  // -       ,      // -      ( "." );  ();  = "25C555B6";  =  (  );  (  ); // ************************************ //   // ************************************ //    ( "e1cib/list/." );  ( " " ); //      ( "!", "", . ); //   ( "!" ); //     ( "e1cib/list/." );  ( "" ); //     =  ( "!", "", . );  (   )   ( "        " ); ; //    . //     ( "!" );  ( " " ); //   " "  =  ( "!OnlySelectedElement" );  (  = "" )   ( "!OnlySelectedElement" ); ; // ,        ( "!DocumentTypeElement", " " ); //  -  ( "!Ok" ); //       ( "" );  ( "" ); // ********************************************* //  // *********************************************   (  )  =  ();  =   (); . ( "",  ); . ( "",  ); . ( "",  () + 172800 ); //    . ( "",  - 86400 ); . ( "", " " +  ); . ( "", " " +  ); . ( "", " " +  ); . ( "",  (  ) );  ;    (  )  = .;  =   (); . (  ( "1 " + , 5, 150, 250 ) ); . (  ( "2 " + , 15, 250, 350, . ) );  ;    ( , , , ,  =  )  =   (); . ( "",  ); . ( "",  ); . ( "",  ); . ( "",  ); . ( "",  );  ;    (  )  = .; // ***************************************************** // ,       // *****************************************************  (  ( ".",  ) )  ; ; // ****************************************************************** // ,         // ******************************************************************  ( "e1cib/command/..." );  ( "" );  =  ( "!" );  (  <> " " )   ( "  ,         . | ,       ,   |        ,   " ); ; // ****************** //   // ******************  =  ( "..." ); . = .;  ( "..",  ); // ****************** //   // ******************  =  ( "..." ); . = .;  ( "..",  ); // ****************** //   // ******************  =  ( "..." ); . = .;  ( "..",  ); // ************** //   // **************     .   =  ( "..." ); . = .;  ( "..",  ); ; // ******************* //   // *******************  =   ();     .   =  ( "..." ); . = .; . = .; . = .; . (  ); ;  =  ( "..." ); . = ; . = .; . = .; . = .;  ( "..",  ); // ******************* //   // *******************  =   ();     .   =  ( "..." ); . = .; . = .; . = .; . = .; . (  ); ;  =  ( "..." ); . = ; . = .; . = .; . = .;  ( "..",  ); // ******************************** //    // ********************************  ( ".",  );  

Since this is our main scenario for the second stage, let's take a closer look at it.
The script begins with Invoke ("General. Start") ;. I make this call to set global variables and perform common tasks before starting any test. Let's see what's inside the General test. Start:

 //         //      ,       //    = ;  ( __ =  )  __ =   ();  ; ; // ************************************************************************* //   "__"      // ************************************************************************* __. ( "",  ); __. ( "", "" );  (  = "11" )  __. ( "", "  """"" ); ; // *********************************************** //      // ***********************************************  (); 

If you are using the Tester demo base, then the General test. The beginning is already there. Open this test and make changes to it, in particular, we need this part of the module:
  (  = "11" )  __. ( "", "  """"" ); ; 

It all works as follows. When the SaleAccordingTo Match test is started, it in turn will launch the General test. A start that will define several variables and connect to the application under test. All tests that will be run next will already know that the variable “__” stores the name of the organization, the local currency and other parameters. This is a kind of global parameterization of the test environment (the use of double underscore as a global variable is chosen for independence from the 1C language variant).

Then, the test closes all windows in the application under test. This is necessary in order not to accidentally activate those forms that are used in the process of the test, but are in an inconsistent state.

The next three lines define and create the environment (seeScript structure ):
 //  ""   . //     ,     //    - , //         //   : Ctrl+Shit+I //  ,   ,     "". //    -   .  = "25C555B6"; //   ""   ()     //  .      .  =  (  ); //   ()     . //      -,      .  (  ); 

Let's see what happens inside the environment () function:
   (  )  =  ();  =   (); . ( "",  ); . ( "",  ); . ( "",  () + 172800 ); //    . ( "",  - 86400 ); . ( "", " " +  ); . ( "", " " +  ); . ( "", " " +  ); . ( "",  (  ) );  ;  

Nothing unusual, a structure is being prepared with parameters, but the conceptual one is the use of the input parameter ID.

Test data is created, which means they must be unique. Otherwise, duplicate objects will be created, which in practice will be impossible to use. Indeed, if we create “Romashka LLP” every time, which then “Romashka LLP” to choose when creating a document? Thus, the lines of the code “Supplier” + ID, “Buyer” + ID and others guarantee the creation of unique test data. It also allows you to perform your tests with other participants in the development, without synchronizing the prepared templates, using pre-populated databases and other external files.

Probably, this approach is puzzling, because the base eventually turns into a mess of nothing insignificant identifiers. But in practice, any developer database turns into scraps of experiments from “torn” data; this is only a matter of time. If you are in the working bases carefully store some information on which your development relies - transfer this data to the initial base. If the bases contain errors for reproduction - write tests that reproduce these errors. In other words, if you have something valuable from an application point of view in your workbench, write a script. This will free you from the content of the farm from the information databases, will enable other developers to check your options in their databases at any stage of development. It’s better to translate all useful data-centered experience into script code,so that it can always be repeated.

Another seemingly disturbing moment is the depth of the uniqueness of the test data and its volume. And here it should be noted that not all test data must be made unique. Uniqueness requires only what you need for testing (including verification of business logic). For example, for our test we need the uniqueness of the names of the supplier, buyer, warehouse and goods. We do not require the uniqueness of units of measurement, contracts, agreements, groups of goods and other related data. Growth data will also not be a problem. Even if you run an environment test every 5 minutes (which is highly unlikely), then there will be no more than 100 such launches during the day, which is negligible for the daily base growth. In practice, the need to reset the working database by loading the initial database into it occurs about once every six months. Agree that programmers,Testing everything manually, with about the same periodicity, disable their working bases.

The next section of code, the procedure to create the Environment (). Inside this procedure, the creation of test data. Creating an environment is not a quick process, but it is also not mandatory for each script launch in the process of programming a task. To ensure that the environment is not created every time, you can use two approaches.

The first is to comment on the procedure call createEnvironment () after it was once created. However, over time, it begins to tire.

The second - at the beginning of the procedure, check whether the environment has already been created, and if not, at the end of the procedure, record the fact of its creation:
   (  )  = .; // ***************************************************** // ,       // *****************************************************  (  ( ".",  ) )  ; ; //...  ... // ******************************** //    // ********************************  ( ".",  );  

To store the identifier of the created environment, you can use a “simple” configuration object, where you can easily put and retrieve values. This is what happens in the library script General. Environment. Created:
 // : //         // // : // ,   // // : // ,  -   ,  -      ( "e1cib/list/." );  ( "" );   =  ( "!", "", _ );   = ; ;  ();  ; 

Thus, the Notes directory is used as an object for storing the environment.

Note 1: The transition to the line is made through an attempt, because in the platform versions <= 8.3.9 there is an error in the work of the method of transition to the line. In the absence of the required string, the platform erroneously generates an exception instead of returning a boolean value.

Note 2: This approach to storing the environment identifier is not aesthetic, a more elegant solution suggests itself, for example, the storage of the ID inside the Tester itself. Unfortunately, not all the described solutions came at once, it was a long way from trial and error, which continues to this day. The concept of working with identifiers has proven its suitability, and I will definitely consider the implementation of this functionality at the Tester configuration level in the foreseeable future.

The rest and the main part of the procedure to create the Environment () contains a routine for filling parameters and invoking script-methods. Despite the simplicity of the object creation logic, it may be necessary to run the environment creation code repeatedly during its development. In this case, it may not be effective to run the full test cycle. One of the frequently used tricks is to temporarily take away the code at the beginning of the main script, with the operator inserting a return; before the main test, like this:
  (); //  -...  =  ( "..." ); . = " ";  ( "..",  ); ; //  ,        () // : // -         //    ,       // -    // -     ()  // -       ,      // -      ( "." );  (); //.... 

Thus, piece by piece logic can be debugged and transferred to the procedure to create the Environment (). Please note that to recreate the whole environment, you just need to change the ID at the beginning of the test.

I described the definition and creation of the environment, we now turn to the target part of the Sale scenario with the Matching Agreement:
 //    ( "e1cib/list/." );  ( " " ); //      ( "!", "", . ); //   ( "!" ); //     ( "e1cib/list/." );  ( "" ); //     =  ( "!", "", . );  (   )   ( "        " ); ; //    . //     ( "!" );  ( " " ); //   " "  =  ( "!OnlySelectedElement" );  (  = "" )   ( "!OnlySelectedElement" ); ; // ,        ( "!DocumentTypeElement", " " ); //  -  ( "!Ok" ); //       ( "" );  ( "" ); 

The sequence of steps is quite obvious; a part of the verification code of the generated motions attracts interest. To do this, use the standard platform function to output any tabular field in a tabular document:
  ( "!" );  ( " " ); //  ... 

and Tester's ability to compare a tabular document with the layout stored in the script:
  ( "" );  ( "" ); 


The picture combines the test application for clarity (located above) and the Tester (located below). As you understand, I ran a little ahead, the template stored in Tester was previously copied from the application under test, at the time the program code was ready to form these movements, but we had not yet done programming the second jerk. This is a necessary measure, I had to logically complete the description of the three-structured approach to the organization of scenarios.

If we now run the script for execution, it will fall at the stage of creating the environment, because we have, in addition to the logic of carrying out, there is still no props for Date Coordination in the tabular part of the Goods Document of the Realization of Goods Services.

Let's do the programming:
- Add the necessary requisite : - Let's


output to the form:



- In the Processing Procedure of the object module, add the code:
  (, )  = " | ..  , ..  , | .  , .  , .  , | .  , .  , &   | ..   | // | //  | // |   .   |  . = . | . = & | . <>  ( 1, 1, 1 ) |  isnull ( .,  ) |";  =   (  ); . ( "",  );  = . (). ();        = .. ();  ( ,  ); . (); ; //...     

Note: To stay in the wake of the presentation, I omit some implementation details. For example, you probably noticed the lack of working out the situation of deleting a row from a table part, which was previously subject to approval.
Run the application, run the test. After completing the test, you should have this:

Highlight this layout in UT11 and copy it to the Tester on the tab Template for the Sale with the Date Approval. Then, in Tester, select the relevant area, right-click on the context menu and select Mark area:

In order for the template not to be checked as it is, we need to parameterize it. To do this, in each cell, which may vary depending on the time and conditions for running the test, in the context menu, we will replace the value with the template:

We will do this with each field so that we end up with the following picture:

Note that the values ​​of the cells Quantity and Amount are left as they are. This is important because, unlike the previous fields, which can vary depending on the environment identifier, this part is fixed in the test condition and should be guaranteed to be such (for a more complete example of checking business logic, see Checking business logic ).
Run the script for execution and make sure that the test passes successfully.
Go to the next scheduled stage.

Stage 3


In this breakthrough, we need to develop a list form for the register Matching with filters by customer, product and manager.
In the table below we will do the work on coding and testing:
ProgrammingTesting
In the Configurator:
  1. ,
:
, :
  1. :
    1. ,
    1. ,
    1. ,
    2. ,
    3. /

, , .


- Add the main form of the list, add the details of the form, place it on the form:


- In the module of the list form, we define filtering field handlers:
 &   (  ) .(, "", , ., , ());  &   (  ) .(, "", , ., , ());  &   (  ) .(, "", , ., , ());  

At this stage with programming everything. Let's proceed to the development of the test. To do this, as in previous times, in the script tree, create a new script. We will install this script as the main one, and call it FilteringList:

Let's enter the following script code:
 // : // -          //   ,      // -    // -    , ,       // -     , ,    // -      ,    , // ,         ( "." );  ();  = "25CB69CB";  =  (  );  (  ); // ************************************ //   // ************************************ //     ( "e1cib/list/." );  ( "" ); //      = .;  ( "!",  ); //      =  ( "!", "",  );  (   )   ( "       " ); ; //       ( "!", . ); //      = 0 =  ( ".",  ( "!" ) );  (   )   ( "   " ); ;  ( "!" ); //        ( "!", . [ 0 ]. );  ( "!" ); //      ( "!" ); // ********************************************* //  // *********************************************   (  )  =  ();  =   (); . ( "",  ); . ( "",  ); . ( "",  + 172800 ); //    . ( "",  - 86400 ); . ( "", " " +  ); . ( "", " " +  ); . ( "", "  " +  ); . ( "", " " +  ); . ( "",  (  ) );  ;    (  )  = .;  =   (); . (  ( "1 " + , 15, 250, 350, . ) );  ;    ( , , , ,  =  )  =   (); . ( "",  ); . ( "",  ); . ( "",  ); . ( "",  ); . ( "",  );  ;    (  )  = .; // ***************************************************** // ,       // *****************************************************  (  ( ".",  ) )  ; ; // ****************** //   // ******************  =  ( "..." ); . = .;  ( "..",  ); // ****************** //   // ******************  =  ( "..." ); . = .;  ( "..",  ); // ******************* //   // *******************  =  ( "..." ); . = .;  ( "..",  ); . = .;  ( "..",  ); // ************** //   // **************     .   =  ( "..." ); . = .;  ( "..",  ); ; // ******************* //   // *******************  =   ();     .   =  ( "..." ); . = .; . = .; . = .; . (  ); ;  =  ( "..." ); . = ; . = .; . = .; . = .;  ( "..",  ); // ******************* //   // *******************  =   ();     .   =  ( "..." ); . = .; . = .; . = .; . = .; . (  ); ;  =  ( "..." ); . = ; . = .; . = .; . = .;  ( "..",  ); // ******************************** //    // ********************************  ( ".",  );  

Comments on the test code:
  1. In fact, this script is a simplified version of the script that we created in the previous step.
  2. In this scenario, I omitted the verification of the agreements with clients, in a real project you will highlight this setting in a separate environmental verification test and will not be included in each of your tests.
  3. ( ".", ( "! " ) ). , .
  4. , 7 .
  5. , - , . , . “?” . , ( ).
  6. .
Run the test, it should pass without errors. This stage is ready, go ahead.


Stage 4


At this stage, we need to develop a form for editing the record for the register Reconciliation. The user needs a form for editing to record the results of negotiations with the customer (the conditions of the problem were described here ).

In the table below we will do the work on coding and testing:
ProgrammingTesting
In the Configurator:
  1. Add a form entry in the register information Negotiate
  2. Form the appearance
  3. We write the logic of the form
In Tester:
Create an Editing Forms Matching test, where:
  1. Define the environment:
    1. Supplier name
    2. Buyer Name
    3. Item with approval date
  2. Create an environment
    1. Create a supplier, buyer and product
    2. Make a receipt
    3. Create and implement
  3. Target part
    1. ,
    2. , , .
    3. ,
    4. , ,
    5. ,
We will do this jerk combined. Start by creating a form layout in the configurator, create a register entry:

Run the application. Switch to the Tester, and in the script tree, create and set as the main test the Editing Forms Matching:

And enter the following code:
 // : // -          //   ,      // -     // -           // - ,       (    ) // -   , ,     . // -     // -      ,     // -   ,     ,     // -       // - ,              ( "." );  ();  = "25CB8B15";  =  (  );  (  ); // ************************************ //   // ************************************ //     ( "e1cib/list/." );  =  ( "" ); //      = .;  ( "!",  ); //      ( "!", "",  ); //    ( "!" );  ( . (). () ); // ,   ,        ( "" =  ( "!" ) )   ( "!" ); //   ; //      ( "!", "",  ); //     ( "!" ); //      ( "!", "" ); //  -    ( "!", " " ); //      ( "!" ); //          (  );  ( "!" );  ( . (). () ); //      ( "!", "" ); //        ( "!" );  ( "!" ); //      ( "!", "" );  ( "!" ); //  ,          (  );  ( "!" ); //        (  ( "* *" ). () = 0 )   ( "   " ); ;  (); // ********************************************* //  // *********************************************   (  )  =  ();  =   (); . ( "",  ); . ( "",  ); . ( "",  + 172800 ); //    . ( "",  - 86400 ); . ( "", " " +  ); . ( "", " " +  ); . ( "", " " +  ); . ( "",  (  ) );  ;    (  )  = .;  =   (); . (  ( "1 " + , 15, 250, 350, . ) );  ;    ( , , , ,  =  )  =   (); . ( "",  ); . ( "",  ); . ( "",  ); . ( "",  ); . ( "",  );  ;    (  )  = .; // ***************************************************** // ,       // *****************************************************  (  ( ".",  ) )  ; ; // ****************** //   // ******************  =  ( "..." ); . = .;  ( "..",  ); // ****************** //   // ******************  =  ( "..." ); . = .;  ( "..",  ); // ******************* //   // *******************  =  ( "..." ); . = .;  ( "..",  ); // ************** //   // **************     .   =  ( "..." ); . = .;  ( "..",  ); ; // ******************* //   // *******************  =   ();     .   =  ( "..." ); . = .; . = .; . = .; . (  ); ;  =  ( "..." ); . = ; . = .; . = .; . = .;  ( "..",  ); // ******************* //   // *******************  =   ();     .   =  ( "..." ); . = .; . = .; . = .; . = .; . (  ); ;  =  ( "..." ); . = ; . = .; . = .; . = .;  ( "..",  ); // ******************************** //    // ********************************  ( ".",  );  

Comments on script code:
  1. This test was created by copying the previous one, the environment was practically not modified, I removed the creation of a potential client.
  2. Such a line of code may be of interest: Here (Application. GetActive Window (). GetObject ()) ;. In this case, an example of working with the application under test through standard platform methods is shown. In the Application variable, the Tester stores the Testable Application object, through which all other platform methods can be called in the testing client mode (for more details, see the Tester API ).

So, we run the test and make sure that it falls, since we have not implemented the logic of the form. Next, we return to the configurator, switch to the record form module, and enter the following code:
 // ***************************************** // ***********   &   (  )  ();  &   (  =  )  (  =    ( , "" ) )  .. = .; ;  &   ( ,  )   ( , "," ). (  ) <> ;  &   ( ,  )  ( .. () )   ();  = ; ;  &   ()  (  ( "ru = '     ,       '" ) );  // ***************************************** // ***********   &   (  )  ();  ( "" );  &   ()  (  . )  . = ""; ;  

Then, we will switch to the form and set the event handlers: Reading On The Server, Creating The Server, Working Out When Changing. Run the application, run the test and make sure that it passes.

Conclusion


We considered the theoretical and practical parts of using the Tester system for organizing the work of a programmer through testing a code-driven client application. Many calculations can be found controversial and even opposite to the teachings of authorities in the field of building testing processes. Not in spite of, but with the knowledge of this, this material was being prepared. The main goal was to show the practical application of the methodology and means of scenario testing.
I admit that in each developed scenario, someone will find a “brute force” in terms of the volume of the functional being tested, and someone will find a “shortfall”. I can only hope that this article has reached a balance between all the annoying simplicity and uninteresting complexity. Not less important task was to show how you can implant automated scenario testing into the development, so that it does not seem to be an appendix or another superstructure above the essence of programming.

Many thanks for not disregarding this work. Successful to you tests, friends!

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


All Articles