Repository: pytorch/ignite

Issue:
[Feature Request]  tqdm_logger update on every epoch instead of every iteration
Currently `tqdm_logger` creates a progress bar for every epoch and updates it on every iteration. I would like to have a single progress bar for the entire run that updates every epoch instead.

Discussion:
vfdev-5: DO NOT MERGE YET. Forgot about #391 
vfdev-5: @drozzy you can check out this version if it works better for you.
Keep in mind that tqdm_notebook has some issue with the layout in some cases: https://github.com/tqdm/tqdm/issues/649
vfdev-5: @anmolsjoshi OK, I'll update the notebooks ASAP
vfdev-5: @anmolsjoshi I updated TextCNN and docstring. Rendering of progressbar in the github is not better.
Just `HBox ...` however inside jupyter notebook we can see the widgets etc... We can leave it like this, IMO

Patch:
diff --git a/.travis.yml b/.travis.yml
index 6f94eb96..d5a52526 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,7 +29,7 @@ before_install: &before_install
   - source activate test-environment
   - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then pip install enum34; fi
   # Test contrib dependencies
-  - pip install tqdm==4.30.0 scikit-learn tensorboardX visdom
+  - pip install tqdm scikit-learn tensorboardX visdom
   # Futures should be already installed via visdom -> tornado -> futures
   # Let's reinstall it anyway to be sure
   - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then pip install futures; fi
diff --git a/examples/notebooks/TextCNN.ipynb b/examples/notebooks/TextCNN.ipynb
index c1e6b429..015e83bc 100644
--- a/examples/notebooks/TextCNN.ipynb
+++ b/examples/notebooks/TextCNN.ipynb
@@ -180,7 +180,7 @@
       "type(train_data[0]) :  <class 'torchtext.data.example.Example'>\n",
       "Attributes of Example :  ['fromCSV', 'fromJSON', 'fromdict', 'fromlist', 'fromtree', 'label', 'text']\n",
       "example.label :  neg\n",
-      "example.text[:10] :  ['my', 'roommates', '&', 'i', 'nearly', 'shorted', 'out', 'our', 'tv', 'from']\n"
+      "example.text[:10] :  ['i', 'sat', 'glued', 'to', 'the', 'screen,', 'riveted,', 'yawning,', 'yet', 'keeping']\n"
      ]
     }
    ],
@@ -228,8 +228,8 @@
       "Attributes of TEXT :  ['dtype', 'dtypes', 'lower', 'numericalize', 'pad', 'postprocessing', 'preprocess', 'preprocessing', 'process', 'sequential', 'tokenize', 'vocab']\n",
       "Attributes of TEXT.vocab :  ['extend', 'freqs', 'itos', 'stoi', 'vectors']\n",
       "First 5 values TEXT.vocab.itos :  ['<unk>', '<pad>', 'the', 'a', 'and']\n",
-      "First 5 key, value pairs of TEXT.vocab.stoi :  {'<unk>': 0, '<pad>': 1, 'the': 2, 'a': 3, 'and': 4}\n",
-      "Shape of TEXT.vocab.vectors.shape :  torch.Size([219779, 100])\n"
+      "First 5 key, value pairs of TEXT.vocab.stoi :  {'derived)': 134015, 'blum,': 120130, 'cartland': 50785, 'eccentric': 4902, 'designs': 6221}\n",
+      "Shape of TEXT.vocab.vectors.shape :  torch.Size([218957, 100])\n"
      ]
     }
    ],
@@ -314,34 +314,23 @@
      "output_type": "stream",
      "text": [
       "batch.label[0] :  tensor(1., device='cuda:0')\n",
-      "batch.text[0] :  tensor([     9,  11344,     10,     20,      8,      2,    432,   1510,      3,\n",
-      "           155,    183,   1179,      4,   1470,    112,     57,    847,      4,\n",
-      "             9,    458,     12,     38,     75,     69,   1160,      2,   2163,\n",
-      "             4,     26,    458,     12,    127,  16064,     13,     93,    131,\n",
-      "            41,     71, 215711,     38,     60,    309,      8,    161,    125,\n",
-      "            12,    671,      2,    250,      7,     10,     20,    998,   2574,\n",
-      "         16171,  10119,  11530,    626,    161,      6,     73,     34,      2,\n",
-      "           769,      2,     81,     82,   2332,      9,    118,      9,  15689,\n",
-      "            13,    256,     20,      7,    866,   9785, 192842,     34,     29,\n",
-      "             2,    165,    292,     50,   1928,  12911,      2,  21507,     29,\n",
-      "            21,   5842,   9545,     44, 131869,     50,   5788,   1981,   1281,\n",
-      "         88677,     15,     27,    928,      6,   4160,    949,     44,  19521,\n",
-      "            50, 118472,      7,    445,  28620,     31,      2,    286,      8,\n",
-      "          5166,     44,    104,    239,     16,  30839,     13,    749,      2,\n",
-      "         22656,     44,     15,     55,     15,     92,     20,    990,    195,\n",
-      "           506,      8,   1005,      9,     14,   1309,      8,      2,    548,\n",
-      "           852,      6,   5760,    125,      2,  60411,    108,     13,   9560,\n",
-      "           271,      7,    372,   3211,   1115,  26899,     41,     71,  20937,\n",
-      "         23786,     16,     21,   1157,      5,  21240,      3,    162,     36,\n",
-      "            41,     62,     30,    104,    101,     97,  85758,   1661,  14580,\n",
-      "             7,    431,     15,  14060,      2,   3905,  17500,   2474,     36,\n",
-      "            41,   2898,      3,  12545,     16,   5788,     34,    122,   1005,\n",
-      "            27,     41,     32,   2591, 152559,    164,     11,    146,    421,\n",
-      "           168,      6,  13810,    461,     18,     34,      2,    187,     22,\n",
-      "          1219,  11836,     13,  63553,     92,   8996,     25,    307,     43,\n",
-      "            10,     20,      4,     67,    112,     44,      3,   4928],\n",
-      "       device='cuda:0')\n",
-      "Lengths of first 10 batches :  [840, 793, 622, 605, 864, 917, 651, 587, 996, 672, 509]\n"
+      "batch.text[0] :  tensor([     9,   1107,    205,     10,     24,      4,    454,     12,     49,\n",
+      "          1271,     12,    346,      3,   2793,      6,   3109,     20,    240,\n",
+      "             4,     79,     76,    210,      7,     61,    653,     50,     25,\n",
+      "            26,      3,    469,    502,    264,    313,      3,    457,  21725,\n",
+      "             6,     73,   1090,     92,     89,      6,    209,     67,     12,\n",
+      "             4,    181,      2,     20,  32092,   4102, 173802,    260,     31,\n",
+      "         16607,      4,     21,   2546,  33723,     69,    748,  44230,     90,\n",
+      "            32,    337,   2438,   1509,   4902, 170285,  21837,      3,  47953,\n",
+      "           342,    260,     31,   1673,  10692,     14,      3,    448,   1018,\n",
+      "          2410,      8,      2,     20,      4,     17,      2,    119,     57,\n",
+      "           474,    215,   1779,     14,  12440,   3661,    260,     31,      2,\n",
+      "          2356,      4,   2333,   8324,  24453,  23239,     16,     41,    208,\n",
+      "           300,    269,    303,      8,      2,     20,    701,      2,    119,\n",
+      "            46,     25,    354,    562,     50,    145,      3,    290,     96,\n",
+      "            10,     30,      7,     17,    929,    469,    502,    819,   2614,\n",
+      "           502,     16,    311,    568,   8498], device='cuda:0')\n",
+      "Lengths of first 10 batches :  [978, 625, 650, 450, 587, 671, 526, 984, 789, 911, 669]\n"
      ]
     }
    ],
@@ -656,16 +645,25 @@
    "source": [
     "### Progress Bar\n",
     "\n",
-    "Next we create an instance of Ignite's progess bar and attach it to the trainer and pass it a key of engine.state.metrics to track. In this case, the progress bar will be tracking engine.state.metrics['loss']"
+    "Next we create an instance of Ignite's progess bar and attach it to the trainer and pass it a key of `engine.state.metrics` to track. In this case, the progress bar will be tracking `engine.state.metrics['loss']`"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 20,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/usr/local/lib/python3.5/dist-packages/tqdm/autonotebook/__init__.py:14: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)\n",
+      "  \" (e.g. in jupyter console)\", TqdmExperimentalWarning)\n"
+     ]
+    }
+   ],
    "source": [
-    "pbar = ProgressBar(persist=True)\n",
+    "pbar = ProgressBar(persist=True, bar_format=\"\")\n",
     "pbar.attach(trainer, ['loss'])"
    ]
   },
@@ -749,7 +747,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 23,
+   "execution_count": 24,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -768,565 +766,478 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 24,
+   "execution_count": 25,
    "metadata": {
     "scrolled": false
    },
    "outputs": [
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [1/20]: [625/625] 100%|██████████, loss=6.57e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 1  Avg accuracy: 0.74 Avg loss: 0.64\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [2/20]: [5/625]   1%|          , loss=6.44e-01 [00:00<00:11]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "fff122f9c62148adac293b981b0c0af6",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
+      "\n",
+      "Training Results - Epoch: 1  Avg accuracy: 0.76 Avg loss: 0.64\n",
       "Validation Results - Epoch: 1  Avg accuracy: 0.73 Avg loss: 0.64\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [2/20]: [625/625] 100%|██████████, loss=5.73e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 2  Avg accuracy: 0.79 Avg loss: 0.55\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [3/20]: [4/625]   1%|          , loss=5.45e-01 [00:00<00:12]"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Validation Results - Epoch: 2  Avg accuracy: 0.77 Avg loss: 0.56\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [3/20]: [625/625] 100%|██████████, loss=4.90e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 3  Avg accuracy: 0.80 Avg loss: 0.48\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [4/20]: [4/625]   1%|          , loss=4.93e-01 [00:00<00:10]"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Validation Results - Epoch: 3  Avg accuracy: 0.78 Avg loss: 0.49\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [4/20]: [625/625] 100%|██████████, loss=4.65e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 4  Avg accuracy: 0.81 Avg loss: 0.44\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [5/20]: [4/625]   1%|          , loss=5.01e-01 [00:00<00:10]"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Validation Results - Epoch: 4  Avg accuracy: 0.80 Avg loss: 0.46\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [5/20]: [625/625] 100%|██████████, loss=4.41e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "ff8745963cce4e799d4e804e427c39b4",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Training Results - Epoch: 5  Avg accuracy: 0.82 Avg loss: 0.42\n"
+      "\n",
+      "Training Results - Epoch: 2  Avg accuracy: 0.79 Avg loss: 0.56\n",
+      "Validation Results - Epoch: 2  Avg accuracy: 0.78 Avg loss: 0.56\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [6/20]: [4/625]   1%|          , loss=4.87e-01 [00:00<00:10]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "e1d758e6ebb44bbaaf63369e0a723040",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Validation Results - Epoch: 5  Avg accuracy: 0.81 Avg loss: 0.44\n"
+      "\n",
+      "Training Results - Epoch: 3  Avg accuracy: 0.80 Avg loss: 0.48\n",
+      "Validation Results - Epoch: 3  Avg accuracy: 0.79 Avg loss: 0.49\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [6/20]: [625/625] 100%|██████████, loss=4.33e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "31b248535085452a9ece3521c0f19704",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Training Results - Epoch: 6  Avg accuracy: 0.83 Avg loss: 0.40\n"
+      "\n",
+      "Training Results - Epoch: 4  Avg accuracy: 0.81 Avg loss: 0.44\n",
+      "Validation Results - Epoch: 4  Avg accuracy: 0.80 Avg loss: 0.45\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [7/20]: [4/625]   1%|          , loss=3.53e-01 [00:00<00:10]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "7370678ac46f475998dc2f874eedda7d",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Validation Results - Epoch: 6  Avg accuracy: 0.81 Avg loss: 0.43\n"
+      "\n",
+      "Training Results - Epoch: 5  Avg accuracy: 0.82 Avg loss: 0.42\n",
+      "Validation Results - Epoch: 5  Avg accuracy: 0.81 Avg loss: 0.43\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [7/20]: [625/625] 100%|██████████, loss=4.19e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "3c533b8a1c594e028be9422ed55a8bbc",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Training Results - Epoch: 7  Avg accuracy: 0.84 Avg loss: 0.39\n"
+      "\n",
+      "Training Results - Epoch: 6  Avg accuracy: 0.83 Avg loss: 0.40\n",
+      "Validation Results - Epoch: 6  Avg accuracy: 0.81 Avg loss: 0.42\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [8/20]: [4/625]   1%|          , loss=4.21e-01 [00:00<00:12]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "1597ea3c65034cc4bbbcb8c013adb96c",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
+      "\n",
+      "Training Results - Epoch: 7  Avg accuracy: 0.84 Avg loss: 0.39\n",
       "Validation Results - Epoch: 7  Avg accuracy: 0.82 Avg loss: 0.41\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [8/20]: [625/625] 100%|██████████, loss=3.95e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 8  Avg accuracy: 0.85 Avg loss: 0.37\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [9/20]: [4/625]   1%|          , loss=4.04e-01 [00:00<00:12]"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Validation Results - Epoch: 8  Avg accuracy: 0.83 Avg loss: 0.41\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [9/20]: [625/625] 100%|██████████, loss=3.93e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 9  Avg accuracy: 0.85 Avg loss: 0.36\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [10/20]: [4/625]   1%|          , loss=3.41e-01 [00:00<00:11]"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Validation Results - Epoch: 9  Avg accuracy: 0.83 Avg loss: 0.40\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [10/20]: [625/625] 100%|██████████, loss=3.82e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 10  Avg accuracy: 0.85 Avg loss: 0.35\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [11/20]: [4/625]   1%|          , loss=3.05e-01 [00:00<00:11]"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Validation Results - Epoch: 10  Avg accuracy: 0.83 Avg loss: 0.39\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [11/20]: [625/625] 100%|██████████, loss=3.71e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 11  Avg accuracy: 0.86 Avg loss: 0.34\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [12/20]: [4/625]   1%|          , loss=3.64e-01 [00:00<00:11]"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Validation Results - Epoch: 11  Avg accuracy: 0.83 Avg loss: 0.38\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [12/20]: [625/625] 100%|██████████, loss=3.47e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 12  Avg accuracy: 0.86 Avg loss: 0.33\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [13/20]: [4/625]   1%|          , loss=4.57e-01 [00:00<00:11]"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Validation Results - Epoch: 12  Avg accuracy: 0.84 Avg loss: 0.38\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [13/20]: [625/625] 100%|██████████, loss=3.48e-01 [00:11<00:00]\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Training Results - Epoch: 13  Avg accuracy: 0.87 Avg loss: 0.32\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [14/20]: [4/625]   1%|          , loss=3.06e-01 [00:00<00:12]"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Validation Results - Epoch: 13  Avg accuracy: 0.84 Avg loss: 0.37\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [14/20]: [625/625] 100%|██████████, loss=3.44e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "a0bad52713dd496fab612d43cbc8f0ba",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Training Results - Epoch: 14  Avg accuracy: 0.87 Avg loss: 0.31\n"
+      "\n",
+      "Training Results - Epoch: 8  Avg accuracy: 0.85 Avg loss: 0.37\n",
+      "Validation Results - Epoch: 8  Avg accuracy: 0.82 Avg loss: 0.40\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [15/20]: [4/625]   1%|          , loss=3.93e-01 [00:00<00:11]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "ed22e1ce816a4aa0b885cc80702860a8",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Validation Results - Epoch: 14  Avg accuracy: 0.84 Avg loss: 0.37\n"
+      "\n",
+      "Training Results - Epoch: 9  Avg accuracy: 0.85 Avg loss: 0.36\n",
+      "Validation Results - Epoch: 9  Avg accuracy: 0.83 Avg loss: 0.39\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [15/20]: [625/625] 100%|██████████, loss=3.24e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "31b84c5326e94efc9fa6b6ac8a176fd1",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Training Results - Epoch: 15  Avg accuracy: 0.88 Avg loss: 0.31\n"
+      "\n",
+      "Training Results - Epoch: 10  Avg accuracy: 0.85 Avg loss: 0.35\n",
+      "Validation Results - Epoch: 10  Avg accuracy: 0.83 Avg loss: 0.38\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [16/20]: [4/625]   1%|          , loss=3.69e-01 [00:00<00:11]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "a231ba4c28a243db868f676c784411c0",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Validation Results - Epoch: 15  Avg accuracy: 0.84 Avg loss: 0.36\n"
+      "\n",
+      "Training Results - Epoch: 11  Avg accuracy: 0.86 Avg loss: 0.34\n",
+      "Validation Results - Epoch: 11  Avg accuracy: 0.83 Avg loss: 0.37\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [16/20]: [625/625] 100%|██████████, loss=3.28e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "5650adc8034e4d3686da74ae4a21aaf5",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Training Results - Epoch: 16  Avg accuracy: 0.88 Avg loss: 0.30\n"
+      "\n",
+      "Training Results - Epoch: 12  Avg accuracy: 0.87 Avg loss: 0.33\n",
+      "Validation Results - Epoch: 12  Avg accuracy: 0.84 Avg loss: 0.37\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [17/20]: [4/625]   1%|          , loss=3.75e-01 [00:00<00:11]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "c6e6108d2fa54175b0fcd57e4af13362",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Validation Results - Epoch: 16  Avg accuracy: 0.84 Avg loss: 0.36\n"
+      "\n",
+      "Training Results - Epoch: 13  Avg accuracy: 0.87 Avg loss: 0.32\n",
+      "Validation Results - Epoch: 13  Avg accuracy: 0.84 Avg loss: 0.36\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [17/20]: [625/625] 100%|██████████, loss=3.10e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "7e2828d9042a4d8a9ec0e189334c7800",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Training Results - Epoch: 17  Avg accuracy: 0.89 Avg loss: 0.29\n"
+      "\n",
+      "Training Results - Epoch: 14  Avg accuracy: 0.87 Avg loss: 0.32\n",
+      "Validation Results - Epoch: 14  Avg accuracy: 0.84 Avg loss: 0.36\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [18/20]: [4/625]   1%|          , loss=2.92e-01 [00:00<00:12]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "379d84a46a1f421990e63821074da8c0",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Validation Results - Epoch: 17  Avg accuracy: 0.84 Avg loss: 0.35\n"
+      "\n",
+      "Training Results - Epoch: 15  Avg accuracy: 0.88 Avg loss: 0.31\n",
+      "Validation Results - Epoch: 15  Avg accuracy: 0.84 Avg loss: 0.35\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [18/20]: [625/625] 100%|██████████, loss=2.99e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "f5e8535883024e9aa3875e77cd3e294a",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Training Results - Epoch: 18  Avg accuracy: 0.89 Avg loss: 0.28\n"
+      "\n",
+      "Training Results - Epoch: 16  Avg accuracy: 0.88 Avg loss: 0.30\n",
+      "Validation Results - Epoch: 16  Avg accuracy: 0.85 Avg loss: 0.34\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [19/20]: [4/625]   1%|          , loss=3.25e-01 [00:00<00:11]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "3c4372380e884c30b4fd25cbfa146d0e",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Validation Results - Epoch: 18  Avg accuracy: 0.85 Avg loss: 0.35\n"
+      "\n",
+      "Training Results - Epoch: 17  Avg accuracy: 0.89 Avg loss: 0.29\n",
+      "Validation Results - Epoch: 17  Avg accuracy: 0.85 Avg loss: 0.34\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [19/20]: [625/625] 100%|██████████, loss=3.15e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "9e1d44194fc7496593d23b24019edc45",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Training Results - Epoch: 19  Avg accuracy: 0.90 Avg loss: 0.27\n"
+      "\n",
+      "Training Results - Epoch: 18  Avg accuracy: 0.89 Avg loss: 0.28\n",
+      "Validation Results - Epoch: 18  Avg accuracy: 0.85 Avg loss: 0.34\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [20/20]: [4/625]   1%|          , loss=3.12e-01 [00:00<00:10]"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "372de51144b746c2a49948d9e2dff360",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Validation Results - Epoch: 19  Avg accuracy: 0.85 Avg loss: 0.34\n"
+      "\n",
+      "Training Results - Epoch: 19  Avg accuracy: 0.90 Avg loss: 0.27\n",
+      "Validation Results - Epoch: 19  Avg accuracy: 0.85 Avg loss: 0.33\n"
      ]
     },
     {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "Epoch [20/20]: [625/625] 100%|██████████, loss=2.82e-01 [00:11<00:00]\n"
-     ]
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "949c2fe98ebc44f9a943697c585f9b83",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "HBox(children=(IntProgress(value=0, max=625), HTML(value='')))"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     },
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
+      "\n",
       "Training Results - Epoch: 20  Avg accuracy: 0.90 Avg loss: 0.26\n",
-      "Validation Results - Epoch: 20  Avg accuracy: 0.85 Avg loss: 0.34\n"
+      "Validation Results - Epoch: 20  Avg accuracy: 0.86 Avg loss: 0.33\n"
      ]
     },
     {
      "data": {
       "text/plain": [
-       "<ignite.engine.engine.State at 0x7f55dcad41d0>"
+       "<ignite.engine.engine.State at 0x7f40aad2c400>"
       ]
      },
-     "execution_count": 24,
+     "execution_count": 25,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1345,9 +1256,9 @@
  ],
  "metadata": {
   "kernelspec": {
-   "display_name": "torchnb3.6",
+   "display_name": "Python 3",
    "language": "python",
-   "name": "torchexamples"
+   "name": "python3"
   },
   "language_info": {
    "codemirror_mode": {
@@ -1359,7 +1270,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.6.8"
+   "version": "3.5.2"
   }
  },
  "nbformat": 4,
diff --git a/ignite/contrib/handlers/tqdm_logger.py b/ignite/contrib/handlers/tqdm_logger.py
index 6b156a68..3ced7f03 100644
--- a/ignite/contrib/handlers/tqdm_logger.py
+++ b/ignite/contrib/handlers/tqdm_logger.py
@@ -1,13 +1,15 @@
 # -*- coding: utf-8 -*-
-try:
-    from tqdm import tqdm
-except ImportError:
-    raise RuntimeError("This contrib module requires tqdm to be installed")
+import numbers
+import warnings
+
+import torch
 
 from ignite.engine import Events
 
+from ignite.contrib.handlers.base_logger import BaseLogger, BaseOutputHandler
+
 
-class ProgressBar(object):
+class ProgressBar(BaseLogger):
     """
     TQDM progress bar handler to log training progress and computed metrics.
 
@@ -69,19 +71,43 @@ class ProgressBar(object):
         When adding attaching the progress bar to an engine, it is recommend that you replace
         every print operation in the engine's handlers triggered every iteration with
         ``pbar.log_message`` to guarantee the correct format of the stdout.
+
+    Note:
+        When using inside jupyter notebook, `ProgressBar` automatically uses `tqdm_notebook`. For correct rendering,
+        please install `ipywidgets <https://ipywidgets.readthedocs.io/en/stable/user_install.html#installation>`_.
+        Due to `tqdm notebook bugs <https://github.com/tqdm/tqdm/issues/594>`_, bar format may be needed to be set
+        to an empty string value.
+
     """
 
+    events_order = [
+        Events.STARTED,
+        Events.EPOCH_STARTED,
+        Events.ITERATION_STARTED,
+        Events.ITERATION_COMPLETED,
+        Events.EPOCH_COMPLETED,
+        Events.COMPLETED
+    ]
+
     def __init__(self, persist=False,
                  bar_format='{desc}[{n_fmt}/{total_fmt}] {percentage:3.0f}%|{bar}{postfix} [{elapsed}<{remaining}]',
                  **tqdm_kwargs):
+
+        try:
+            from tqdm.autonotebook import tqdm
+        except ImportError:
+            raise RuntimeError("This contrib module requires tqdm to be installed. "
+                               "Please install it with command: \n pip install tqdm")
+
+        self.pbar_cls = tqdm
         self.pbar = None
         self.persist = persist
         self.bar_format = bar_format
         self.tqdm_kwargs = tqdm_kwargs
 
-    def _reset(self, engine):
-        self.pbar = tqdm(
-            total=len(engine.state.dataloader),
+    def _reset(self, pbar_total):
+        self.pbar = self.pbar_cls(
+            total=pbar_total,
             leave=self.persist,
             bar_format=self.bar_format,
             **self.tqdm_kwargs
@@ -91,35 +117,11 @@ class ProgressBar(object):
         self.pbar.close()
         self.pbar = None
 
-    def _update(self, engine, metric_names=None, output_transform=None):
-        if self.pbar is None:
-            self._reset(engine)
-
-        desc = self.tqdm_kwargs.get("desc", "Epoch")
-        if engine.state.max_epochs > 1:
-            desc += " [{}/{}]".format(engine.state.epoch, engine.state.max_epochs)
-        self.pbar.set_description(desc)
-
-        metrics = {}
-        if metric_names is not None:
-            if not all(metric in engine.state.metrics for metric in metric_names):
-                self._close(engine)
-                raise KeyError("metrics not found in engine.state.metrics")
-
-            metrics.update({name: '{:.2e}'.format(engine.state.metrics[name]) for name in metric_names})
-
-        if output_transform is not None:
-            output_dict = output_transform(engine.state.output)
-
-            if not isinstance(output_dict, dict):
-                output_dict = {"output": output_dict}
-
-            metrics.update({name: '{:.2e}'.format(value) for name, value in output_dict.items()})
-
-        if metrics:
-            self.pbar.set_postfix(**metrics)
-
-        self.pbar.update()
+    @staticmethod
+    def _compare_lt(event1, event2):
+        i1 = ProgressBar.events_order.index(event1)
+        i2 = ProgressBar.events_order.index(event2)
+        return i1 < i2
 
     @staticmethod
     def log_message(message):
@@ -129,9 +131,12 @@ class ProgressBar(object):
         Args:
             message (str): string you wish to log.
         """
+        from tqdm import tqdm
         tqdm.write(message)
 
-    def attach(self, engine, metric_names=None, output_transform=None):
+    def attach(self, engine, metric_names=None, output_transform=None,
+               event_name=Events.ITERATION_COMPLETED,
+               closing_event_name=Events.EPOCH_COMPLETED):
         """
         Attaches the progress bar to an engine object.
 
@@ -141,13 +146,91 @@ class ProgressBar(object):
             output_transform (callable, optional): a function to select what you want to print from the engine's
                 output. This function may return either a dictionary with entries in the format of ``{name: value}``,
                 or a single scalar, which will be displayed with the default name `output`.
+            event_name: event's name on which the progress bar advances. Valid events are from
+                :class:`~ignite.engine.Events`.
+            closing_event_name: event's name on which the progress bar is closed. Valid events are from
+                :class:`~ignite.engine.Events`.
         """
-        if metric_names is not None and not isinstance(metric_names, list):
-            raise TypeError("metric_names should be a list, got {} instead.".format(type(metric_names)))
+        desc = self.tqdm_kwargs.get("desc", "Epoch")
+
+        if not (event_name in Events and closing_event_name in Events):
+            raise ValueError("Logging and closing events should be only ignite.engine.Events")
+
+        if not self._compare_lt(event_name, closing_event_name):
+            raise ValueError("Logging event {} should be called before closing event {}"
+                             .format(event_name, closing_event_name))
 
-        if output_transform is not None and not callable(output_transform):
-            raise TypeError("output_transform should be a function, got {} instead."
-                            .format(type(output_transform)))
+        log_handler = _OutputHandler(desc, metric_names, output_transform,
+                                     event_name=event_name,
+                                     closing_event_name=closing_event_name)
+        super(ProgressBar, self).attach(engine, log_handler, event_name)
+        engine.add_event_handler(closing_event_name, self._close)
 
-        engine.add_event_handler(Events.ITERATION_COMPLETED, self._update, metric_names, output_transform)
-        engine.add_event_handler(Events.EPOCH_COMPLETED, self._close)
+
+class _OutputHandler(BaseOutputHandler):
+    """Helper handler to log engine's output and/or metrics
+
+    Args:
+        description (str): progress bar description.
+        metric_names (list of str, optional): list of metric names to plot.
+        output_transform (callable, optional): output transform function to prepare `engine.state.output` as a number.
+            For example, `output_transform = lambda output: output`
+            This function can also return a dictionary, e.g `{'loss': loss1, `another_loss`: loss2}` to label the plot
+            with corresponding keys.
+        event_name: event's name on which the progress bar advances. Valid events are from
+            :class:`~ignite.engine.Events` or any `event_name` added by
+            :meth:`~ignite.engine.Engine.register_events`.
+        closing_event_name: event's name on which the progress bar is closed. Valid events are from
+            :class:`~ignite.engine.Events` or any `event_name` added by
+            :meth:`~ignite.engine.Engine.register_events`.
+
+    """
+    def __init__(self, description, metric_names=None, output_transform=None,
+                 event_name=Events.ITERATION_COMPLETED,
+                 closing_event_name=Events.EPOCH_COMPLETED):
+        if metric_names is None and output_transform is None:
+            # This helps to avoid 'Either metric_names or output_transform should be defined' of BaseOutputHandler
+            metric_names = []
+        super(_OutputHandler, self).__init__(description, metric_names, output_transform, another_engine=None)
+        self.event_name = event_name
+        self.closing_event_name = closing_event_name
+
+    @staticmethod
+    def get_max_number_events(event_name, engine):
+        if event_name in (Events.ITERATION_STARTED, Events.ITERATION_COMPLETED):
+            return len(engine.state.dataloader)
+        if event_name in (Events.EPOCH_STARTED, Events.EPOCH_COMPLETED):
+            return engine.state.max_epochs
+        return 1
+
+    def __call__(self, engine, logger, event_name):
+
+        if logger.pbar is None:
+            logger._reset(pbar_total=self.get_max_number_events(self.event_name, engine))
+
+        desc = self.tag
+        max_num_of_closing_events = self.get_max_number_events(self.closing_event_name, engine)
+        if max_num_of_closing_events > 1:
+            global_step = engine.state.get_event_attrib_value(self.closing_event_name)
+            desc += " [{}/{}]".format(global_step, max_num_of_closing_events)
+        logger.pbar.set_description(desc)
+
+        metrics = self._setup_output_metrics(engine)
+
+        rendered_metrics = {}
+        for key, value in metrics.items():
+            if isinstance(value, numbers.Number) or \
+                    isinstance(value, torch.Tensor) and value.ndimension() == 0:
+                rendered_metrics[key] = "{:.2e}".format(value)
+            elif isinstance(value, torch.Tensor) and value.ndimension() == 1:
+                for i, v in enumerate(value):
+                    k = "{}_{}".format(key, i)
+                    rendered_metrics[k] = "{:.2e}".format(v)
+            else:
+                warnings.warn("ProgressBar can not log "
+                              "metrics value type {}".format(type(value)))
+
+        if rendered_metrics:
+            logger.pbar.set_postfix(**rendered_metrics)
+
+        logger.pbar.update()


Test patch:
diff --git a/tests/ignite/contrib/handlers/test_pbar.py b/tests/ignite/contrib/handlers/test_tqdm_logger.py
similarity index 51%
rename from tests/ignite/contrib/handlers/test_pbar.py
rename to tests/ignite/contrib/handlers/test_tqdm_logger.py
index 25269482..82f80313 100644
--- a/tests/ignite/contrib/handlers/test_pbar.py
+++ b/tests/ignite/contrib/handlers/test_tqdm_logger.py
@@ -6,6 +6,7 @@ import torch
 from ignite.contrib.handlers import ProgressBar
 from ignite.engine import Engine, Events
 from ignite.metrics import Accuracy
+from ignite.contrib.handlers import CustomPeriodicEvent
 
 
 def update_fn(engine, batch):
@@ -33,6 +34,18 @@ def test_pbar(capsys):
     assert err[-1] == expected
 
 
+def test_pbar_log_message(capsys):
+
+    ProgressBar.log_message("test")
+
+    captured = capsys.readouterr()
+    out = captured.out.split('\r')
+    out = list(map(lambda x: x.strip(), out))
+    out = list(filter(None, out))
+    expected = u'test'
+    assert out[-1] == expected
+
+
 def test_attach_fail_with_string():
     engine = Engine(update_fn)
     pbar = ProgressBar()
@@ -65,7 +78,7 @@ def test_pbar_with_metric():
     pbar = ProgressBar()
     pbar.attach(trainer, ['avg_accuracy'])
 
-    with pytest.raises(KeyError):
+    with pytest.warns(UserWarning):
         trainer.run(data=data, max_epochs=1)
 
 
@@ -148,3 +161,103 @@ def test_pbar_with_tqdm_kwargs(capsys):
     err = list(filter(None, err))
     expected = u'My description:  [10/10]: [4/5]  80%|████████  , output=1.00e+00 [00:00<00:00]'.format()
     assert err[-1] == expected
+
+
+def test_pbar_for_validation(capsys):
+    loader = [1, 2, 3, 4, 5]
+    engine = Engine(update_fn)
+
+    pbar = ProgressBar(desc="Validation")
+    pbar.attach(engine)
+    engine.run(loader, max_epochs=1)
+
+    captured = capsys.readouterr()
+    err = captured.err.split('\r')
+    err = list(map(lambda x: x.strip(), err))
+    err = list(filter(None, err))
+    expected = u'Validation: [4/5]  80%|████████   [00:00<00:00]'
+    assert err[-1] == expected
+
+
+def test_pbar_output_tensor(capsys):
+    loader = [1, 2, 3, 4, 5]
+
+    def update_fn(engine, batch):
+        return torch.Tensor([batch, 0])
+
+    engine = Engine(update_fn)
+
+    pbar = ProgressBar(desc="Output tensor")
+    pbar.attach(engine, output_transform=lambda x: x)
+    engine.run(loader, max_epochs=1)
+
+    captured = capsys.readouterr()
+    err = captured.err.split('\r')
+    err = list(map(lambda x: x.strip(), err))
+    err = list(filter(None, err))
+    expected = u'Output tensor: [4/5]  80%|████████  , output_0=5.00e+00, output_1=0.00e+00 [00:00<00:00]'
+    assert err[-1] == expected
+
+
+def test_pbar_output_warning(capsys):
+    loader = [1, 2, 3, 4, 5]
+
+    def update_fn(engine, batch):
+        return batch, "abc"
+
+    engine = Engine(update_fn)
+
+    pbar = ProgressBar(desc="Output tensor")
+    pbar.attach(engine, output_transform=lambda x: x)
+    with pytest.warns(UserWarning):
+        engine.run(loader, max_epochs=1)
+
+
+def test_pbar_on_epochs(capsys):
+
+    n_epochs = 10
+    loader = [1, 2, 3, 4, 5]
+    engine = Engine(update_fn)
+
+    pbar = ProgressBar()
+    pbar.attach(engine, event_name=Events.EPOCH_STARTED, closing_event_name=Events.COMPLETED)
+    engine.run(loader, max_epochs=n_epochs)
+
+    captured = capsys.readouterr()
+    err = captured.err.split('\r')
+    err = list(map(lambda x: x.strip(), err))
+    err = list(filter(None, err))
+    actual = err[-1]
+    expected = u'Epoch: [9/10]  90%|█████████  [00:00<00:00]'
+    assert actual == expected
+
+
+def test_pbar_wrong_events_order():
+
+    engine = Engine(update_fn)
+    pbar = ProgressBar()
+
+    with pytest.raises(ValueError, match="should be called before closing event"):
+        pbar.attach(engine, event_name=Events.COMPLETED, closing_event_name=Events.COMPLETED)
+
+    with pytest.raises(ValueError, match="should be called before closing event"):
+        pbar.attach(engine, event_name=Events.COMPLETED, closing_event_name=Events.EPOCH_COMPLETED)
+
+    with pytest.raises(ValueError, match="should be called before closing event"):
+        pbar.attach(engine, event_name=Events.COMPLETED, closing_event_name=Events.ITERATION_COMPLETED)
+
+    with pytest.raises(ValueError, match="should be called before closing event"):
+        pbar.attach(engine, event_name=Events.EPOCH_COMPLETED, closing_event_name=Events.EPOCH_COMPLETED)
+
+    with pytest.raises(ValueError, match="should be called before closing event"):
+        pbar.attach(engine, event_name=Events.ITERATION_COMPLETED, closing_event_name=Events.ITERATION_STARTED)
+
+
+def test_pbar_on_custom_events(capsys):
+
+    engine = Engine(update_fn)
+    pbar = ProgressBar()
+    cpe = CustomPeriodicEvent(n_iterations=15)
+
+    with pytest.raises(ValueError, match=r"Logging and closing events should be only ignite.engine.Events"):
+        pbar.attach(engine, event_name=cpe.Events.ITERATIONS_15_COMPLETED, closing_event_name=Events.EPOCH_COMPLETED)