понедельник, 18 мая 2015 г.

Java Date Format

Java Date Format

Просто справочный пост про форматы дат.
Конструктор по умолчанию использует паттерн времени и формат символов по умолчанию для текущей локализации. То есть, для русской локализации стандартным паттерном времени является паттерн "dd.MM.yy HH:mm".
Конструктор SimpleDateFormat(String pattern) принимает паттерн даты, в котором будет отдавать результат метод format(). В примере мы использовали паттерн "dd MMMM", который требует от format() вывести дату в следующем формате: "две цифры дня месяца" + "пробел" + "название месяца". В данном случае используется название месяца по умолчанию для текущей локализации, т.е., "Февраль".
Конструктор SimpleDateFormat("dd MMMM", myDateFormatSymbols ) аналогичен предыдущему за исключением того, что название месяца используется не по умолчанию, а те, которые возвращает переменная myDateFormatSymbols. В свою очередь, в переменной myDateFormatSymbols мы переопределили метод getMonths() чтобы он возвращал названия месяцев с прописной буквы и в родительном падеже.
Конструктор SimpleDateFormat("dd MMMM", Locale.ENGLISH) аналогичен конструктору SimpleDateFormat(String pattern), но использует заданную локализацию. В нашем случае это английская локализация Locale.ENGLISH.
Рассмотрим подробно параметры, принимаемые классом SimpleDateFormat в качестве паттерна даты.
СимволЧто означаетПример
Gэра (в английской локализации - AD и BC)н.э.
yгод (4-х значное число)2012
yyгод (последние 2 цифры)12
yyyyгод (4-х значное число)2012
Mномер месяца без лидирующих нулей2
MMномер месяца (с лидирующими нулями если номер месяца < 10)02
MMMчетырех буквенное сокращение месяца в русской локализации и трех буквенное - в английской (Feb)фев
MMMMполное название месяца (в английской локализации - February)Февраль
wнеделя в году без лидирующих нулей7
wwнеделя в году с лидирующими нулями07
Wнеделя в месяце без лидирующих нулей2
WWнеделя в месяце с лидирующим нулем (если это необходимо)02
Dдень в году38
dдень месяца без лидирующих нулей7
ddдень месяца с лидирующими нулями07
Fдень недели в месяце без лидирующих нулей1
FFдень недели в месяце с лидирующими нулями01
Eдень недели (сокращение)Вт
EEEEдень недели (полностью)вторник
aAM/PM указательAM
Hчасы в 24-часовом формате без лидирующих нулей6
HHчасы в 24-часовом формате с лидирующим нулем06
kколичество часов в 24-часовом формате18
Kколичество часов в 12-часовом формате6
hвремя в 12-часовом формате без лидирующих нулей6
hhвремя в 12-часовом формате с лидирующим нулем06
mминуты без лидирующих нулей32
mmминуты с лидирующим нулем32
sсекунды без лидирующих нулей11
ssсекунды с лидирующим нулем11
Sмиллисекунды109
zчасовой поясEET
Zчасовой пояс в формате RFC 822+0200
'символ экранирования для текста'Date='
''кавычка'o''clock'
Рассмотрим несколько примеров паттернов даты и времени, которые представлены в официальной документации. Русская локализация:
Паттерн даты и времениРезультат
"e;yyyy.MM.dd G 'at' HH:mm:ss z"e;2012.02.07 н.э. at 16:51:35 EET
"e;EEE, MMM d, ''yy"e;Вт, фев 7, '12
"e;h:mm a"e;4:51 PM
"e;hh 'o''clock' a, zzzz"e;04 o'clock PM, Eastern European Time
"e;K:mm a, z"e;4:51 PM, EET
"e;yyyyy.MMMMM.dd GGG hh:mm aaa"e;02012.Февраль.07 н.э. 04:51 PM
"e;EEE, d MMM yyyy HH:mm:ss Z"e;Вт, 7 фев 2012 16:51:35 +0200
"e;yyMMddHHmmssZ"e;120207165135+0200
Английская локализация:
Паттерн даты и времениРезультат
"e;yyyy.MM.dd G 'at' HH:mm:ss z"e;2012.02.07 AD at 16:55:57 EET
"e;EEE, MMM d, ''yy"e;Tue, Feb 7, '12
"e;h:mm a"e;4:55 PM
"e;hh 'o''clock' a, zzzz"e;04 o'clock PM, Eastern European Time
"e;K:mm a, z"e;4:55 PM, EET
"e;yyyyy.MMMMM.dd GGG hh:mm aaa"e;02012.February.07 AD 04:55 PM
"e;EEE, d MMM yyyy HH:mm:ss Z"e;Tue, 7 Feb 2012 16:55:57 +0200
"e;yyMMddHHmmssZ"e;120207165557+0200

вторник, 31 марта 2015 г.

Java Client WebSockets


Java Client WebSockets

Собственно решил сделать небольшую заметку про websocketы,а точнее реализация их клиентов на Java,серверной части тут не будет(она особо нам и не нужна для наших целей),
зато будут 2 реализации,кому какая больше нравится.
Итак,коротко что такое WebSocket:
WebSocket — протокол полнодуплексной связи поверх TCP-соединения, предназначенный для обмена сообщениями между браузером и веб-сервером в режиме реального времени.
Можно даже не до конца понимать определение из википедии,чтобы понять насколько широкие горизонты в разработке и тестировании открывает эта технология.
Сейчас напишем пару клиентских программ использующих вебсокет для соединения с сервером.
1й варинт.
Добавляем в pom.xml

 
        
            javax.websocket
            javax.websocket-client-api
            1.0
        
        
            org.glassfish.tyrus
            tyrus-client
            1.1
        
        
            org.glassfish.tyrus
            tyrus-container-grizzly
            1.1
        

И код самого клиента

 
@ClientEndpoint(configurator = WebSocketClientEndpoint.Configurator.class)
public class WebSocketClientEndpoint {
    private Logger logger = Logger.getLogger(WebSocketClientEndpoint.class);
    Session userSession = null;
    private MessageHandler messageHandler;

    public static class Configurator extends javax.websocket.ClientEndpointConfig.Configurator {
        static String cookiesConf;

        public static void addCookie(String cookies) {
            cookiesConf = cookies;
        }

        @Override
        public void beforeRequest(Map> headers) {
            headers.put("Cookie", Collections.singletonList(cookiesConf));
            super.beforeRequest(headers);
        }
    }

    public WebSocketClientEndpoint(String host, String port) {
        try {
            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
            container.connectToServer(this, URI.create("ws://" + host + ":" + port));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @OnError
    public void onError(Throwable t) {
        t.printStackTrace();
    }

    /**
     * Callback hook for Connection open events.
     *
     * @param userSession the userSession which is opened.
     */
    @OnOpen
    public void onOpen(Session userSession) {
        logger.info("Opening WS");
        this.userSession = userSession;

    }

    /**
     * Callback hook for Connection close events.
     *
     * @param userSession the userSession which is getting closed.
     * @param reason      the reason for connection close
     */
    @OnClose
    public void onClose(Session userSession, CloseReason reason) {
        logger.info("Closing WS");
        this.userSession = null;
    }

    /**
     * Callback hook for Message Events. This method will be invoked when a client send a message.
     *
     * @param message The text message
     */
    @OnMessage
    public void onMessage(String message) {
        if (this.messageHandler != null) this.messageHandler.handleMessage(message);
    }

    /**
     * register message handler
     */
    public WebSocketClientEndpoint addMessageHandler(MessageHandler msgHandler) {
        this.messageHandler = msgHandler;
        return this;
    }

    /**
     * Send a message.
     *
     * @param message
     */
    public WebSocketClientEndpoint sendMessage(String message) {
        this.userSession.getAsyncRemote().sendText(message);
        if (this.messageHandler != null) this.messageHandler.handleMessage(message);
        return this;
    }


    public interface MessageHandler {
        void handleMessage(String message);
    }
}

И пользуемся им как то так:

 
     WebsocketClientEndpoint clientEndPoint = new WebsocketClientEndpoint(new URI("ws://test.dev:8080"));
            // add listener
            clientEndPoint.addMessageHandler(message -> System.out.println(message));
            // send message to websocket
            clientEndPoint.sendMessage("{'event':'Hello world!'}");


Вроде удобно,просто и быстро.Но мне понадобилась поддержка cookie и  в данной реализации это создает определенные сложности(вроде статического класса конфигуратора),так что я использовал 2й вариант на jetty.
Добавляем в pom.xml


 

        
            org.eclipse.jetty.aggregate
            jetty-all-server
            8.1.16.v20140903
        
        
            org.eclipse.jetty.websocket
            websocket-client
            9.2.10.v20150310
        

И код самого клиента:

 
public class ClientWebSocket {
    private Logger logger = Logger.getLogger(ClientWebSocket.class);
    private WebSocket.Connection connection;
    private WebSocketClient client;
    private WebSocketClientFactory factory;

    ClientWebSocket() {
        factory = new WebSocketClientFactory();
        try {
            factory.start();
        } catch (Exception e) {
            logger.info("Factory start problem");
        }
        client = new WebSocketClient(factory);
    }

    public ClientWebSocket open(String uri) {
        try {
            Future connectionFuture = client.open(URI.create(uri), new WebSocket.OnTextMessage() {
                @Override
                public void onMessage(String s) {
                    logger.info(s);
                }

                @Override
                public void onOpen(Connection connection) {
                    logger.info("Opening WS");
                }

                @Override
                public void onClose(int i, String s) {
                    logger.info("Closing WS");
                }
            });
            try {
                this.connection = connectionFuture.get();
            } catch (InterruptedException | ExecutionException e) {
                logger.info("Cant get connection ws");
            }
        } catch (IOException e) {
            logger.info("IO exception with open ws");
        }
        return this;

    }

    public ClientWebSocket addCookies(String name, String value) {
        client.getCookies().put(name, value);
        return this;
    }

    public ClientWebSocket sendMessage(String mess) {
        try {
            connection.sendMessage(mess);
        } catch (Exception e) {
            logger.info("Plz open the connection");
        }
        return this;
    }

    public ClientWebSocket closeConnection() {
        try {
            connection.close();
            factory.stop();
        } catch (Exception e) {
            logger.info("Close connection error");
        }
        return this;
    }
}

И используем его как то так:

 
 String uri = "ws://test.dev:8080";
        ClientWebSocket client = new ClientWebSocket();
        client.addCookies("_user_id", "111111").open(uri).sendMessage("{'event':'Hello world!'}").closeConnection();

Вот так все просто.

четверг, 15 января 2015 г.

Java Annotations

Java Annotations

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

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

Все вроде как просто и делается так же просто.
Делаем простенькую аннотацию

 
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IsKnownBug {
    public String getBugUrl();

    public String getBugDescription() default "";
}

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


 
   @Override
    public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
            if (method.getTestMethod().getMethod().getAnnotation(IsKnownBug.class) != null && testResult.getStatus() == ITestResult.FAILURE) {
                makeScreenshot(testResult.getName());
                IsKnownBug clazz = testResult.getMethod().getMethod().getAnnotation(IsKnownBug.class);
                Assert.fail(clazz.getBugUrl() + " " + clazz.getBugDescription());
            }
            }
        }

Сам тест помеченный аннотацией будет выглядеть как то так:


 
  @IsKnownBug(getBugUrl = "http://jira.test.ru/browse/TEST-7583", getBugDescription = "IMORTANT BUG")
    @Test(description = "check elements with online after filter on the main page")
    public void checkElementsWithOnlineAfterFilter(Class page) {
    }

Ну и в отчете это будет выглядеть как то так


Вот и все.Всем спасибо.

пятница, 29 августа 2014 г.

Load testing with Amazon

Использование EC2 Amazon для нагрузочного тестирования

Думаю, что тут все просто.Не всегда нам хватает своих машин или своей ширины канала для нагрузочного тестирования.
А быстро нам все это предоставить не всегда возможно,но есть выход что с этим делать.
Можно воспользоваться EC2 Amazon.
Сервис который предоставит нам до 10 микро инстансов,на удобной нам системе и бесплатно(правда только первый год,но нам этого хватит)

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

Важно!-Не нужно заходить на машину и настраивать iptables,как делал сначала я.Все это настраиваться в UI Instance в категории Security Groups.

3.Настраиваем доступы следующим образом


4.После этого мы уже почти закончили)
Сетапим Jmeter и запускаем на машинах jmeter-server
Запускаем примерно вот так

jmeter-server -Dserver.rmi.localport=2048 -Djava.rmi.server.hostname=`curl -s http://169.254.169.254/latest/meta-data/public-ipv4`

На всякий случай объясню,что мы тут делаем.
Мы биндим RMI на 2048 порт и запускаем сервер с публичным IP который нам предоставил EC2

5.Нам понадобится ssh туннели,кто не в курсе как это и что это лезем сюда.

ssh -R11099:localhost:11099 ...(user@ip)

ssh -i yourkey.pem -R 11099:localhost:11099 ec2-user@54.213.155.162

6.На основной машине запускаем Jmeter следующим образом

jmeter -Dclient.rmi.localport=11099 -Djava.rmi.server.hostname=localhost 

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

Кстати скопировать на инстанс проще всего как то так 

rsync -azvv --progress -e "ssh -i pathtopem.pem" target_folder ec2-user@52.88.37.176:destination_folder

Вот собственно и все.
Всем спасибо.