Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
667 / 213 / 88
Регистрация: 21.07.2016
Сообщений: 1,036
Записей в блоге: 2
1

Тестирование клиент-серверного приложения без Thread.Sleep ?

02.01.2018, 16:35. Показов 1591. Ответов 3
Метки нет (Все метки)

Есть пока что небольшой вебсокет-сервер.
При покрытии этого сервера NUnit-тестами передо мной встал вопрос: а как собственно правильно написать тесты? Ведь приложение то не однопоточное и не синхронное...

Первое что приходит в голову это использование Thread.Sleep:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class ServerTest
{
    string ResponseFromMyServer { get; set; }
    Server MyServer { get; set; }
    WebSocket4Net.WebSocket MyClient { get; set; }
 
    [Test]
    public void Test_Authorization_SuccessAndFailure()
    {
        MyClient.MessageReceived += new EventHandler<WebSocket4Net.MessageReceivedEventArgs>(websocket_MessageReceived);
        Client.SendMessageToServer(message, server);
        for (var i = 0; i < 50 && ResponseFromMyServer == null; ++i)
        {
            System.Threading.Thread.Sleep(100);
        }
        Assert.AreEqual(expected, ResponseFromMyServer);
    }
 
    private void websocket_MessageReceived(object sender, WebSocket4Net.MessageReceivedEventArgs args)
    {
        ResponseFromMyServer = args.Message;
    }
}
Сам по себе подход мне не нравится, да и лишние задержки меня тоже не устраивают.
Каким образом можно тестировать подобные вещи?


Полный код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using System;
using NUnit.Framework;
 
namespace WebSocketServer.Tests
{
    [TestFixture]
    public class ServerTest
    {
        const string _hostname = "localhost";
        const int _port = 8811;
        const string _protocol = "ws";
 
        string ResponseFromMyServer { get; set; }
        Server MyServer { get; set; }
        WebSocket4Net.WebSocket MyClient { get; set; }
 
        private void websocket_MessageReceived(object sender, WebSocket4Net.MessageReceivedEventArgs args)
        {
            ResponseFromMyServer = args.Message;
        }
 
        [OneTimeSetUp]
        public void RunBeforeAll()
        {
            MyServer = new Server(_hostname, _port, _protocol).Start();
            System.Threading.Thread.Sleep(1000);
 
            MyClient = new WebSocket4Net.WebSocket($"{_protocol}://{_hostname}:{_port}");
            MyClient.MessageReceived += new EventHandler<WebSocket4Net.MessageReceivedEventArgs>(websocket_MessageReceived);
            MyClient.Open();
            System.Threading.Thread.Sleep(3000);
        }
 
        [SetUp]
        public void RunBeforeEach()
        {
            ResponseFromMyServer = null;
        }
 
        [Test]
        public void Test_Authorization_SuccessAndFailure()
        {
            // step 1
            // Тестирование авторизации на успех
            var expected = "{"
                + "\"Type\":\"AUTH_MESSAGE\","
                + "\"Payload\":{\"Message\":null,\"UserName\":\"dailydose\",\"Status\":1}"
                + "}";
            MyClient.Send("{\"Type\": \"AUTH_MESSAGE\", \"Payload\": { \"UserName\": \"dailydose\" }}");
 
            for(var i = 0; i < 50 && ResponseFromMyServer == null; ++i)
            {
                System.Threading.Thread.Sleep(100);
            }
 
            System.Console.WriteLine("expected:" + expected);
            System.Diagnostics.Debug.WriteLine("expected:" + expected);
            System.Console.WriteLine("ResponseFromMyServer:" + ResponseFromMyServer);
            System.Diagnostics.Debug.WriteLine("ResponseFromMyServer:" + ResponseFromMyServer);
            Assert.AreEqual(expected, ResponseFromMyServer);
 
            // step 2
            // Тестирование авторизации другого клиента под уже существующим ником
            ResponseFromMyServer = null;
            var anotherClient = new WebSocket4Net.WebSocket($"{_protocol}://{_hostname}:{_port}");
            anotherClient.MessageReceived += new EventHandler<WebSocket4Net.MessageReceivedEventArgs>(websocket_MessageReceived);
            anotherClient.Open();
            System.Threading.Thread.Sleep(3000);
 
            expected = "{"
                + "\"Type\":\"AUTH_MESSAGE\","
                + "\"Payload\":{\"Message\":\"Error: the user name dailydose is already in use!\",\"UserName\":\"dailydose\",\"Status\":0}"
                + "}";
            anotherClient.Send("{\"Type\": \"AUTH_MESSAGE\", \"Payload\": { \"UserName\": \"dailydose\" }}");
 
            for (var i = 0; i < 50 && ResponseFromMyServer == null; ++i)
            {
                System.Threading.Thread.Sleep(100);
            }
 
            System.Console.WriteLine("expected:" + expected);
            System.Diagnostics.Debug.WriteLine("expected:" + expected);
            System.Console.WriteLine("ResponseFromMyServer:" + ResponseFromMyServer);
            System.Diagnostics.Debug.WriteLine("ResponseFromMyServer:" + ResponseFromMyServer);
            Assert.AreEqual(expected, ResponseFromMyServer);
        }
 
        [Test]
        public void asyncMethodTest()
        {
 
            Assert.Pass("Aee");
        }
    }
}
Добавлено через 2 часа 3 минуты
Вот немного переписал тест, но вопрос всё еще остаётся открытым - Каким образом можно тестировать подобные вещи?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
using System;
using System.Linq;
using NUnit.Framework;
using System.Threading;
 
namespace WebSocketServer.Tests
{
    [TestFixture]
    public class ServerTest
    {
        const string _hostname = "localhost";
        const int _port = 8811;
        const string _protocol = "ws";
 
        string ResponseFromMyServer { get; set; }
        string PreviousResponseFromMyServer { get; set; }
        Server MyServer { get; set; }
        WebSocket4Net.WebSocket MyClient { get; set; }
 
        private void OnReceiveMessageFromServer(object sender, WebSocket4Net.MessageReceivedEventArgs args)
        {
            PreviousResponseFromMyServer = ResponseFromMyServer;
            ResponseFromMyServer = args.Message;
        }
 
        private void Log<T>(T expected)
        {
            Console.WriteLine("expected:" + expected);
            System.Diagnostics.Debug.WriteLine("expected:" + expected);
 
            Console.WriteLine("PreviousResponseFromMyServer:" + PreviousResponseFromMyServer);
            System.Diagnostics.Debug.WriteLine("PreviousResponseFromMyServer:" + PreviousResponseFromMyServer);
 
            Console.WriteLine("ResponseFromMyServer:" + ResponseFromMyServer);
            System.Diagnostics.Debug.WriteLine("ResponseFromMyServer:" + ResponseFromMyServer);
        }
 
        [OneTimeSetUp]
        public void RunBeforeAll()
        {
            MyServer = new Server(_hostname, _port, _protocol).Start();
            Thread.Sleep(1000);
 
            MyClient = new WebSocket4Net.WebSocket($"{_protocol}://{_hostname}:{_port}");
            MyClient.MessageReceived += new EventHandler<WebSocket4Net.MessageReceivedEventArgs>(OnReceiveMessageFromServer);
            MyClient.Open();
            Thread.Sleep(3000);
        }
 
        [SetUp]
        public void RunBeforeEach()
        {
            PreviousResponseFromMyServer = null;
            ResponseFromMyServer = null;
        }
 
        /// <summary>
        /// Тестирование авторизации на успех
        /// </summary>
        [Test, Order(1)]
        public void Test_Authorization_Success()
        {
            var expected = MyServer.BuildMessage(
                AuthMessage.Type,
                new AuthMessage()
                {
                    UserName = "DailyDose",
                    Status = AuthMessage.StatusCode.SUCCESS
                }
            );
            MyClient.Send(
                MyServer.BuildMessage(
                    AuthMessage.Type,
                    new AuthMessage()
                    {
                        UserName = "DailyDose"
                    }
                )
            );
 
            for (var i = 0; i < 50 && ResponseFromMyServer == null; ++i)
            {
                Thread.Sleep(100);
            }
 
            Log(expected);
            var possibleValues = new[] { PreviousResponseFromMyServer, ResponseFromMyServer };
            Assert.IsTrue(possibleValues.Contains(expected));
        }
 
        /// <summary>
        /// Тестирование авторизации другого клиента под уже существующим ником
        /// </summary>
        [Test, Order(2)]
        public void Test_Authorization_Error()
        {
            var anotherClient = new WebSocket4Net.WebSocket($"{_protocol}://{_hostname}:{_port}");
            anotherClient.MessageReceived += new EventHandler<WebSocket4Net.MessageReceivedEventArgs>(OnReceiveMessageFromServer);
            anotherClient.Open();
            Thread.Sleep(3000);
 
            var expected = MyServer.BuildMessage(
                AuthMessage.Type,
                new AuthMessage()
                {
                    Message = "Error: the user name <DailyDose> is already in use!",
                    UserName = "DailyDose",
                    Status = AuthMessage.StatusCode.ERROR
                }
            );
            anotherClient.Send(
                MyServer.BuildMessage(
                    AuthMessage.Type,
                    new AuthMessage()
                    {
                        UserName = "DailyDose"
                    }
                )
            );
 
            for (var i = 0; i < 50 && ResponseFromMyServer == null; ++i)
            {
                Thread.Sleep(100);
            }
 
            Log(expected);
            Assert.AreEqual(expected, ResponseFromMyServer);
        }
    }
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.01.2018, 16:35
Ответы с готовыми решениями:

Дождаться выполнения Task без Thread.Sleep?
using System; public class Test { public static void Main() { Console.WriteLine(&quot;1&quot;);...

Пример клиент-серверного приложения
Может у кого есть пример клиент-сервера передачи текста от клиента к серверу и наоборот? на...

Создание клиент-серверного приложения
Начал изучать С# подскажите как сделать приложение клиент и сервер для отправки сообщений (не на...

Пример клиент-серверного приложения TCP/IP
Здравствуйте, нужен простой и понятный пример клиент-серверного приложения для передачи данных и...

3
Эксперт .NET
9194 / 6551 / 1071
Регистрация: 21.01.2016
Сообщений: 24,789
02.01.2018, 17:09 2
dailydose, это у вас уже какие-то интеграционные тесты пошли. Вы здесь не только свой код тестируете, но и код библиотеки WebSocket4Net, а так же сетевой стёк, по которому идёт общение. Если так и задумывалось, то ОК. Но если вы хотели только свой код протестировать, то так делать не надо.

Тестируйте отдельно код клиента и код сервера. Прячьте за абстракцией сторонние технологии, но с умом.
1
667 / 213 / 88
Регистрация: 21.07.2016
Сообщений: 1,036
Записей в блоге: 2
02.01.2018, 17:20  [ТС] 3
Usaga,
Цитата Сообщение от Usaga Посмотреть сообщение
Вы здесь не только свой код тестируете, но и код библиотеки WebSocket4Net
Я думаю, что эта библиотека достаточно пережила, и её тестировать нет необходимости.
В данном коде она используется как раз-таки, чтобы протестировать мой сервер

Добавлено через 2 минуты
Usaga,
Цитата Сообщение от Usaga Посмотреть сообщение
Тестируйте отдельно код клиента и код сервера.
Клиенты естественно у нас в разных проектах и тестов на них пока нет, но уже приметили chai+mocha для веб-клиента и junit для андроид-клиента
0
Эксперт .NET
9194 / 6551 / 1071
Регистрация: 21.01.2016
Сообщений: 24,789
02.01.2018, 17:22 4
Лучший ответ Сообщение было отмечено dailydose как решение

Решение

dailydose, эмулируйте код "ниже" вашего сервера и код потребитель. Посылайте данные классу сервера напрямую из теста. Если нужно, то вынесите "нижний" уровень в виде абстракции (т.е. спрячьте библиотеку WebSocket4Net за интерфейсом) и заменяйте его mock-ом.
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.01.2018, 17:22

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Нужен пример простейшего клиент-серверного приложения
Добрый день. Прчитал примеры в MSDN, скачал книжку Сетевое программироване, но понять пока нечего...

Работа с сокетами, основы клиент-серверного приложения
Нашел простой пример клиент-серверного приложения на C#: Сервер: // SocketServer.cs using...

Нужен пример клиент-серверного приложения основанный на RPC
Народ, есть у кого пример клиент-серверного приложения основанный на RPC?

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.