Случайны выбор дневника Раскрыть/свернуть полный список возможностей


Найдено 4584 сообщений
Cообщения с меткой

тестирование - Самое интересное в блогах

Следующие 30  »
rss_rss_hh_new

[Из песочницы] Тестирование RESTful API на NodeJS с Mocha и Chai

Вторник, 23 Августа 2016 г. 16:18 (ссылка)



Перевод руководства Samuele Zaza. Текст оригинальной статьи можно найти здесь: https://scotch.io/tutorials/test-a-node-restful-api-with-mocha-and-chai*



Я до сих пор помню восторг от возможности наконец-то писать бекэнд большого проекта на node и я уверен, что многие разделяют мои чувства.



А что дальше? Мы должны быть уверены, что наше приложение ведет себя так, как мы того ожидаем. Один из самых распространенных способов достичь этого — тесты. Тестирование — это безумно полезная вещь, когда мы добавляем новую фичу в приложение: наличие уже установленного и настроенного тестового окружения, которое может быть запущено одной командой, помогает понять, в каком месте новая фига породит новые баги.

Ранее мы обсуждали разработку RESTful Node API и аутентификацию Node API. В этом руководстве мы напишем простой RESTful API и используем Mocha и Chai для его тестирования. Мы будем тестировать CRUD для приложения "книгохранилище".



Как всегда, вы можете все делать по шагам, читая руководство, или скачать исходный код на github.



Mocha: Тестовое окружение



Mocha — это javascript фреймворк для Node.js, который позволяет проводить асинхронное тестирование. Скажем так: он создает окружение, в котором мы можем использовать свои любимые assert библиотеки.





Mocha поставляется с огромным количеством возможностей. На сайте их огромный список. Больше всего мне нравится следующее:




  • простая поддержка асинхронности, включая Promise

  • поддержка таймаутов асинхронного выполнения

  • before, after, before each, after each хуки (очень полезно для очистки окружения перед тестами)

  • использование любой assertion библиотеки, которую вы заходите (в нашем случае Chai)



Chai: assertion библиотека



Итак, с Mocha у нас появилось окружение для выполнения наших тестов, но как мы будем тестировать HTTP запросы, например? Более того, как проверить, что GET запрос вернул ожидаемый JSON в ответ, в зависимости от переданных параметров? Нам нужна assertion библиотека, потому что mocha явно недостаточно.



Для этого руководства я выбрал Chai:





Chai дает нам своду выбора интерфейса: "should", "expect", "assert". Лично использую should, но вы можете выбрать любую. К тому же у Chai есть плагин Chai HTTP, который позволяет без затруднений тестировать HTTP запросы.



PREREQUISITES




  • Node.js: базовое понимание node.js и рекомендуется базовое понимание RESTful API (я не буду сильно углубляться в детали реализации).

  • POSTMAN для выполнения запросов к API.

  • Синтакс ES6: я решил использовать последнюю версию Node (6..), в которой хорошо реализована интеграция ES6 features для лучшей читаемости кода. Если вы еще не очень дружите с ES6, вы можете почитать отличные статьи (Pt.1, Pt.2 and Pt.3). Но не беспокойтесь, я буду давать пояснения когда встретится какой-нибудь особенные синтаксис.



Настало время настроить наше книгохранилище.



Настройка проекта



Структура папок



Структура проекта будет иметь следующий вид:



-- controllers 
---- models
------ book.js
---- routes
------ book.js
-- config
---- default.json
---- dev.json
---- test.json
-- test
---- book.js
package.json
server.json


Обратите внимание, что папка /config содержит 3 JSON файла: как видно из названия, они содержат настройки для различного окружения.



В этом руководстве мы будем переключаться между двумя базами данных — одна для разработки, другая для тестирования. Такие образом, файлы будут содержать mongodb URI в JSON формате:



dev.json и default.json:



{
"DBHost": "YOUR_DB_URI"
}


test.json:



{
"DBHost": "YOUR_TEST_DB_URI"
}


Больше о файлах конфигурации (папка config, порядок файлов, формат файлов) можно почитать [тут] (https://github.com/lorenwest/node-config/wiki/Configuration-Files).



Обратите внимание на файл /test/book.js, в котором будут все наши тесты.



package.json



Создайте файл package.json и вставьте следующее:



{
"name": "bookstore",
"version": "1.0.0",
"description": "A bookstore API",
"main": "server.js",
"author": "Sam",
"license": "ISC",
"dependencies": {
"body-parser": "^1.15.1",
"config": "^1.20.1",
"express": "^4.13.4",
"mongoose": "^4.4.15",
"morgan": "^1.7.0"
},
"devDependencies": {
"chai": "^3.5.0",
"chai-http": "^2.0.1",
"mocha": "^2.4.5"
},
"scripts": {
"start": "SET NODE_ENV=dev && node server.js",
"test": "mocha --timeout 10000"
}
}


Опять-таки, ничего нового для того, кто написал хотя бы один сервер на node.js. Пакеты mocha, chai, chai-http, необходимые для тестирования, устанавливаются в блок dev-dependencies (флаг --save-dev из командной строки).

Блок scripts содержит два способа запуска сервера.



Для mocha я добавил флаг --timeout 10000, потому что я забираю данные из базы, расположенной на mongolab и отпущенные двух секунд по умолчанию может не хватать.



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



Сервер



Давайте создадим файл server.js и вставим следующий код:



let express = require('express');
let app = express();
let mongoose = require('mongoose');
let morgan = require('morgan');
let bodyParser = require('body-parser');
let port = 8080;
let book = require('./app/routes/book');
let config = require('config'); // загружаем адрес базы из конфигов
//настройки базы
let options = {
server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
replset: { socketOptions: { keepAlive: 1, connectTimeoutMS : 30000 } }
};

//соединение с базой
mongoose.connect(config.DBHost, options);
let db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));

//не показывать логи в тестовом окружении
if(config.util.getEnv('NODE_ENV') !== 'test') {
//morgan для вывода логов в консоль
app.use(morgan('combined')); //'combined' выводит логи в стиле apache
}

//парсинг application/json
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.text());
app.use(bodyParser.json({ type: 'application/json'}));

app.get("/", (req, res) => res.json({message: "Welcome to our Bookstore!"}));

app.route("/book")
.get(book.getBooks)
.post(book.postBook);
app.route("/book/:id")
.get(book.getBook)
.delete(book.deleteBook)
.put(book.updateBook);

app.listen(port);
console.log("Listening on port " + port);

module.exports = app; // для тестирования


Основные моменты:




  • Нам нужен модуль config для доступа к файлу конфигурации в соответствии с переменной окружения NODE_ENV. Из него мы получаем mongo db URI для соединения с базой данных. Это позволит нам содержать основную базу чистой, а тесты проводить на отдельной базы, скрытой от пользователей.

  • Переменная окружения NODE_ENV проверяется на значение "test", чтобы отключить логи morgan в командной строке, иначе они появятся в выводе при запуске тестов.

  • Последняя строка экспортирует сервер для тестов.

  • Обратите внимание на объявление переменных через let. Оно делает переменную видимой только в рамках замыкающего блока или глобально, если она вне блока.



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



Модели и роутинг



Настало время для описать модель книги. Создадим файл book.js в папке /app/model/ со следующим содержимым:



let mongoose = require('mongoose');
let Schema = mongoose.Schema;

//определение схемы книги
let BookSchema = new Schema(
{
title: { type: String, required: true },
author: { type: String, required: true },
year: { type: Number, required: true },
pages: { type: Number, required: true, min: 1 },
createdAt: { type: Date, default: Date.now },
},
{
versionKey: false
}
);

// установить параметр createdAt равным текущему времени
BookSchema.pre('save', next => {
now = new Date();
if(!this.createdAt) {
this.createdAt = now;
}
next();
});

//Экспорт модели для последующего использования.
module.exports = mongoose.model('book', BookSchema);


У нашей книги есть название, автор, количество страниц, год публикации и дата создания в базе. Я установил опции versionKey значение false, так как она не нужна в данном руководстве.



Необычный callback в .pre() — это функция стрелка, функция с более коротким синтаксисом. Согласно определению MDN: "привязывается к текущему значению this (не имеет собственного this, arguments, super, or new.target). Функции-стрелки всегда анонимны".



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



В папке /app/routes/ создадим файл book.js следующего содержания:



let mongoose = require('mongoose');
let Book = require('../models/book');

/*
* GET /book маршрут для получения списка всех книг.
*/
function getBooks(req, res) {
//Сделать запрос в базу и, если не ошибок, отдать весь список книг
let query = Book.find({});
query.exec((err, books) => {
if(err) res.send(err);
//если нет ошибок, отправить клиенту
res.json(books);
});
}

/*
* POST /book для создания новой книги.
*/
function postBook(req, res) {
//Создать новую книгу
var newBook = new Book(req.body);
//Сохранить в базу.
newBook.save((err,book) => {
if(err) {
res.send(err);
}
else { //Если нет ошибок, отправить ответ клиенту
res.json({message: "Book successfully added!", book });
}
});
}

/*
* GET /book/:id маршрут для получения книги по ID.
*/
function getBook(req, res) {
Book.findById(req.params.id, (err, book) => {
if(err) res.send(err);
//Если нет ошибок, отправить ответ клиенту
res.json(book);
});
}

/*
* DELETE /book/:id маршрут для удаления книги по ID.
*/
function deleteBook(req, res) {
Book.remove({_id : req.params.id}, (err, result) => {
res.json({ message: "Book successfully deleted!", result });
});
}

/*
* PUT /book/:id маршрут для редактирования книги по ID
*/
function updateBook(req, res) {
Book.findById({_id: req.params.id}, (err, book) => {
if(err) res.send(err);
Object.assign(book, req.body).save((err, book) => {
if(err) res.send(err);
res.json({ message: 'Book updated!', book });
});
});
}

//экспортируем все функции
module.exports = { getBooks, postBook, getBook, deleteBook, updateBook };


Основные моменты:




  • Все маршруты стандартные GET, POST, DELETE, PUT для выполнение CRUD.

  • В функции updatedBook() мы используем Object.assign, новую функцию ES6, которая перезаписывает общие свойства book и req.body и оставляет.остальные нетронутыми

  • В конце мы экспортируем объект с использованием синтаксиса "короткое свойство" (на русском можно почитать тут, прим. переводчика) чтобы не делать повторений.



Мы закончили эту часть и получили готовое приложение!



Наивное тестирование



Давайте запустим наше приложение, откроем POSTMAN для отправки HTTP запросов к серверу и проверим что все работает как ожидалось.



В командной строке выпоним



npm start


GET /BOOK



В POSTMAN выполним GET запрос и, если предположить что в базе есть книги, получим ответ:

:



Сервер без ошибок вернул книги из базы.



POST /BOOK



Давайте добавим новую книгу:





Похоже, что книга добавилась. Сервер вернул книгу и сообщение, подтверждающее, что она была добавлена. Так ли это? Выполним еще один GET запрос и посмотрим на результат:





Работает!



PUT /BOOK/:ID



Давайте поменяем количество страниц в книге и посмотрим на результат:





Отлично! PUT тоже работает, так что можно выполнить еще один GET запрос для проверки





Все работает...



GET /BOOK/:ID



Теперь получим одну книгу по ID в GET запросе и потом удалим ее:





Получили правильный ответ и теперь удалим эту книгу:



DELETE /BOOK/:ID



Посмотрим на результат удаления:





Даже последний запрос работает как и задумано и нам даже не нужно делать еще один GET запрос для проверки, так как мы отправили клиенту ответ от mongo (свойство result), которое показывает, что книга действительно удалилась.



При выполнении тестом через POSTMAN приложение ведет себя как и ожидается, верно? Значит, его можно можно использовать на клиенте?



Давайте я вам отвечу: НЕТ!!



Наши действия я называю наивным тестированием, потому что мы выполнили только несколько операций без учета спорных случаев: POST запрос без ожидаемых данных, DELETE с неверным id или вовсе без id.



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



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



Давайте сделаем что-то лучшее, чтобы тестировать наше приложение.



Хорошее тестирование



Во-первых, давайте создадим файл books.js в папке /test:



//During the test the env variable is set to test
process.env.NODE_ENV = 'test';

let mongoose = require("mongoose");
let Book = require('../app/models/book');

//Подключаем dev-dependencies
let chai = require('chai');
let chaiHttp = require('chai-http');
let server = require('../server');
let should = chai.should();

chai.use(chaiHttp);
//Наш основной блок
describe('Books', () => {
beforeEach((done) => { //Перед каждым тестом чистим базу
Book.remove({}, (err) => {
done();
});
});
/*
* Тест для /GET
*/
describe('/GET book', () => {
it('it should GET all the books', (done) => {
chai.request(server)
.get('/book')
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('array');
res.body.length.should.be.eql(0);
done();
});
});
});

});


Как много новых штук! Давай разберемся:




  • Обязательно обратите внимание на переменную NODE_ENV которой мы присвоили значение test. Это позволит серверу загрузить конфиг для тестовой базы и не выводить в консоль логи morgan.

  • Мы подключили dev-dependencies и собственно сервер (мы его экспортировали через module.exports).

  • Мы подключили chaiHttp к chai .



Все начинается с блока describe, который используется для улучшения структуризации наших утверждений. Это отразится на выводе, как мы увидим позже.



beforeEach — это блок, который выполнится для каждого блока описанного в этом describe блоке. Для чего мы это делаем? Мы удаляем все книги из базы, чтобы база была пуста в начале каждого тесте.



Тестируем /GET



Итак, у нас есть первый тест. Chai выполняет GET запрос и проверяет, что переменная res удовлетворяет первому параметру (утверждение) блока it "it should GET all the books". А именно, для данного пустого книгохранилища ответ должен быть следующим:




  • Статус 200.

  • Результат должен быть массивом.

  • Так как база пуста, мы ожидаем что размер массива будет равен 0.



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



Терерь в командной строке выпоним:



npm test


и получим:



Тест прошел и вывод отражает структуру, которую мы описали с помощью блоков describe.



Тестируем /POST



Теперь проверим насколько хорош наш API. Предположим мы пытаемся добавить книгу без поля `pages: сервер не должен вернуть соответствующую ошибку.



Добавим этот код в конец блока describe('Books'):



describe('/POST book', () => {
it('it should not POST a book without pages field', (done) => {
let book = {
title: "The Lord of the Rings",
author: "J.R.R. Tolkien",
year: 1954
}
chai.request(server)
.post('/book')
.send(book)
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('errors');
res.body.errors.should.have.property('pages');
res.body.errors.pages.should.have.property('kind').eql('required');
done();
});
});

});


Тут мы добавили тест на неполный /POST запрос. Посмотрим на проверки:




  • Статус должен быть 200.

  • Тело ответа должно быть объектом.

  • Одним из свойств тела ответа должно быть errors.

  • У поля errors должно быть пропущенное в запросе свойство pages.

  • pages должно иметь свойство kind равное required чтобы показать причину почему мы получили негативный ответ от сервера.



Обратите внимание, что мы отправили данные о книге с помощью метода .send().



Давайте выполним команду еще раз и посмотрим на вывод:





Тест работает!!



Перед тем, как писать следующий тест, уточним пару вещей:




  • Во-первых, почему ответ от сервера имеет такую структуру? Если вы читали callback для маршрута /POST, то вы увидели что в случае ошибки сервер отправляет в ответ ошибку от mongoose. Попробуйте сделать это через POSTMAN и посмотрите на ответ.

  • В случае ошибки мы все равно отвечаем с кодом 200. Это сделано для простоты, так как мы только учимся тестировать наш API.



Однако я бы предложил отдавать в ответ статус 206 Partial Content instead



Давайте отправим правильный запрос. Вставьте следующий код в конец блока describe(''/POST book''):



it('it should POST a book ', (done) => {
let book = {
title: "The Lord of the Rings",
author: "J.R.R. Tolkien",
year: 1954,
pages: 1170
}
chai.request(server)
.post('/book')
.send(book)
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('message').eql('Book successfully added!');
res.body.book.should.have.property('title');
res.body.book.should.have.property('author');
res.body.book.should.have.property('pages');
res.body.book.should.have.property('year');
done();
});
});


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



Снова запустим команду и получим:





Тестируем /GET/:ID



Теперь создадим книгу, сохраним ее в базу и используем id для выполнения GET запроса. Добавим следующий блок:



describe('/GET/:id book', () => {
it('it should GET a book by the given id', (done) => {
let book = new Book({ title: "The Lord of the Rings", author: "J.R.R. Tolkien", year: 1954, pages: 1170 });
book.save((err, book) => {
chai.request(server)
.get('/book/' + book.id)
.send(book)
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('title');
res.body.should.have.property('author');
res.body.should.have.property('pages');
res.body.should.have.property('year');
res.body.should.have.property('_id').eql(book.id);
done();
});
});

});
});


Через asserts мы убедились, что сервер возвратил все поля и нужную книгу (id в ответе от севера совпадает с запрошенным):





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



Тестируем /PUT/:ID



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



describe('/PUT/:id book', () => {
it('it should UPDATE a book given the id', (done) => {
let book = new Book({title: "The Chronicles of Narnia", author: "C.S. Lewis", year: 1948, pages: 778})
book.save((err, book) => {
chai.request(server)
.put('/book/' + book.id)
.send({title: "The Chronicles of Narnia", author: "C.S. Lewis", year: 1950, pages: 778})
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('message').eql('Book updated!');
res.body.book.should.have.property('year').eql(1950);
done();
});
});
});
});


Мы хотим убедиться, что поле message равно Book updated! и поле year действительно изменилось.





Мы почти закончили.



Тестируем /DELETE/:ID.



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



describe('/DELETE/:id book', () => {
it('it should DELETE a book given the id', (done) => {
let book = new Book({title: "The Chronicles of Narnia", author: "C.S. Lewis", year: 1948, pages: 778})
book.save((err, book) => {
chai.request(server)
.delete('/book/' + book.id)
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('message').eql('Book successfully deleted!');
res.body.result.should.have.property('ok').eql(1);
res.body.result.should.have.property('n').eql(1);
done();
});
});
});
});


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





Восхитительно! Наши тесты проходят и у нас есть отличная база для тестирования нашего API с помощью более изысканных проверок.



Заключение



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



Мы прошли через все этапы создания RESTful API, делая наивные тесты с POSTMAN, а затем предложили лучший способ тестирования, являлось нашей основной целью.



Написание тестов является хорошей привычкой для обеспечения стабильности работы сервера. К сожалению часто это недооценивается.



Бонус: Mockgoose



Всегда найдется кто-то, кто скажет что две базы — это не лучшее решение, но другого не дано. И что же делать? Альтернатива есть: Mockgoose.



По сути Mockgoose создает обертку для Mongoose, которая перехватывает обращения к базе и вместо этого использует in memory хранилище. К тому же он легко интегрируется с mocha



Примечание: Mockgoose требует чтобы на машине, где запускаются тесты была установлена mongodb


Original source: habrahabr.ru.

https://habrahabr.ru/post/308352/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Один день из жизни тестировщика системы локального позиционирования

Вторник, 23 Августа 2016 г. 15:23 (ссылка)

Всем привет!

Меня зовут Денис Койвистойнен nimpos и я являюсь тестировщиком в компании RTL-Service.

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





Поехали



9:00

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



9:10

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



9:25

Просматриваем и анализируем логи от устройств, оставленных на ночь на тестирование. Для этого используем стандартные команды linux для фильтрации данных (grep, cat, tail, more) и написанными сотрудниками нашего отдела скриптами на Python и Bash.



Рис.№ 1 — Анализ полученных логов



10:30

Приступаем к выполнению поставленных на сегодня задач: одна из приоритетных задач, имеющих статус “Срочно” — протестировать новую версию прошивки для точки доступа (access point), в которой ранее был пофиксен баг (произвольная смена режима работы устройства со шлюза на ретранслятор). Загружаем новую версию прошивки в устройство, проверяем, что она корректно загрузилась. В терминале настраиваем фильтрацию по заданному режиму работы (используем grep), выходные данные результатов указываем в файл для того, чтобы в конце эксперимента можно было проверить его на наличие ошибок, если они возникнут в режиме. Для сбора данных потребуется от нескольких часов до нескольких суток, так что можно перейти к следующей задаче.



11:30

Далее у нас на очереди по срочным задачам — проверка голосовой сессии через цепочки ретрансляторов. В качестве шлюзов и ретрансляторов будем использовать оборудование нашего производства — RealTracTM Access Point Indoor (точка доступа в офисном исполнении, в задачу которой входит формирование зоны радиопокрытия и осуществление передачи данных от\к мобильным устройствам с целью обеспечения локального позиционирования и передачи голоса (Рис.№ 2)).



Рис.№ 2 — RealTracTM Access Point Indoo



Для этого прошиваем наш шлюз (шлюз-точка доступа, ШТД), через который будут приниматься пакеты с ретрансляторов (ретранслятор-точка доступа, РТД), все наши ретрансляторы и коммуникатор (носимое радиоустройство с функцией голосовой связи, обеспечивающее передачу данных от\к стационарным радиоустройствам в пределах зон радиопокрытия (Рис.№ 3)) на прошивку одной версии.



Рис.№ 3 — Коммуникатор



Расставляем нашу цепочку в последовательности ШТД — РТД — РТД — РТД (Рис.№ 4). Одно из немаловажных условий для корректной передачи данных – это то, что устройство должно быть в зоне прямой видимости следующего устройства в цепочке.



Рис.№ 4 — Схема расположения оборудования



12:00

Все устройства, которые будут использоваться в тестировании, расставлены, можно приступать к нашему тесту (Рис.№5).



Рис.№ 5 — Схема расположения оборудования



И тут, на нашем пути, возникла проблема – площадка для проведения теста – небольшая, а стены недостаточно плотные и не экранируют сигналы. В результате сигнал от ретрансляторов проходит сквозь стены. Это создает такой эффект, что несколько ретрансляторов будут слышать коммуникатор, а это недопустимо, так как мы проверяем корректность передачи сигнала по цепочке РТД. Для решения возникшей проблемы мы уменьшаем мощность ретрансляторов и коммуникатора. Для уменьшения мощности передачи сигнала устройством мы используем разработанную нашей компанией утилиту setparam.



12:15

Мощности на устройствах уменьшены. Теперь надо убедиться, что несколько РТД не будут слышать коммуникатор. Для проверки слышимости точек доступа из конкретного места воспользуемся анализатором (носимое устройство, разработанное нашей компанией специально для измерения по радиоканалу различных параметров устройств, в том числе RSSI, расстояния до всех находящихся в зоне слышимости устройств и прочее (Рис.№6)).



Рис.№ 6 — Анализатор



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



12:30

После некоторых перестановок ретрансляторов по территории удалось добиться необходимого эффекта. Теперь дело за малым — один сотрудник выполняет роль диспетчера и звонит на коммуникатор другого, который стоит в конце цепочки. Если вызов на коммуникатор прошёл, значит, цепочка из ретрансляторов работает исправно. Теперь проверяем цепочку, вызывая диспетчера с коммуникатора. При вызове с коммуникатора у диспетчера появляется уведомление о входящем вызове.



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

Ретранслятор в центре цепочки отключен, сотрудник с коммуникатора стоит у последнего ретранслятора в цепочке, диспетчер звонит на коммутатор — и вызов не проходит до коммуникатора. Пробуем совершить вызов в обратную сторону — вызываем с коммутатора нашего диспетчера — в ответ – тишина, это как раз то, что нам и требовалось.



Тест подошёл к концу, осталось проверить логи сервера на наличие ошибок. Для этого переходим в наш каталог с логами и выполняем команду для парсинга по всем файлам на наличие строк “ERROR”, “WARNING”, “EXCEPTION”.



Обнаруженное сообщение ERROR



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



13:03

Обеденное время. На время обеда запустим авто-тесты веб-клиента (про использование данного способа ускорения автоматизации тестирования веб-интерфейса за счёт применение Python и Selenide есть статья в нашем хабе) (https://habrahabr.ru/company/rtl-service/blog/300860/), чтобы система зря не простаивала.



14:00

Из всех авто-тестов, запущенных на обеде, с ошибкой завершился только один. Когда будет свободное время, надо будет посмотреть, в чём проблема. Для этого сохраним лог выполнения задачи в отдельный файл для его дальнейшего изучения.





Ошибки при выполнении автотестов



Проверяем логи, отфильтрованные по ошибкам в нашем эксперименте с звонками на коммуникатор. Критических ошибок не выявлено. Идём дальше.



14:30

Поступила задача с приоритетом «Немедленно» на выполнение, это означает, что все задачи на текущий момент приостанавливаются. Суть поставленной задачи в том, что при вращении подложки нанесенной на карту в веб-клиенте, загрузка оперативной памяти и центрального процессора возрастала до 80-90 % и не высвобождалась по окончанию вращения. Было озвучено предположение, что такую нагрузку на систему вызывает процесс Java, поражаемой нашей системой. Для выполнения моей задачи требовалось попробовать воспроизвести данную ошибку.

Для этого были выбраны подложки нескольких размеров (1000 x 1000, 3508 x 2480). Разворачиваем нашу систему, устанавливаем нашу первую подложку из выбранных (1000 x 1000) и начинаем вращать, наблюдая как возрастает нагрузка на центральный процессор и оперативную память в отдельной консоли (используем консольные команды top и htop). При подложке такого размера не удалось нагрузить систему до требуемых более 80%. Теперь берем подложку более крупного размера. Повторяем наши прошлые действия уже с новой подложкой — вращаем её, одновременно наблюдаем параметры загрузки в консоли — тут результат уже есть, при вращении подложки около минуты нам уже удалось создать нагрузку в 84 %, этого уже достаточно для воспроизведения поставленной задачи. Ждём 10 — 15 минут, чтобы проверить, будет ли снижаться нагрузка на процессор и оперативную память.





Вывод команды top



15:20

За прошедшее время, а было времени выделено даже больше, чем планируемые 10-15 минут, нагрузка с процессора спала до 5-7 %, а нагрузка на оперативную память так и осталась в районе 80%.

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



15:50

Повторный эксперимент показал аналогичный результат. Оформляем полученные результаты о выявленной проблеме в поставленной задаче.



16:20

Просмотрим, не сменился ли режим работы устройства, которое мы прошили утром. Для этого смотрим, что лог, фильтрующий значения смены режимов устройств пуст. Значит, строим предположение, что за 5 часов работы смена режима не наблюдалось. Но для проверки оставим тест на сутки и завтра проверим результат по сохраненным логам.



16:40

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



17:30

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



18:00

Проверяем, что логи пишутся в файл, устройство включено в сеть. Можно отправляться домой. А завтра вновь, навстречу новым невыявленным багам, интересным задачам и трудностям, которые всегда встречаются на нелёгком пути тестировщика.



Что в итоге





Подводя итоги прошедшего дня, можно сделать вывод, что для корректного проведения тестов и получения достоверных результатов требуется особое внимание уделить этапу предварительного планирования теста. Следует заранее предусмотреть все трудности и возможные проблемы, с которыми можно столкнуться во время проведения теста, это позволит минимизировать время на устранение (решение) проблем.



К примеру, эксперимент по передаче голоса по цепочке ретрансляторов занял бы гораздо меньше времени, если бы мы заранее (ещё на этапе планирования эксперимента) учли, что ретрансляторы будут слышать друг друга через стены, и уменьшили бы мощность ретрансляторов. А во время проведения эксперимента не отвлекались бы на эту проблему.



Также ещё до начала расстановки оборудования и проведения тестов следует несколько раз удостовериться, что параметры, выставленные на используемом оборудовании, соответствует требуемым значениям. Проверить, что оборудование определяется в системе, световая и звуковая индикация, где она есть, исправна и корректно функционирует. Это позволит сэкономить время на замену неисправного устройства и повторения теста (вследствие неверно выставленного значения параметра).



Спасибо за внимание, готов ответить на вопросы в комментариях.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/308342/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
stertenorva

SpaceX приступает к тестированию "марсианского" двигателя

Воскресенье, 21 Августа 2016 г. 15:34 (ссылка)

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

Читать далее...
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Через тернии к сборке

Вторник, 09 Августа 2016 г. 10:31 (ссылка)

Привет, дорогие читатели. Я – разработчик в компании “RTL Service”, в которой мои обязанности по разработке продукта пересекаются с обязанностями DevOps. Конкретнее – я создаю и поддерживаю инфраструктуру сборки и первичного тестирования наших продуктов еще до их попадания в отдел тестирования.



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

В качестве сервера CI (непрерывной интеграции) у нас используется Hudson, можете кидать в меня тапками, но мы руководствуемся принципом «Работает — не трогай».

В дальнейшем есть планы попробовать TeamCity либо Jenkins.



Общая информация о задачах и группах на нашем CI сервере.



Все задачи по сборкам у нас разбиты на 5 больших групп:

https://habrahabr.ru/post/307398/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Перевод] Тестирование интеграции продукта на скорости Netflix

Среда, 27 Июля 2016 г. 21:12 (ссылка)

Нормальное взаимодействие участников Netflix обеспечивается архитектурой микросервисов и привязано персонально к каждому из наших более чем 80 миллионов участников. Сервисы принадлежат разным командам (группам), каждая из которых имеет свой собственный цикл разработки и релиза. Это означает, что необходимо иметь постоянно действующую и компетентную группу тестирования интеграции, обеспечивающую выполнение сквозных стандартов качества в ситуации, когда микросервисы вводятся в действие каждый день децентрализованно.



В качестве группы тестирования интеграции разрабатываемых продуктов мы обязаны не снижать скорость введения нового, обеспечивая в то же время контроль качества и быструю обратную связь для разработчиков. Каждая группа разработчиков отвечает за качество поставляемого ею продукта. Нашей задачей является бесперебойная работа с различными техническими группами с упором на сквозную функциональность и координацию деятельности групп. Мы представляем собой небольшую группу специалистов по тестированию интеграции в организации, насчитывающей более 200 разработчиков.



Быстрый ввод новых разработок при необходимости обеспечении требуемого качества создаёт интересные задачи для нашей команды. В настоящей статье мы рассмотрим три такие задачи:



1. Тестирование и мониторинг высокорейтинговых показов (High Impact Title = HIT = хит)

2. A/B-тестирование

3. Глобальный запуск



Тестирование и мониторинг высокорейтинговых показов



Имеется множество высокорейтинговых показов — как, например, телесериал «Оранжевый — хит сезона», которые регулярно появляются на Netflix. Форма и размер этих показов — самые разные. Некоторые являются сериалами, некоторые — отдельными картинами; есть ориентированные только на детей; какие-то выстреливают все серии сезона сразу, а другие выпускают по несколько серий каждую неделю. Часть этих показов запускается со сложными A/B-тестами, в которых каждый элемент теста имеет различное взаимодействие с участником.



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



Стратегия тестирования зависит от её фазы. На разных фазах действует разная стратегия продвижения, что делает задачу тестирования/автоматизации довольно сложной. В основном, можно выделить две фазы:



1. До запуска показа. До запуска необходимо обеспечить нахождение метаданных показа в требуемом месте, чтобы в день запуска всё прошло безукоризненно. Поскольку в запуске хита участвует множество групп (команд), то необходимо убедиться, что стыковка всех внутренних (серверных) систем друг с другом и с клиентской частью пользовательского интерфейса происходит безупречно. Продвижение показа осуществляется через Spotlight (большое окно, похожее на доску объявлений, в верхней части главной страницы Netflix), через тизеры и трейлеры. Но поскольку на каждом уровне Netflix имеется персонализация, то необходимо создавать сложные тестовые наборы, чтобы обеспечить соответствие типа показа профилю участника. Поскольку система постоянно изменяется, то автоматизация становится трудной. Основное тестирование на этой фазе происходит вручную.



2. После запуска показа. Наша работа не заканчивается в день запуска. Мы должны постоянно контролировать запущенные показы, чтобы ни в коем случае не допустить ухудшения взаимодействия с участником. Показ становится частью расширенного каталога Netflix, и это само по себе создаёт проблему. Мы должны теперь написать тесты, проверяющие, продолжает ли показ находить свою аудиторию согласованным образом и сохраняется ли целостность данных у этого показа (например, некоторые проверки выясняют, не изменилось ли общее количество серий после запуска; другая проверка контролирует, продолжают ли результаты поиска возвращать показ в надлежащие поисковые строки). Но, имея 600 часов оригинального программирования на Netflix, идущего онлайн только в этом году, дополнительно к лицензированному контенту, мы не можем положиться здесь на ручное тестирование. Также, когда показ запущен, существуют общие предположения, которые мы можем сделать о нём, поскольку данные для этого показа и логика продвижения не будут меняться — например, количество серий больше 0 для ТВ-выпусков, показ доступен для поиска (действительно как для кинофильмов, так и для ТВ-выпусков) и т.д. Это позволяет нам автоматически мониторить, продолжают ли те или иные операции, связанные с каждым показом, работать правильно.



Тестирование хитов является сложной задачей, и оно привязано ко времени. Но участие в запуске показа, отслеживание того, что все связанные с показом функции, серверная логика работают правильно во время запуска, даёт волнующий опыт. Просмотр фильмов со знаменитостями и крутые промо-материалы от Netflix представляют собой также приятную добавку.



A/B-тестирование



Мы осуществляем множество A/B-тестов. В каждый момент времени работает много A/B-тестов с различным уровнем сложности.



В прошлом основная часть проверки в A/B-тестах представляла собой комбинацию автоматизированного и ручного тестирования: автоматика использовалась для индивидуальных компонентов (тестирование методом белого ящика), а сквозное тестирование (тестирование методом чёрного ящика) происходило, большей частью, вручную. Когда объём A/B-тестов у нас заметно увеличился, оказалось невозможным вручную осуществлять все требуемые сквозные тесты, и мы начали наращивать автоматизацию.



Одной из главных проблем при введении сквозной автоматизации A/B-тестов стало огромное количество компонентов, подлежащих автоматической обработке. Наш подход состоял в рассмотрении автоматизации тестирования как поставляемого продукта и в сосредоточенности на поставке продукта с минимальным функционалом (minimum viable product = MVP), состоящего из частей, допускающих многократное использование. Нашим требованием к MVP было обеспечение подтверждения базового взаимодействия с участником путём проверки правильности данных от конечных REST-точек различных микросервисов. Это давало нам возможность итерационно двигаться к решению вместо поиска наилучшего решения сразу при старте.







Существенной отправной точкой для нас было создание общей библиотеки, обеспечивающей возможность многократного использования и переназначения модулей для любого автоматизированного теста. Например, у нас был A/B-тест, модифицировавший «Мой список» участника, — при его автоматизации мы написали скрипт, добавлявший показ(ы) в «Мой список» участника или удалявший показ(ы) из этого списка. Эти скрипты были спараметрированы так, чтобы их можно было многократно использовать в любом будущем A/B-тесте, имевшем дело с «Моим списком». Такой подход позволил нам быстрее автоматизировать A/B-тесты благодаря большему количеству многократно используемых компоновочных блоков. Эффективность работы была повышена путём максимально возможного применения уже существующей автоматизации. Например, вместо написания нашей собственной программы автоматизации пользовательского интерфейса мы смогли использовать Netflix Test Studio для переключения между сценариями тестирования, требующими действий со стороны пользовательского интерфейса для различных устройств.



При выборе языка/платформы для внедрения нашей автоматизации мы исходили из необходимости обеспечения быстрой обратной связи для команд разработчиков продукта. Это требовало действительно быстрой работы тестового комплекса — выполнения буквально за секунды. Мы также стремились сделать наши тесты как можно более лёгкими для внедрения и распространения. Имея в виду эти два требования, мы отказались от нашего первого выбора — Java. Наши тесты оказались бы зависимыми от использования множества взаимосвязанных jar-файлов, и пришлось бы заниматься управлением зависимостями, контролем версий, будучи подверженными воздействиям изменений в различных версиях файлового формата JAR. Всё это значительно увеличило бы длительность тестов.



Мы решили ввести нашу автоматизацию, получая доступ к микросервисам через их конечные REST-точки, благодаря чему мы могли бы настраивать использование jar-файлов и не писать какую-либо бизнес-логику. Чтобы обеспечить простоту внедрения и распространения нашей автоматизации, мы решили использовать комбинацию параметризированной оболочки и python-скриптов, которая может быть выполнена из командной строки. Это должен был быть отдельный скрипт оболочки для управления исполнением тестового сценария, в ходе которого должны вызываться другие скрипты оболочки и python-скрипты, действующие как многократно используемые утилиты.







Такой подход имеет несколько положительных моментов:



1. Мы смогли получить длительность теста (включая время на установку и отсоединение) 4-90 секунд; медиана времени работы — 40 секунд. При использовании автоматизации на базе Java медиана времени работы оценочно могла бы быть 5-6 минут.

2. Непрерывная интеграция была упрощена. Всё, что нам требовалось, это система Jenkins Job, которая осуществляет нисходящую загрузку из нашего репозитария, выполняет требуемые скрипты и регистрирует результаты. Встроенный в Jenkins консольный анализ записей оказался достаточным для получения статистики тест «прошёл / не прошёл».

3. Лёгкий запуск. Чтобы сторонний специалист запустил наш тестовый комплекс, требуется только доступ к нашему гит-репозитарию и терминал.



Глобальный запуск



Один из наших самых больших проектов в 2015 году состоял в том, чтобы удостовериться, что мы имели достаточное тестирование интеграции, обеспечивающее гладкий одновременный запуск Netflix в 130 странах. Фактически нам требовалось автоматизировать, как минимум, тестовый комплекс на общую работоспособность для каждой комбинации страны и языка. Это заметно осложнило функциональность нашего продукта автоматизации.



Наши тесты работали довольно быстро, поэтому мы первоначально решили, что достаточно будет запускать тестовую программу в цикле для каждой комбинации страны и языка. Результатом стало то, что тесты, которые проходили примерно за 15 секунд, начали работать по часу и более. Требовалось найти более приемлемый подход к этой проблеме. В дополнение к этому каждый протокол тестирования вырос примерно в 250 раз, что сделало более трудным анализ неудач. Чтобы справиться с этими проблемами, мы сделали два дела:



1. Мы использовали плагин Jenkins Matrix для запараллеливания наших тестов, благодаря чему тесты для каждой страны начали выполняться параллельно. Мы также должны были настроить наши ведомые устройства Jenkins на такое использование разных исполнителей, чтобы другие задания не стояли в очереди, когда наши тесты сталкивались с любой состязательной ситуацией или с бесконечными циклами. Это было выполнимо для нас, потому что у нашей автоматизации были только затраты, связанные с работающими скриптами оболочки, и не было необходимости предварительной загрузки двоичных файлов.



2. Мы не хотели осуществлять рефакторинг каждого теста, написанного до этого момента, и мы не хотели, чтобы каждый тест работал с каждой отдельной комбинацией страна/язык. В результате мы решили использовать модель «по запросу», при которой мы могли продолжать писать автоматизированные тесты так, как мы это делали раньше, а для выведения его на глобальную готовность к нему добавлялась бы надстройка. Эта надстройка должна содержать идентификатор тестового набора и комбинацию «страна/язык» в качестве параметров, а затем должна выполнять тестовый набор с этими параметрами, как показано ниже:







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



Проблемы будущего



Темп введения нового не замедляется на Netflix — он только растёт. Поэтому наш продукт автоматизации продолжает развиваться. Вот некоторые из проектов на нашей дорожной карте:



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



2. Встраивание предупреждений. В Netflix имеется несколько систем предупреждений. Но включение определённых предупреждений оказывается иногда не имеющим отношения к выполнению соответствующих тестовых комплексов. Это вызывается тем, что тесты зависят от сервисов, которые могут не функционировать на 100% и могут быть вообще неисправными, давая неприменимые для нас результаты. Необходимо создать систему, которая может анализировать эти предупреждения и затем определять, какие тесты должны быть запущены.



3. Учёт беспорядка. Наши тесты в настоящее время предполагают, что среда Netflix функционирует на 100%, но такое не всегда имеет место. Команда специалистов по надёжности постоянно выполняет испытания на разупорядоченность, чтобы тестировать полную целостность системы. В настоящее время результаты автоматизации тестирования в деградировавшей среде показывают интенсивность отказов более 90%. Мы должны улучшить нашу автоматизацию тестирования, чтобы обеспечить соответствующие результаты при работе в деградировавшей среде.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/306460/

Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Польза от Grafana для отдела тестирования

Вторник, 26 Июля 2016 г. 11:52 (ссылка)

Доброго времени суток!

Как уже говорилось в предыдущих постах, наша компания (RTL-Service) занимается системой локального позиционирования. Перед вами – новая статья от отдела тестирования.

В процессе тестирования каких-либо объектов (устройства, сервер, клиент,...) часто необходимо знать, как в течение промежутка времени изменяются значения параметров этих объектов.



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



В нашем отделе был написан проект (на Python) для проверки прошивок устройств на адекватность принимаемых значений параметров. В рамках этого проекта на устройства в течение суток постоянно отсылались запросы на смену значений параметров. При этом, если отсылалось допустимое значение параметра, то отслеживалось, что устройство приняло запрос и установило соответствующее значение параметра. Если устройству отсылалось недопустимое значение параметра, то проверялось, что устройство его отвергло и сохранило «старое» значение параметра. Так как при альфа-тестировании прошивки, как правило, присылаются на устройства только допустимые значения параметров, то в результате проведения тестов появляются баги.



Практика использования разработанного проекта показала, что багофикс идет. Однако, для установления причины возникновения этих багов требовалось еще потратить время, чтобы определить как часто возникает некорректная ситуация, в какие моменты времени, с какой периодичностью. Наиболее простым вариантом решения этой задачи является построение графиков. Конечно, в python есть библиотеки matplotlib и пр., но наиболее оптимальным вариантом является отрисовка изменения параметров с помощью дашбордов.



В сети существует большое количество дашбордов: Graphite, Grafana, Diamond и т.п. Но наш выбор пал именно на Grafana.

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



image


Это чудо создано шведским человеком по имени Торкель. Посмотреть гайды по установке и использованию можно тут.



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

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

На нижеприведенном рисунке видно, как изменялась температура и заряд батареи от времени для одного из наших устройств:



image


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

Далее приведу наглядный график изменения давления:



image


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



image


В общем и целом, Grafana — очень удобное средство для мониторинга разного типа параметров, которое всегда придет на помощь.

В следующем посту от отдела тестирования мы на примере одного дня из жизни тестировщика покажем специфику работы в нашем ОТК.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/306406/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Как настроить расширяемую систему для регрессионного тестирования на телефонах: опыт мобильной Почты Mail.Ru

Пятница, 22 Июля 2016 г. 15:07 (ссылка)





Привет, Хабр! Сегодня я хочу рассказать, как мы построили с нуля гибкую и расширяемую систему для выполнения автотестов на Android-смартфонах. Сейчас у нас используется около 60 устройств для регрессионного тестирования мобильного приложения Почты Mail.Ru. В среднем они тестируют около 20 сборок приложения ежедневно. Для каждой сборки выполняется около 600 UI-тестов и более 3500 unit-тестов.



Автотесты доступны круглосуточно — они экономят очень много времени тестировщиков и позволяют нам выпускать качественное приложение. Без них мы бы тестировали каждую сборку 36 часов (с учетом ожидания) или примерно 13 часов без ожидания. Вместе со сборкой, актуализацией переводов, при рабочей загрузке агентов с автотестами тестирование в среднем занимает 1.5 часа, что ежедневно позволяет нам экономить недели работы тестировщиков.



Мы рассмотрим, как всё делать с самого начала тем, кто занимается написанием автотестов, а не инфраструктурой: начиная от покупки телефона, его перепрошивки и заканчивая созданием docker-контейнеров, внутри которых будет доступен телефон для автотестов.



Какие телефоны выбрать для автотестов на Андроиде?





Когда Android только-только становился популярным, у разработчиков тестов был выбор из двух зол: покупать дорогой зоопарк телефонов либо работать с медленными и глючными виртуалками. Сегодня всё несколько проще, на рынке появились дешёвые аппараты «эконом»-класса, а виртуальный Андроид обзавёлся образом для x86 и HAXM. Однако выбор всё ещё остался, многие предпочитают для автотестов виртуальные машины, но телефоны уже стали вполне доступной опцией даже для скромного бюджета на автотестирование. Так как же выбрать телефон для регрессионных автотестов и какое оборудование ещё нужно, чтобы всё вместе оно могло работать 24/7?



Рынок телефонов очень большой — глаза разбегаются. Какие же критерии выставить при выборе телефона? У меня после череды проб и ошибок вышел такой список (цену на аппарат опускаю, с ней, надеюсь, всё понятно):




  1. Есть возможность получить права root.

  2. Есть возможность анлока boot-раздела телефона.

  3. На телефоне стоит версия Андроида, максимально близкая к стоковой, или подобные можно установить (чтобы не пришлось лопатить кучу вариантов теста под разные интерфейсы).

  4. Оперативная память на телефоне желательно должна быть размером от 1 Гб (можно работать и на меньшей, но, даже если тесты написаны стабильно, различные проверки отображения «тяжёлых» объектов на телефоне с низкой оперативной памятью окажутся долгими).

  5. Совсем здорово, если у телефона будет долгий саппорт от производителя/пользователей, тогда у нас остаётся шанс продлить ему жизнь новыми версиями ОС.



Основная часть критериев достаточно прозрачна. Если окажется, что на телефоне что-то работает не так, то мы должны хотя бы иметь шанс заставить это работать сами. :) К сожалению, большая часть критериев — это не те вещи, о которых можно спросить продавца при покупке, поэтому в первую очередь наш путь лежит на forum.xda-developers.com и 4pda.ru/forum, где о рыночной модели можно узнать все подробности. Плюс ко всем перечисленным критериям, если модель уже долго продаётся, обращайте на форумах внимание на отзывы о браке и времени ресурса памяти и батареек, без них ваше устройство превратится в тыкву. Проблемы экрана, кнопок, корпуса, динамиков и прочего, что обычно интересует пользователя, вас, как правило, пугать не должны: телефон прекрасно будет работать с браком этих элементов, хотя всё зависит от специфики проекта.



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



1. Модель телефона имеет кучу региональных подвидов, при этом только на части из них можно получить рут или разлочить бутлоадер. Мало того что наткнуться на российский сертифицированный телефон в неофициальном магазине сложно — серые и белые телефоны выглядят одинаково, — так ещё и многие продавцы или их поставщики перепрописывают названия моделей, характеристики железа, регионы и даже версии операционных систем. Вполне возможен случай, когда внутри «Настроек» в Андроиде вы видите одну модель, внутри бутлоадера другую, а в шелле, когда набираете getprop и получаете айдишники, — третью. Просто телефон прошёл пару рук и пару регионов до вас. Сначала его хозяином был пользователь Веризона из Южной Дакоты, потом тот сдал его, в refurbished-состоянии аппарат как-то попал торговцу в Тель-Авиве, который его криво перепрошил на их версию операционной системы, а через ещё какое-то время телефон перекупил продавец в Москве, который уже стал продавать его как новый. Вам привозит его курьер, вы берёте в руки своё новое восьмиядерное перепрошиваемое российское устройство, не подозревая, что это шестиядерный залоченный региональный эксклюзив для контрактных пользователей оператора сотовой связи из США.





Элементы коробки и телефона с «современной» начинкой и высокой ценой, который по внутренним характеристикам оказался перепрошитой младшей моделью от AT&T



2. Один и тот же серийный номер. Здесь определить проблему попроще, но, к сожалению, даже официальные продавцы этим страдают, отсутствие серийного номера — это напасть многих бюджетных девайсов. Если при работе ваших автотестов используется adb, а к машине подключено несколько устройств, нужно либо переписывать код adb (так он увидит только один девайс), либо, если покупка совершалась по критериям выше, вписывать уникальный серийник самому.





Типичные значения серийников у бюджетных телефонов



3. Псевдослучайный MAC-адрес у Wi-Fi-модуля после перезагрузки телефона. Это была довольно серьёзная проблема, потому что мы узнали о ней, когда я убедился, что «всё хорошо», телефон нам подходит, и мы заказали 20 штук точно таких же. :) В процессе работы автотестов телефоны иногда перезагружаются, через какое-то время тесты начали падать из-за отсутствия доступа к сети по Wi-Fi, хотя всё при этом выглядело нормально: соединение с сетью было и после включения/выключения Wi-Fi-модуля всё работало корректно. Просто после ребутов в какой-то момент у пары телефонов оказывался одинаковый MAC, Wi-Fi-точка доступа же пускала только последний присоединившийся. На тех телефонах, где в итоге генерился MAC-адрес, я, к сожалению, не нашёл, пришлось в загрузочном разделе поместить скрипт, который устанавливал его насильно на уникальный.





Телефон демонстрирует чудеса spoofing’а из коробки



Тем не менее, если соблюдать при выборе телефона перечисленные выше критерии, эти проблемы не должны быть фатальными — всё это можно исправить руками и заставить телефон работать как нужно.



Кроме телефонов, для запуска автотестов понадобится сам компьютер и USB-хабы, тут тоже есть несколько нюансов. Постоянно работающим телефонам нужно хорошее питание (минимум 0,5 А на устройство, лучше больше), многие хабы на рынке идут со слабыми адаптерами и никак не рассчитаны на то, что в каждый порт будет подключён постоянно работающий телефон. С планшетами ещё сложнее, девятидюймовые планшеты при постоянной работе разряжаются, экран слишком большой, приходится выбирать из семидюймовых. Из практики у нас вышло, что на адаптер в 4 А можно подключить 6–7 телефонов (в зависимости от их загрузки работой), т. е. большая часть многопортовых хабов с характеристиками типа «адаптер на 3 А, 20 USB-портов», мягко говоря, бесполезны. Самые крутые — серверные решения, но цена у них зашкаливает, так что ограничимся пользовательским рынком. Чтобы телефоны не разряжались, стоит брать хабы на четыре порта с питанием в 3 А, либо хабы на шесть портов с питанием на 4 А. Если есть хабы с хорошим питанием, но с большим количеством портов, — часть портов можно просто не использовать.



Готовим телефон к работе



Давайте для примера возьмём одну модель телефона, решим одну из проблем его операционной системы, а дальше попробуем собрать эти устройства в примитивный тестовый стенд для автотестов. Телефон сам по себе дешёвый и хороший, но с некоторыми недостатками (описанными выше). В частности, у этих телефонов одинаковый iSerial, adb видит только одно устройство. :( Совсем везде на телефоне его менять не будем, но сделаем так, чтобы adb отдельные телефоны отличал.



Для этого нам нужно будет перепрошить у телефона boot-раздел и установить на устройстве кастомный раздел восстановления — так вы сможете уберечься от неудачных экспериментов. У наших телефонов стоит МТ6580, т. е. процессор фирмы Mediatek, значит, для перепрошивки можно использовать SP Flash Tool. Ещё нужны готовый образ recovery.img и scatter-файл устройства. Почти для всех устройств их можно найти в интернете, на тех же самых ресурсах XDA и 4PDA, но при желании recovery можно перекомпилировать для своего устройства, взяв за основу TWRP, а scatter-файл создать самому. В любом случае берём наши готовые файлы и перепрошиваем:







После установки раздела восстановления сохраните через него бэкап boot-раздела и переместите его к себе на машину, обычно в этом разделе располагаются конфигурационные файлы ОС. Чтобы захардкодить свой iSerial, нужно распаковать образ загрузочного раздела телефона, это можно сделать с помощью Android Image Kitchen. Запускаем unpackimg.sh и получаем распакованный образ в папке ramdisk:







Здесь много init-файлов, в которых указываются различные переменные, в том числе и серийный номер.







Находим файл, где устанавливается серийный номер ${ro.serialno}, и заменяем его на свой номер, например 999222333019:



find ramdisk/ -maxdepth 1 -name "init.mt*" -exec sed -i 's/${ro.serialno}/999222333019/g' {} +


Запаковываем образ обратно с помощью repackimg.sh, перекидываем его на телефон и устанавливаем с помощью кастомного рекавери. Теперь adb будет отличать устройства, нам остаётся включить режим разработчика на телефоне и разрешить debug в меню разработчика. Любые подобные проблемы можно решать точно таким же путём, практически всё в телефоне можно перепрошить или поправить, если этого потребуют задачи тестирования.



Настройка тестовой машины



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



При заказе/сборке машины, к которой будут подключены телефоны, есть специфика. Кроме стандартных HDD/RAM/CPU, нужно обратить внимание на количество USB-контроллеров на материнской плате и поддерживаемый протокол USB. Телефоны, работающие на USB 3.0 (xHCI), могут существенно ограничить максимальное количество устройств на машине (обычно 8 на контроллер, в итоге 16 устройств на машину с двумя контроллерами), поэтому стоит проверить, есть ли возможность его отключить и использовать только EHCI. Такие опции есть в биосе или ОС, лучше всего насильно отключить xHCI в биосе, если вам не нужны высокоскоростные устройства.



Создаём контейнер для телефона



Если нужно, чтобы слейв / агент системы интеграции работал с отдельным телефоном, то их следует как-то разделить. У нас агенты запускаются в отдельных docker-контейнерах, каждому из которых доступно по одному устройству, — так мы можем распределять задачи в CI на отдельные устройства, а точнее на их возможности (например, контейнер с планшетом может выполнять тесты, для которых требуется широкая диагональ экрана, а контейнер с телефоном — тесты, для которых нужна возможность принимать SMS-сообщения). Пример установки и настройки системы на Ubuntu описан далее. Устанавливаем сам Docker:



sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
echo 'deb https://apt.dockerproject.org/repo <версия ubuntu> main' >> /etc/apt/sources.list.d/docker.list
sudo apt-get update
sudo apt-get install docker-engine


В качестве сторадж-драйвера будем использовать overlayFS (работает быстрее дефолтного):



echo 'DOCKER_OPTS="-s overlay"' >> /etc/default/docker


Создаем dockerfile, из которого будем делать образы. Добавим в него Android SDK:



FROM ubuntu:trusty
ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update -y && \
apt-get install -y software-properties-common && \
add-apt-repository ppa:webupd8team/java -y && \
apt-get update -y && \
echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \
apt-get install -y oracle-java8-installer && \
apt-get remove software-properties-common -y && \
apt-get autoremove -y && \
apt-get clean
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
ENV ANT_VERSION 1.9.4

RUN cd && \
wget -q http://archive.apache.org/dist/ant/binaries/apache-ant-${ANT_VERSION}-bin.tar.gz && \ tar -xzf apache-ant-${ANT_VERSION}-bin.tar.gz && \ mv apache-ant-${ANT_VERSION} /opt/ant && \ rm apache-ant-${ANT_VERSION}-bin.tar.gz

ENV ANT_HOME /opt/ant
ENV PATH ${PATH}:/opt/ant/bin

ENV ANDROID_SDK_VERSION r24.4.1
ENV ANDROID_BUILD_TOOLS_VERSION 23.0.3

RUN dpkg --add-architecture i386 && \
apt-get update -y && \
apt-get install -y libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 && \
rm -rf /var/lib/apt/lists/* && \
apt-get autoremove -y && \
apt-get clean

ENV ANDROID_SDK_FILENAME android-sdk_${ANDROID_SDK_VERSION}-linux.tgz
ENV ANDROID_SDK_URL http://dl.google.com/android/${ANDROID_SDK_FILENAME}
ENV ANDROID_API_LEVELS android-15,android-16,android-17,android-18,android-19,android-20,android-21,android-22,android-23
ENV ANDROID_HOME /opt/android-sdk-linux
ENV PATH ${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
RUN cd /opt && \
wget -q ${ANDROID_SDK_URL} && \
tar -xzf ${ANDROID_SDK_FILENAME} && \
rm ${ANDROID_SDK_FILENAME} && \
echo y | android update sdk --no-ui -a --filter tools,platform-tools,${ANDROID_API_LEVELS},build-tools-${ANDROID_BUILD_TOOLS_VERSION}

###Добавим файл системы интеграции, это может быть слейв дженкинса, агент Bamboo и т. п., в зависимости от того, с чем вы работаете
ADD moyagent.sh /agentCI/


В докерфайл также можно добавить все необходимые библиотеки и файлы, которыми будет пользоваться агент системы интеграции. Соберём dockerfile:



docker build .


Теперь у нас есть образ с Android SDK, осталось сделать так, чтобы он видел только одно устройство. Для этого будем цеплять его через симлинк c помощью udev:



echo ‘"SUBSYSTEM=="usb", ATTRS{serial}=="$DEVICE_SERIAL", SYMLINK+="androidDevice1"’ >> /etc/udev/rules.d/90-usb-symlink-phones.rules


Вместо $DEVICE_SERIAL вписываем наш свежепрошитый серийник. Перезапускаем определение правил устройств:



udevadm control --reload
udevadm trigger


Теперь в пути /dev/androidDevice1 у нас будет симлинк на устройство, осталось передать его в контейнер при запуске:



docker run -i -t --rm --device=/dev/androidDevice1:/dev/bus/usb/001/1 android-docker-image:latest adb devices


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



docker run -i -t --rm --device= /dev/androidDevice1:/dev/bus/usb/001/1 android-docker-image:latest /bin/sh /agentCI/moyagent.sh


Кстати, ключ --device стал работать с симлинками относительно недавно (master-ветка на Гитхабе), до этого приходилось генерить из симлинка realpath c помощью скрипта и уже его передавать Докеру, так что если у вас не выходит подключение устройства, то добавьте в udev в параметр RUN+= такой скрипт:



realpath /dev/androidDevice1 | xargs -I linkpath link linkpath /dev/bus/usb/010/1


После этого в старых версиях Docker добавить телефон можно так:



docker run --privileged -v /dev/bus/usb/010/:/dev/bus/usb/100/ -i -t  android-docker-image:latest adb devices


Всё, можно подключать свой слейв к системе интеграции и работать с ним.



Заключение



Физические мобильные устройства в системе интеграции рано или поздно появляются у любого более-менее крупного проекта на Андроиде — неизбежно возникают необходимость покрытия ошибок, нестандартные тестовые случаи или просто фичи, которые требуют реального устройства. Кроме всего этого, устройства не используют ресурсы ваших серверов, так как процессоры и память у них свои, а хост для телефонов не должен быть супермощным, «домашний» десктоп со всем этим вполне справится. Соизмеряйте плюсы и минусы, считайте, что выгоднее, — наверняка в вашей системе автоматизированного тестирования есть место реальным устройствам. Желаю вам поменьше багов и побольше тестового покрытия. :)
Original source: habrahabr.ru.

https://habrahabr.ru/post/306236/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Комментарии (0)КомментироватьВ цитатник или сообщество
Donnarossa

Результаты теста "Сколько баллов ваш ветер?"

Пятница, 22 Июля 2016 г. 22:15 (ссылка)



 






















 


Ветер порывистый


Ваш ветер непостоянен. То он слегка дует, неспешно разглядывая всё вокруг, то вдруг начинает торопиться, сбиваясь с ног и куда-то опаздывая.


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


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


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












 

Метки:   Комментарии (2)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Отчёт с прошедшего 17 июня QA MeetUp

Понедельник, 18 Июля 2016 г. 17:40 (ссылка)





17 июня в Нижнем Новгороде прошла встреча QA MeetUp для всех, кто имеет отношение к сфере тестирования и просто неравнодушных. На встрече выступили целых шесть докладчиков, и мы предлагаем вам посмотреть видеозаписи и презентации их выступлений.



— Никита Макаров, Одноклассники



«API, Облака и зачем это все тестировщику»




Облачные решения уже около пяти лет находятся в числе горячих тем всей IT-индустрии. В них видят потенциал, равно как и ограничения использования. Спикер рассказал и показал, как облако может приносить пользу тестировщику, а также проговорит об API и публичных сервисах.







Видеозапись:

Часть 1 it.mail.ru/video/728

Часть 2 it.mail.ru/video/729



— Юлия Сомова, Mail.Ru Group



«Микросервисный подход реализации приложения на примере автоматизации тестирования проекта Почта Mail.Ru»




В последние несколько лет получил распространение термин «Microservice Architecture», когда приложение строится в виде набора независимых сервисов. Спикер в нескольких словах опишет тему, а затем проиллюстрирует такой тип архитектуры приложения на примере проектов. В докладе речь шла о фундаментальных отличиях данной структуры от монолитной и вытекающих из этого плюсах, проблемах и путях решения, которые были предприняты в компании. Будет затронута тема интеграции с Zephyr и просмотра результатов автотестов.







Видеозапись: it.mail.ru/video/730



— Наталья Чуфырина, Mail.Ru Group



«Как создать команду по автоматизации тестирования»




Существует мнение, что от разработчиков системы автоматизированных тестов требуется высокая квалификация в области разработки программного обеспечения и солидный багаж знаний. Обычно таких людей в команде тестирования не много. Но можно начать работы по качественной автоматизации тестирования, даже не имея такого опыта. В докладе речь пойдет о:




  • отборе рекрутов в программу обучения автоматизации тестирования;

  • первичном пороге для вхождения в рекруты;

  • составлении учебной программы;

  • промежуточном контроле и испытаниях;

  • начале работы над реальными проектами;

  • подводных камнях и ошибках, которые можно допустить.



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







Видеозапись:

Часть 1 it.mail.ru/video/733

Часть 2 it.mail.ru/video/734



— Алексей Халайджи, Mail.Ru Group



«Как мы автоматизируем UI-тестирование в iOS Почте Mail.Ru»




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







Видеозапись:

Часть 1 it.mail.ru/video/735

Часть 2 it.mail.ru/video/736



— Максим Богуславский, Banki.ru



«Как вырастить в себе автоматизатора и разработчика»




Многие тестировщики по той или иной причине задумываются о том, чтобы начать писать автотесты. Доклад ориентирован на тех, кто хочет попробовать изучить автоматизацию, либо пробовал, но не справился. Почему у кого-то получилось, а у кого-то нет? Какие навыки и личные качества могут помочь нам в этом или помешать? Стоит ли пытаться? В своем докладе Максим постарался дать ответ на эти вопросы.







Видеозапись:

Часть 1 it.mail.ru/video/731

Часть 2 it.mail.ru/video/732



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




  • о том, с чего начать автоматизацию тестирования;

  • о том, что делает автоматизированные тесты выгодными;

  • о том, как превратить точечное написание автоматизирвоанных тестов в стройный конвейер с отлаженными процессами;

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



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







Видеозапись: it.mail.ru/video/738
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/305862/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество

Следующие 30  »

<тестирование - Самое интересное в блогах

Страницы: [1] 2 3 ..
.. 10

LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
О проекте: помощь|контакты|разместить рекламу|версия для pda