Spec-Zone.ru › Django 2.2

Расширенные темы тестирования

Фабрика запросов

class RequestFactory [source]

Фабрика RequestFactory имеет тот же API, что и клиент тестирования. Однако вместо имитации браузера, RequestFactory предоставляет способ генерировать экземпляр запроса, который можно использовать в качестве первого аргумента для любого представления. Это означает, что вы можете протестировать функцию представления так же, как и любую другую функцию — как чёрную коробку с точно известными входными данными, проверяя конкретные выходные данные.

API фабрики RequestFactory — это слегка ограниченный подмножество API клиента тестирования:

  • Он имеет доступ только к HTTP-методам get(), post(), put(), delete(), head(), options() и trace().
  • Эти методы принимают все те же аргументы, кроме follow. Поскольку это всего лишь фабрика для создания запросов, вам нужно самостоятельно обработать ответ.
  • Он не поддерживает middleware. Атрибуты сессии и аутентификации должны быть предоставлены самим тестом, если они необходимы для корректной работы представления.

Пример

Ниже приведен простой юнит-тест с использованием фабрики запросов:

from django.contrib.auth.models import AnonymousUser, User
from django.test import RequestFactory, TestCase

from .views import MyView, my_view

class SimpleTest(TestCase):
    def setUp(self):
        # Every test needs access to the request factory.
        self.factory = RequestFactory()
        self.user = User.objects.create_user(
            username='jacob', email='jacob@…', password='top_secret')

    def test_details(self):
        # Create an instance of a GET request.
        request = self.factory.get('/customer/details')

        # Recall that middleware are not supported. You can simulate a
        # logged-in user by setting request.user manually.
        request.user = self.user

        # Or you can simulate an anonymous user by setting request.user to
        # an AnonymousUser instance.
        request.user = AnonymousUser()

        # Test my_view() as if it were deployed at /customer/details
        response = my_view(request)
        # Use this syntax for class-based views.
        response = MyView.as_view()(request)
        self.assertEqual(response.status_code, 200)

Тестирование и несколько имен хостов

Настройка ALLOWED_HOSTS валидируется при запуске тестов. Это позволяет клиенту тестов различать внутренние и внешние URL-адреса.

Проекты, поддерживающие многопользовательский доступ или иным образом изменяющие бизнес-логику на основе хоста запроса и использующие пользовательские имена хостов в тестах, должны включать эти хосты в ALLOWED_HOSTS.

Первый и самый простой способ сделать это — добавить хосты в файл настроек. Например, набор тестов для docs.djangoproject.com включает следующее:

from django.test import TestCase

class SearchFormTestCase(TestCase):
    def test_empty_get(self):
        response = self.client.get('/en/dev/search/', HTTP_HOST='docs.djangoproject.dev:8000')
        self.assertEqual(response.status_code, 200)

а в файле настроек содержится список доменов, поддерживаемых проектом:

ALLOWED_HOSTS = [
    'www.djangoproject.dev',
    'docs.djangoproject.dev',
    ...
]

Другой вариант — добавить необходимые хосты в ALLOWED_HOSTS с помощью override_settings() или modify_settings(). Этот вариант может быть предпочтительным в автономных приложениях, которые не могут упаковать свой собственный файл настроек, или для проектов, где список доменов не статичен (например, поддомены для многопользовательского доступа). Например, вы могли бы написать тест для домена http://otherserver/ следующим образом:

from django.test import TestCase, override_settings

class MultiDomainTestCase(TestCase):
    @override_settings(ALLOWED_HOSTS=['otherserver'])
    def test_other_domain(self):
        response = self.client.get('http://otherserver/foo/bar/')

Отключение проверки ALLOWED_HOSTS (ALLOWED_HOSTS = ['*']) при выполнении тестов предотвращает вывод полезного сообщения об ошибке от клиента тестов, если вы следуете перенаправлению на внешний URL.

Тестирование и несколько баз данных

Тестирование конфигураций мастер/ведомый

Если вы тестируете конфигурацию с несколькими базами данных с репликацией мастер/ведомый (в некоторых базах данных это называется мастер/раб), эта стратегия создания тестовых баз данных создаёт проблему. Когда создаются тестовые базы данных, репликации не будет, и в результате данные, созданные на главном сервере, не будут видны на ведомом.

Чтобы компенсировать это, Django позволяет определить, что база данных является тестовым зеркалом. Рассмотрим следующий (упрощённый) пример конфигурации базы данных:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject',
        'HOST': 'dbprimary',
         # ... plus some other settings
    },
    'replica': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject',
        'HOST': 'dbreplica',
        'TEST': {
            'MIRROR': 'default',
        },
        # ... plus some other settings
    }
}

В этой настройке у нас есть два сервера баз данных: dbprimary, описанный псевдонимом базы данных default, и dbreplica, описанный псевдонимом replica. Как можно ожидать, dbreplica был настроен администратором базы данных как чтение реплики dbprimary, поэтому в нормальной работе любые записи в default появятся в replica.

Если Django создаст две независимые тестовые базы данных, это нарушит любые тесты, которые ожидают, что репликация произойдёт. Однако база данных replica была настроена как тестовое зеркало (с использованием настройки теста MIRROR), указывая, что в ходе тестирования replica должна рассматриваться как зеркало default.

При настройке тестовой среды тестовая версия replica не будет создана. Вместо этого соединение с replica будет перенаправлено на default. В результате записи в default появятся в replica — но это происходит потому, что это одна и та же база данных, а не потому, что между двумя базами данных происходит репликация данных.

Управление порядком создания тестовых баз данных

По умолчанию Django будет предполагать, что все базы данных зависят от базы данных default и поэтому всегда будет создавать базу данных default первой. Однако никаких гарантий относительно порядка создания других баз данных в вашей тестовой настройке не даётся.

Если ваша конфигурация базы данных требует определённого порядка создания, вы можете указать существующие зависимости с помощью настройки теста DEPENDENCIES. Рассмотрим следующий (упрощённый) пример конфигурации базы данных:

DATABASES = {
    'default': {
        # ... db settings
        'TEST': {
            'DEPENDENCIES': ['diamonds'],
        },
    },
    'diamonds': {
        # ... db settings
        'TEST': {
            'DEPENDENCIES': [],
        },
    },
    'clubs': {
        # ... db settings
        'TEST': {
            'DEPENDENCIES': ['diamonds'],
        },
    },
    'spades': {
        # ... db settings
        'TEST': {
            'DEPENDENCIES': ['diamonds', 'hearts'],
        },
    },
    'hearts': {
        # ... db settings
        'TEST': {
            'DEPENDENCIES': ['diamonds', 'clubs'],
        },
    }
}

В этой конфигурации база данных diamonds будет создана первой, так как это единственный псевдоним базы данных без зависимостей. Псевдонимы default и clubs будут созданы следующими (хотя порядок создания этой пары не гарантируется), затем hearts, и наконец, spades.

Если в определении DEPENDENCIES есть циклические зависимости, будет возбуждено исключение ImproperlyConfigured.

Расширенные возможности TransactionTestCase

TransactionTestCase.available_apps

Предупреждение

Этот атрибут относится к API с ограниченным доступом. Он может быть изменён или удалён без периода устаревания в будущем, например, для адаптации к изменениям в загрузке приложений.

Он используется для оптимизации собственного набора тестов Django, который содержит сотни моделей, но не имеет связей между моделями в различных приложениях.

По умолчанию, available_apps устанавливается в None. После каждого теста Django вызывает flush для сброса состояния базы данных. Это очищает все таблицы и отправляет сигнал post_migrate, который восстанавливает один тип контента и четыре разрешения для каждой модели. Эта операция становится дорогостоящей пропорционально количеству моделей.

Установка available_apps в список приложений указывает Django действовать так, как если бы доступны были только модели из этих приложений. Поведение TransactionTestCase изменяется следующим образом:

  • post_migrate генерируется перед каждым тестом для создания типов контента и разрешений для каждой модели в доступных приложениях, если они отсутствуют.
  • После каждого теста Django очищает только таблицы, соответствующие моделям в доступных приложениях. Однако на уровне базы данных усечение может распространяться на связанные модели в недоступных приложениях. Кроме того, post_migrate не генерируется; он будет сгенерирован следующей TransactionTestCase, после выбора правильного набора приложений.

Поскольку база данных не полностью очищается, если тест создаёт экземпляры моделей, не включённых в available_apps, они будут оставаться и могут привести к тому, что не связанные тесты завершатся ошибкой. Будьте осторожны с тестами, которые используют сессии; по умолчанию движок сессий хранит их в базе данных.

Поскольку post_migrate не генерируется после очистки базы данных, её состояние после TransactionTestCase не такое же, как после TestCase: отсутствуют строки, созданные слушателями post_migrate. Учитывая порядок выполнения тестов, это не проблема, если все TransactionTestCase в данном наборе тестов объявляют available_apps или ни один из них этого не делает.

available_apps является обязательным для собственного набора тестов Django.

TransactionTestCase.reset_sequences

Установка reset_sequences = True в TransactionTestCase обеспечит, что последовательности всегда будут сброшены перед запуском теста:

class TestsThatDependsOnPrimaryKeySequences(TransactionTestCase):
    reset_sequences = True

    def test_animal_pk(self):
        lion = Animal.objects.create(name="lion", sound="roar")
        # lion.pk is guaranteed to always be 1
        self.assertEqual(lion.pk, 1)

Если вы не тестируете явно номера последовательности первичных ключей, рекомендуется не жестко кодировать значения первичных ключей в тестах.

Использование reset_sequences = True замедлит тест, поскольку сброс первичного ключа — относительно дорогостоящая база данных операция.

Принудительный последовательный запуск классов тестов

Если у вас есть классы тестов, которые нельзя запускать параллельно (например, потому что они используют общий ресурс), вы можете использовать django.test.testcases.SerializeMixin для их последовательного запуска. Этот миксин использует файловую систему lockfile.

Например, вы можете использовать __file__, чтобы определить, что все классы тестов в одном файле, унаследованные от SerializeMixin, будут запускаться последовательно:

import os

from django.test import TestCase
from django.test.testcases import SerializeMixin

class ImageTestCaseMixin(SerializeMixin):
    lockfile = __file__

    def setUp(self):
        self.filename = os.path.join(temp_storage_dir, 'my_file.png')
        self.file = create_file(self.filename)

class RemoveImageTests(ImageTestCaseMixin, TestCase):
    def test_remove_image(self):
        os.remove(self.filename)
        self.assertFalse(os.path.exists(self.filename))

class ResizeImageTests(ImageTestCaseMixin, TestCase):
    def test_resize_image(self):
        resize_image(self.file, (48, 48))
        self.assertEqual(get_image_size(self.file), (48, 48))

Использование Django-тестового исполнителя для тестирования повторно используемых приложений

Если вы пишете повторно используемое приложение, вы можете использовать Django-тестовый исполнитель для запуска собственного набора тестов и тем самым воспользоваться инфраструктурой Django для тестирования.

Общим подходом является директория tests рядом с кодом приложения со следующей структурой:

runtests.py
polls/
    __init__.py
    models.py
    ...
tests/
    __init__.py
    models.py
    test_settings.py
    tests.py

Давайте посмотрим внутрь нескольких этих файлов:

runtests.py
#!/usr/bin/env python
import os
import sys

import django
from django.conf import settings
from django.test.utils import get_runner

if __name__ == "__main__":
    os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.test_settings'
    django.setup()
    TestRunner = get_runner(settings)
    test_runner = TestRunner()
    failures = test_runner.run_tests(["tests"])
    sys.exit(bool(failures))

Это скрипт, который вы вызываете для запуска набора тестов. Он настраивает среду Django, создает тестовую базу данных и запускает тесты.

Для большей ясности этот пример содержит только самое необходимое для использования Django-тестового исполнителя. Вы можете добавить параметры командной строки для управления подробностью, передачи определенных тегов тестов для запуска и т. д.

tests/test_settings.py
SECRET_KEY = 'fake-key'
INSTALLED_APPS = [
    "tests",
]

Этот файл содержит настройки Django, необходимые для запуска тестов вашего приложения.

Опять же, это минимальный пример; ваши тесты могут потребовать дополнительных настроек для запуска.

Поскольку пакет tests включён в INSTALLED_APPS при запуске ваших тестов, вы можете определять тестовые модели только в файле models.py.

Использование различных фреймворков тестирования

Очевидно, что unittest — не единственный фреймворк для тестирования Python. Хотя Django не предоставляет явной поддержки альтернативных фреймворков, он предоставляет способ вызова тестов, созданных для альтернативного фреймворка, как если бы они были обычными Django-тестами.

При запуске ./manage.py test Django обращается к настройке TEST_RUNNER, чтобы определить, что делать. По умолчанию, TEST_RUNNER указывает на 'django.test.runner.DiscoverRunner'. Этот класс определяет стандартное поведение Django для тестирования. Это поведение включает:

  1. Выполнение глобальной предварительной настройки перед тестом.
  2. Поиск тестов в любом файле ниже текущей директории, имя которого соответствует шаблону test*.py.
  3. Создание тестовых баз данных.
  4. Запуск migrate для установки моделей и начальных данных в тестовые базы данных.
  5. Запуск проверок системы.
  6. Запуск найденных тестов.
  7. Удаление тестовых баз данных.
  8. Выполнение глобального завершения после теста.

Если вы определите свой собственный класс тестового исполнителя и укажете TEST_RUNNER на этот класс, Django будет выполнять ваш тестовый исполнитель всякий раз, когда вы запускаете ./manage.py test. Таким образом, можно использовать любой фреймворк тестирования, который можно выполнить из Python-кода, или изменить процесс выполнения Django-тестов, чтобы удовлетворить любые ваши требования к тестированию.

Определение тестового исполнителя

Тестовый исполнитель — это класс, определяющий метод run_tests(). Django поставляется с классом DiscoverRunner, который определяет стандартное поведение Django для тестирования. Этот класс определяет точку входа run_tests(), а также ряд других методов, которые используются run_tests() для настройки, выполнения и завершения набора тестов.

class DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, interactive=True, failfast=False, keepdb=False, reverse=False, debug_mode=False, debug_sql=False, **kwargs) [source]

DiscoverRunner будет искать тесты в любом файле, соответствующем шаблону pattern.

top_level можно использовать для указания директории, содержащей ваши основные Python-модули. Обычно Django может определить это автоматически, поэтому нет необходимости указывать этот параметр. Если он указан, он, как правило, должен быть директорией, содержащей ваш файл manage.py.

verbosity определяет объём уведомлений и отладочной информации, которые будут выведены в консоль; 0 — отсутствие вывода, 1 — нормальный вывод, и 2 — подробный вывод.

Если interactive равно True, набор тестов имеет разрешение запросить у пользователя инструкции при выполнении набора тестов. Примером такого поведения будет запрос разрешения на удаление существующей тестовой базы данных. Если interactive равно False, набор тестов должен быть способен работать без ручного вмешательства.

Если failfast равно True, набор тестов прекратит работу после обнаружения первой ошибки теста.

Если keepdb равно True, набор тестов будет использовать существующую базу данных или создать её при необходимости. Если False, новая база данных будет создана, попросив пользователя удалить существующую, если она есть.

Если reverse равно True, тесты будут выполняться в обратном порядке. Это может быть полезно для отладки тестов, которые не изолированы должным образом и имеют побочные эффекты. Группировка по классам тестов сохраняется при использовании этого параметра.

debug_mode определяет, какое значение должна иметь настройка DEBUG перед запуском тестов.

Если debug_sql равно True, в случае неудачи тестов запросы SQL будут регистрироваться в django.db.backends logger, а также будет отображаться трассировка. Если verbosity равно 2, запросы всех тестов будут выводиться.

Django может время от времени расширять возможности тестового исполнителя, добавляя новые аргументы. Объявление **kwargs позволяет осуществлять это расширение. Если вы создаёте подкласс DiscoverRunner или пишете свой собственный тестовый исполнитель, убедитесь, что он принимает **kwargs.

Ваш тестовый исполнитель также может определять дополнительные параметры командной строки. Создайте или переопределите метод класса add_arguments(cls, parser) и добавьте пользовательские аргументы, вызвав parser.add_argument() внутри метода, чтобы команда test могла использовать эти аргументы.

Атрибуты

DiscoverRunner.test_suite

Класс, используемый для построения набора тестов. По умолчанию он установлен в unittest.TestSuite. Это можно переопределить, если вы хотите реализовать другую логику сбора тестов.

DiscoverRunner.test_runner

Это класс низкоуровневого тестового исполнителя, который используется для выполнения отдельных тестов и форматирования результатов. По умолчанию он установлен в unittest.TextTestRunner. Несмотря на неудачное сходство в обозначениях, это не тот же тип класса, что и DiscoverRunner, который охватывает более широкий круг задач. Вы можете переопределить этот атрибут, чтобы изменить способ выполнения и отчётности тестов.

DiscoverRunner.test_loader

Это класс, который загружает тесты, будь то из TestCases, модулей или иным образом, и объединяет их в наборы тестов для выполнения исполнителем. По умолчанию он установлен в unittest.defaultTestLoader. Вы можете переопределить этот атрибут, если ваши тесты будут загружаться необычными способами.

Методы

DiscoverRunner.run_tests(test_labels, extra_tests=None, **kwargs) [source]

Запустить набор тестов.

test_labels позволяет указать, какие тесты запускать, и поддерживает несколько форматов (см. DiscoverRunner.build_suite() для списка поддерживаемых форматов).

extra_tests — список дополнительных экземпляров TestCase для добавления в набор, который выполняется тестовым исполнителем. Эти дополнительные тесты выполняются дополнительно к тем, которые обнаружены в модулях, перечисленных в test_labels.

Этот метод должен вернуть количество не пройденных тестов.

classmethod DiscoverRunner.add_arguments(parser) [source]

Переопределите этот метод класса, чтобы добавить пользовательские аргументы, принимаемые командой управления test. См. argparse.ArgumentParser.add_argument() для получения подробностей о добавлении аргументов в парсер.

END_OF_DOCUMENT_MARKER
DiscoverRunner.setup_test_environment(**kwargs) [source]

Настраивает тестовую среду, вызывая setup_test_environment() и устанавливая DEBUG на self.debug_mode (по умолчанию False).

DiscoverRunner.build_suite(test_labels, extra_tests=None, **kwargs) [source]

Создаёт набор тестов, соответствующий предоставленным меткам тестов.

test_labels — список строк, описывающих тесты, которые необходимо выполнить. Метка теста может иметь одну из четырёх форм:

  • path.to.test_module.TestCase.test_method — запустить один отдельный метод теста в случае теста.
  • path.to.test_module.TestCase — запустить все методы теста в случае теста.
  • path.to.module — найти и запустить все тесты в указанном Python-пакете или модуле.
  • path/to/directory — найти и запустить все тесты в указанной директории.

Если test_labels имеет значение None, тест-раннер будет искать тесты во всех файлах в текущей директории, имена которых соответствуют его pattern (см. выше).

extra_tests — список дополнительных экземпляров TestCase, которые нужно добавить в набор, который выполняет тест-раннер. Эти дополнительные тесты выполняются дополнительно к тем, которые обнаружены в модулях, перечисленных в test_labels.

Возвращает экземпляр TestSuite, готовый к запуску.

DiscoverRunner.setup_databases(**kwargs) [source]

Создаёт тестовые базы данных, вызывая setup_databases().

DiscoverRunner.run_checks() [source]

Выполняет системные проверки.

DiscoverRunner.run_suite(suite, **kwargs) [source]

Выполняет набор тестов.

Возвращает результат, полученный в ходе выполнения набора тестов.

DiscoverRunner.get_test_runner_kwargs() [source]

Возвращает ключевые аргументы для инициализации DiscoverRunner.test_runner.

DiscoverRunner.teardown_databases(old_config, **kwargs) [source]

Удаляет тестовые базы данных, восстанавливая условия до теста, вызывая teardown_databases().

DiscoverRunner.teardown_test_environment(**kwargs) [source]

Восстанавливает среду до состояния до начала тестов.

DiscoverRunner.suite_result(suite, result, **kwargs) [source]

Вычисляет и возвращает код возврата, основанный на наборе тестов и результате выполнения этого набора тестов.

Утилиты тестирования

django.test.utils

Для помощи в создании собственного тест-раннера Django предоставляет ряд утилит в модуле django.test.utils.

setup_test_environment(debug=None) [source]

Выполняет общую настройку до теста, например, устанавливает средства отслеживания для системы рендеринга шаблонов и настраивает буфер отправки ложных писем.

Если debug не None, настройка DEBUG изменяется на её значение.

teardown_test_environment() [source]

Выполняет общую завершающую настройку после теста, например, удаляет средства отслеживания из системы шаблонов и восстанавливает нормальную работу служб электронной почты.

setup_databases(verbosity, interactive, keepdb=False, debug_sql=False, parallel=0, aliases=None, **kwargs) [source]

Создаёт тестовые базы данных.

Возвращает структуру данных, которая предоставляет достаточно подробностей, чтобы отменить внесённые изменения. Эти данные будут предоставлены функции teardown_databases() по завершении тестирования.

Аргумент aliases определяет, для каких псевдонимов DATABASES должны быть настроены тестовые базы данных. Если он не предоставлен, по умолчанию используются все псевдонимы в DATABASES.

Добавлена в Django 2.2:

Добавлен аргумент aliases.

teardown_databases(old_config, parallel=0, keepdb=False) [source]

Удаляет тестовые базы данных, восстанавливая условия до начала тестов.

old_config — структура данных, определяющая изменения в конфигурации базы данных, которые необходимо отменить. Это возвращаемое значение метода setup_databases().

django.db.connection.creation

Модуль создания подключения к базе данных также предоставляет некоторые утилиты, которые могут быть полезны во время тестирования.

create_test_db(verbosity=1, autoclobber=False, serialize=True, keepdb=False)

Создаёт новую тестовую базу данных и выполняет migrate над ней.

verbosity имеет такое же поведение, как в run_tests().

autoclobber описывает поведение, которое произойдёт, если обнаружена база данных с тем же именем, что и тестовая база данных:

  • Если autoclobber равно False, пользователя попросят подтвердить уничтожение существующей базы данных. sys.exit вызывается, если пользователь не даёт согласия.
  • Если autoclobber равно True, база данных будет уничтожена без консультации с пользователем.

serialize определяет, сериализует ли Django базу данных в строку JSON в памяти перед запуском тестов (используется для восстановления состояния базы данных между тестами, если у вас нет транзакций). Можно установить это значение в False, чтобы ускорить время создания, если у вас нет ни одного тестового класса с serialized_rollback=True.

Если вы используете стандартный тест-раннер, вы можете управлять этим с помощью параметра SERIALIZE в словаре TEST.

keepdb определяет, должен ли тест использовать существующую базу данных или создать новую. Если True, будет использована существующая база данных, или создана, если отсутствует. Если False, будет создана новая база данных, предложив пользователю удалить существующую, если она есть.

Возвращает имя тестовой базы данных, которую она создала.

create_test_db() имеет побочный эффект изменения значения NAME в DATABASES для соответствия имени тестовой базы данных.

destroy_test_db(old_database_name, verbosity=1, keepdb=False)

Удаляет базу данных, имя которой является значением NAME в DATABASES, и устанавливает NAME на значение old_database_name.

Аргумент verbosity имеет такое же поведение, как для DiscoverRunner.

Если аргумент keepdb равен True, то подключение к базе данных будет закрыто, но база данных не будет уничтожена.

Интеграция с coverage.py

Покрытие кода описывает, какой объем исходного кода был протестирован. Оно показывает, какие части вашего кода выполняются тестами, а какие нет. Это важная часть тестирования приложений, поэтому настоятельно рекомендуется проверять покрытие ваших тестов.

Django легко интегрируется с coverage.py, инструментом для измерения покрытия кода Python-программ. Сначала установите coverage.py. Затем выполните следующую команду из папки вашего проекта, содержащей manage.py:

coverage run --source='.' manage.py test myapp

Это выполнит ваши тесты и соберет данные о покрытии выполненных файлов в вашем проекте. Отчет об этих данных можно увидеть, выполнив следующую команду:

coverage report

Обратите внимание, что некоторые части кода Django были выполнены во время выполнения тестов, но они не отображаются здесь из-за флага source, переданного предыдущей команде.

Для получения дополнительных опций, таких как аннотированные HTML-списки, показывающие пропущенные строки, см. документацию coverage.py.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.2/topics/testing/advanced/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API