【Beta】測試報告

測試計劃

1、對新增長的用戶註冊、登陸及訪問控制的測試

註冊信息的填寫

  • 用戶名包含純大小寫字母、數字、中文、特殊字符及幾種狀況的混合
  • 密碼包含大小寫字母、數字和特殊字符
  • 用戶名長度不大於150個字節
  • 密碼長度不大於128個字節
  • 郵箱格式(因爲未進行郵箱驗證,故只檢查簡單格式)

註冊時的不合法狀況

  • 沒有填寫完整的註冊信息
  • 兩次輸入的密碼不一致
  • 使用已註冊或者不合法的用戶名註冊
  • 使用已註冊的或者格式不正確的郵箱註冊

登陸時的不合法狀況

  • 未填寫用戶名或密碼的狀況下直接點擊登陸
  • 用戶名或郵箱還沒有註冊
  • 密碼錯誤

訪問控制

  • 未登陸時,不能保存本身搭建的模型
  • 登陸以後,能夠保存搭建的模型,也能夠查看並修改以前保存的模型

2、組件的測試

基礎測試

  • 新增組件及原來組件的拖拽
  • 組件之間的連線
  • 組件的參數設置
  • 組件的刪除

穩定性測試

  • 經過自動化測試往畫布中拖入各類組件共5萬次

3、代碼生成、保存模型及下載功能測試

代碼生成及下載正常測試

  • 組件正確鏈接
  • 參數配置正常

在以上條件知足的狀況下,測試可否正確生成代碼,測試可否下載生成的代碼文件python

代碼生成異常測試

  • 未放入「開始」組件
  • 組件的連線不正確
  • 參數的輸入不合法

測試在以上異常狀況下網站的報錯狀況chrome

已登陸時

  • 拖拽組件、連線及調節參數搭建模型
  • 搭建模型以後生成代碼
  • 保存模型
  • 查看模型
  • 刪除模型
  • 修改已保存的模型
  • 保存修改以後的模型
  • 下載生成的代碼文件
  • 登出帳戶

未登陸時

  • 拖拽組件、連線及調節參數搭建模型
  • 搭建模型以後生成代碼
  • 保存模型
  • 下載生成的代碼文件

4、其餘測試

  • 各個頁面的跳轉
  • 下拉框及參數輸入
  • 針對不一樣平臺的測試

測試過程及測試結果

測試過程

  • 4.30~5.4 針對新增長的註冊登陸進行測試,編寫相應地測試用例對內測版本測試
  • 5.6~5.10 針對內測版本核心功能測試
  • 5.12~5.16 針對線上網站新版本的測試
  • 5.18 對線上進行壓力測試
  • 5.19~5.22 進行總體測試

測試期間發現一些比較嚴重的bug,部分已經獲得修復canvas

測試結果

內測版本發現的主要問題有:後端

  • 註冊時,用戶名含有;.<>?/:"{}[]|'~`!#$%^&*()等特殊字符或者中文字符時,會彈出「用戶名或郵箱已被註冊」
  • 新增的元素級相加層組件沒法刪除
  • 登陸以後沒法保存模型
  • 查看模型時畫布顯示一片空白
  • 查看模型時對模型進行修改以後沒法保存
  • 沒法刪除保存的模型
  • 下載下來的代碼文件沒有換行

對部分bug進行修復以後,當前版本還存在的主要問題有:瀏覽器

  • 註冊時,用戶名含有;.<>?/:"{}[]|'~`!#$%^&*()等特殊字符或者中文字符時,會彈出「用戶名或郵箱已被註冊」網絡

  • 用戶搭好模型以後想登陸保存,登陸以後畫布清空併發

  • 幫助界面側邊欄與正文重疊ide

針對Beta階段的新功能、新特性發現的Bug

Beta階段咱們加入了註冊、登陸功能,用戶能夠保存本身搭建的模型,登陸以後能夠查看以前保存的模型,並在此基礎上進行修改再保存;此外,咱們還增長了代碼文件下載的新功能,提高用戶體驗。如下是測試過程當中針對新功能發現的問題:學習

  • 註冊時,用戶名含有;.<>?/:"{}[]|'~`!#$%^&*()等特殊字符或者中文字符時,會彈出「用戶名或郵箱已被註冊」
  • 幫助界面側邊欄與正文重疊
  • 能夠直接輸入模型id查看他人的模型
  • 用戶搭好模型以後想登陸保存,登陸以後畫布清空

針對新功能的場景測試

典型用戶一

猿巨:不瞭解計算機,路人,一個偶然機會打開網站

需求和目標:試試網站的用途,用來增長閒時的樂趣

使用場景:

猿巨註冊了一個帳號;測試

註冊完以後猿巨登陸成功,而後看了幫助文檔後試着本身隨便搭了個模型,進行保存;

猿巨想看是否真的保存成功,因而登出帳戶,再次登陸,查看模型;

猿巨點擊查看,畫布上顯示出他以前搭建的模型,因而猿巨又改了改模型,再次保存,查看模型,發現模型成功修改;

猿巨點擊代碼生成,發現生成了三份代碼,但是他看不懂,因而又點回畫布,拖着組件玩弄,最後退出登陸。

典型用戶二

戰錘:計算機本科大三學生,瞭解過深度學習,搭過簡單模型

需求和目標:認爲本身手寫代碼太累,想經過簡單方法獲取模型代碼,而且能夠隨時調整參數

使用場景:

戰錘註冊了一個帳號;

本身拖拽組件並搭建了一個模型,進行保存以後,查看模型並生成代碼;

戰錘將生成的代碼文件下載下來,結合本身的數據進行訓練、運行;發現參數調節的不太合適;

戰錘回到網站,查看以前保存的模型,並對其中的參數進行調節,從新保存修改後的模型,並查看再次生成代碼;

戰錘通過屢次調節,不用本身手寫代碼就獲得本身想要的模型;

戰錘又搭建了幾個模型,並進行保存,查看帳戶的模型,本身搭建的模型都在,而且能夠隨時進行修改;

戰錘完成工做後,登出帳戶;

一段時間後,戰錘登陸帳戶查看模型,發現以前搭建的模型有重複的,因而將重複的幾個模型刪除,登出帳戶。

典型用戶三

車伕:對深度學習研究較深,經驗豐富,但願能快速搭建出較複雜的模型

需求和目標:快速搭建較複雜的模型而且能實時修改,不用從新搭建

使用場景:

車伕註冊了一個帳號;

車伕利用網站新增長的元素級相加層和channel維度拼接層,再結合網站以前已有的組件,搭建出一個較複雜的並聯的模型;

車伕查看已保存的模型並生成代碼,將生成的代碼文件下載下來,結合本身的數據文件,進行訓練、運行;

車伕在調整修改時,忽然電腦顯示快關機了,因而車伕點擊保存,先將模型保存下來,以後找到電源再繼續,免於讓本身的努力功虧一簣;

車伕再找到電源後登陸帳戶完善模型,獲得本身想要的模型代碼,並保存最新的模型,登出帳戶。

迴歸測試

在這一階段,咱們作了迴歸測試,首先,第一個向後端發送的數據沒有涉及到新增的兩個網絡層,以此測試新增的網絡層對以前的網絡層是否會形成影響;

def test_ops_five(self):
    """
    Test the addition of two strings returns the two string as one
    concatenated string
    """
    result = {
        "Main": ["'''", "", "Copyright @2019 buaa_huluwa. All rights reserved.", "",
                 "View more, visit our team's home page: https://home.cnblogs.com/u/1606-huluwa/", "", "",
                 "This code is the corresponding pytorch code generated from the model built by the user.", "",
                 " \"main.py\" mainly contains the code of the training and testing part, and you can modify it according to your own needs.",
                 "", "'''", "", "#standard library", "import os", "", "#third-party library", "import torch",
                 "import numpy", "import torchvision", "", "", "from Model import *", "from Ops import *", "", "",
                 "#Hyper Parameters", "epoch = 1", "optimizer = torch.optim.Adam", "learning_rate = 0.001",
                 "batch_size = 50", "data_dir = None", "data_set = None", "train = True", "", "",
                 "#initialize a NET object", "net = NET()", "#print net architecture", "print(net)", "", "",
                 "#load your own dataset and normalize", "", "", "",
                 "#you can add some functions for visualization here or you can ignore them", "", "", "",
                 "#training and testing, you can modify these codes as you expect", "for epo in range(epoch):", "", ""],
        "Model": ["'''", "", "This code is the corresponding pytorch code generated from the model built by the user.", "",
                  "\"model.py\" contains the complete model code, and you can modify it according to your own needs", "",
                  "'''", "", "#standard library", "import os", "", "#third-party library", "import torch", "import numpy",
                  "import torchvision", "", "", "class NET(torch.nn.Module):", "    def __init__(self):",
                  "        super(NET, self).__init__()", "        self.conv1d_layer = torch.nn.Sequential(",
                  "            torch.nn.Conv1d(", "                in_channels = 1,", "                out_channels = 16,",
                  "                kernel_size = 5,", "                stride = 1,", "                padding = 2,",
                  "            ),", "            torch.nn.functional.relu(),",
                  "            torch.nn.functional.max_pool2d(),", "        )",
                  "        self.conv2d_layer = torch.nn.Sequential(", "            torch.nn.Conv2d(",
                  "                in_channels = 16,", "                out_channels = 32,",
                  "                kernel_size = 5,", "                stride = 1,", "                padding = 2,",
                  "            ),", "            torch.nn.functional.relu(),",
                  "            torch.nn.functional.max_pool2d(),", "        )",
                  "        self.linear_layer = torch.nn.Linear(32, 10)", "    def forward(self, x_data):",
                  "        view_layer_data = x_data.view(1)",
                  "        conv1d_layer_data = self.conv1d_layer(view_layer_data)",
                  "        conv2d_layer_data = self.conv2d_layer(conv1d_layer_data)",
                  "        linear_layer_data = self.linear_layer(conv2d_layer_data)", "        return linear_layer_data"],
        "Ops": ["'''", "", "This code is the corresponding pytorch code generated from the model built by the user.", "",
                "\"ops.py\" contains functions you might use", "", "'''", "", "#standard library", "import os", "",
                "#third-party library", "import torch", "import numpy", "import torchvision", "", "",
                "def element_wise_add(inputs):", "    ans = inputs[0]", "    for indx in range(1, len(inputs)):",
                "        ans.add_(inputs[indx])", "    return ans"]
    }
    data = {
        "nets":{
            "canvas_4":{
                "name":"start",
                "attribute":{
                    "start":"true"
                },
                "left":"151px",
                "top":"102px"
            },
            "canvas_5":{
                "name":"view_layer",
                "attribute":{
                    "shape":"1"
                },
                "left":"386px",
                "top":"98px"
            },
            "canvas_6":{
                "name":"conv1d_layer",
                "attribute":{
                    "in_channels":"1",
                    "out_channels":"16",
                    "kernel_size":"5",
                    "stride":"1",
                    "padding":"2",
                    "activity":"torch.nn.functional.relu",
                    "pool_way":"torch.nn.functional.max_pool2d",
                    "pool_kernel_size":"3",
                    "pool_stride":"1",
                    "pool_padding":"2"
                },
                "left":"268px",
                "top":"282px"
            },
            "canvas_7":{
                "name":"conv2d_layer",
                "attribute":{
                    "in_channels":"16",
                    "out_channels":"32",
                    "kernel_size":"5",
                    "stride":"1",
                    "padding":"2",
                    "activity":"torch.nn.functional.relu",
                    "pool_way":"torch.nn.functional.max_pool2d",
                    "pool_kernel_size":"3",
                    "pool_stride":"1",
                    "pool_padding":"2"
                },
                "left":"494px",
                "top":"354px"
            },
            "canvas_8":{
                "name":"linear_layer",
                "attribute":{
                    "in_channels":"32",
                    "out_channels":"10"
                },
                "left":"75px",
                "top":"209px"
            }
        },
        "nets_conn":[
            {
                "source":{
                    "id":"canvas_4",
                    "anchor_position":"Right"
                },
                "target":{
                    "id":"canvas_5",
                    "anchor_position":"Left"
                }
            },
            {
                "source":{
                    "id":"canvas_5",
                    "anchor_position":"Bottom"
                },
                "target":{
                    "id":"canvas_6",
                    "anchor_position":"Top"
                }
            },
            {
                "source":{
                    "id":"canvas_6",
                    "anchor_position":"Bottom"
                },
                "target":{
                    "id":"canvas_7",
                    "anchor_position":"Left"
                }
            },
            {
                "source":{
                    "id":"canvas_7",
                    "anchor_position":"Bottom"
                },
                "target":{
                    "id":"canvas_8",
                    "anchor_position":"Bottom"
                }
            }
        ],
        "static":{
            "epoch":"1",
            "learning_rate":"0.001",
            "batch_size":"50"
        }
    }
    res = NeuralNetwork.translate.ops.main_func(data)
    self.assertEqual(res, result)

第二個向後端發送的數據包括以前已有的網絡層和新增的網絡層。

def test_ops_six(self):
        """
        Test the addition of two strings returns the two string as one
        concatenated string
        """

    result = {
        "Main": ["'''", "", "Copyright @2019 buaa_huluwa. All rights reserved.", "",
                "View more, visit our team's home page: https://home.cnblogs.com/u/1606-huluwa/", "", "",
                "This code is the corresponding pytorch code generated from the model built by the user.", "",
                 " \"main.py\" mainly contains the code of the training and testing part, and you can modify it according to your own needs.",
                "", "'''", "", "#standard library", "import os", "", "#third-party library", "import torch",
                "import numpy", "import torchvision", "", "", "from Model import *", "from Ops import *", "", "",
                "#Hyper Parameters", "epoch = 1", "optimizer = torch.optim.Adam", "learning_rate = 0.5", "batch_size = 1",
                "data_dir = None", "data_set = None", "train = True", "", "", "#initialize a NET object", "net = NET()",
                "#print net architecture", "print(net)", "", "", "#load your own dataset and normalize", "", "", "",
                "#you can add some functions for visualization here or you can ignore them", "", "", "",
                "#training and testing, you can modify these codes as you expect", "for epo in range(epoch):", "", ""],
        "Model": ["'''", "", "This code is the corresponding pytorch code generated from the model built by the user.", "",
                "\"model.py\" contains the complete model code, and you can modify it according to your own needs", "",
                "'''", "", "#standard library", "import os", "", "#third-party library", "import torch", "import numpy",
                "import torchvision", "", "", "class NET(torch.nn.Module):", "    def __init__(self):",
                "        super(NET, self).__init__()", "        self.conv2d_layer = torch.nn.Sequential(",
                "            torch.nn.Conv2d(", "                in_channels = 1,", "                out_channels = 96,",
                "                kernel_size = 11,", "                stride = 4,", "                padding = 0,",
                "            ),", "            torch.nn.functional.relu(),",
                "            torch.nn.functional.max_pool2d(),", "        )",
                "        self.conv2d_layer_1 = torch.nn.Sequential(", "            torch.nn.Conv2d(",
                "                in_channels = 96,", "                out_channels = 256,",
                "                kernel_size = 5,", "                stride = 1,", "                padding = 2,",
                "            ),", "            torch.nn.functional.relu(),",
                "            torch.nn.functional.max_pool2d(),", "        )",
                "        self.conv2d_layer_2 = torch.nn.Sequential(", "            torch.nn.Conv2d(",
                "                in_channels = 256,", "                out_channels = 384,",
                "                kernel_size = 3,", "                stride = 1,", "                padding = 1,",
                "            ),", "            torch.nn.functional.relu(),", "        )",
                "        self.conv2d_layer_3 = torch.nn.Sequential(", "            torch.nn.Conv2d(",
                "                in_channels = 384,", "                out_channels = 384,",
                "                kernel_size = 3,", "                stride = 1,", "                padding = 1,",
                "            ),", "            torch.nn.functional.relu(),", "        )",
                "        self.conv2d_layer_4 = torch.nn.Sequential(", "            torch.nn.Conv2d(",
                "                in_channels = 384,", "                out_channels = 256,",
                "                kernel_size = 3,", "                stride = 1,", "                padding = 1,",
                "            ),", "        )", "        self.linear_layer = torch.nn.Linear(256, 4096)",
                "        self.linear_layer_1 = torch.nn.Linear(4096, 4096)",
                "        self.linear_layer_2 = torch.nn.Linear(4096, 1000)", "    def forward(self, x_data):",
                "        conv2d_layer_data = self.conv2d_layer(x_data)",
                "        element_wise_add_layer_data = element_wise_add([x_data])",
                "        conv2d_layer_1_data = self.conv2d_layer_1(conv2d_layer_data)",
                "        conv2d_layer_2_data = self.conv2d_layer_2(conv2d_layer_1_data)",
                "        conv2d_layer_3_data = self.conv2d_layer_3(conv2d_layer_2_data)",
                "        conv2d_layer_4_data = self.conv2d_layer_4(conv2d_layer_3_data)",
                "        linear_layer_data = self.linear_layer(conv2d_layer_4_data)",
                "        linear_layer_1_data = self.linear_layer_1(linear_layer_data)",
                "        linear_layer_2_data = self.linear_layer_2(linear_layer_1_data)",
                "        return element_wise_add_layer_data, linear_layer_2_data"],
        "Ops": ["'''", "", "This code is the corresponding pytorch code generated from the model built by the user.", "",
                "\"ops.py\" contains functions you might use", "", "'''", "", "#standard library", "import os", "",
                "#third-party library", "import torch", "import numpy", "import torchvision", "", "",
                "def element_wise_add(inputs):", "    ans = inputs[0]", "    for indx in range(1, len(inputs)):",
                "        ans.add_(inputs[indx])", "    return ans"]
    }

    data = {
        "nets": {
            "canvas_1": {
                "name": "start",
                "attribute": {
                    "start": "true"
                },
                "left": "365px",
                "top": "20px"
            },
            "canvas_2": {
                "name": "conv2d_layer",
                "attribute": {
                    "in_channels": "1",
                    "out_channels": "96",
                    "kernel_size": "11",
                    "stride": "4",
                    "padding": "0",
                    "activity": "torch.nn.functional.relu",
                    "pool_way": "torch.nn.functional.max_pool2d",
                    "pool_kernel_size": "3",
                    "pool_stride": "2",
                    "pool_padding": "0"
                },
                "left": "317px",
                "top": "109px"
            },
            "canvas_3": {
                "name": "conv2d_layer",
                "attribute": {
                    "in_channels": "96",
                    "out_channels": "256",
                    "kernel_size": "5",
                    "stride": "1",
                    "padding": "2",
                    "activity": "torch.nn.functional.relu",
                    "pool_way": "torch.nn.functional.max_pool2d",
                    "pool_kernel_size": "3",
                    "pool_stride": "2",
                    "pool_padding": "0"
                },
                "left": "315px",
                "top": "203px"
            },
            "canvas_4": {
                "name": "conv2d_layer",
                "attribute": {
                    "in_channels": "256",
                    "out_channels": "384",
                    "kernel_size": "3",
                    "stride": "1",
                    "padding": "1",
                    "activity": "torch.nn.functional.relu",
                    "pool_way": "None",
                    "pool_kernel_size": "",
                    "pool_stride": "",
                    "pool_padding": "0"
                },
                "left": "313px",
                "top": "306px"
            },
            "canvas_5": {
                "name": "conv2d_layer",
                "attribute": {
                    "in_channels": "384",
                    "out_channels": "384",
                    "kernel_size": "3",
                    "stride": "1",
                    "padding": "1",
                    "activity": "torch.nn.functional.relu",
                    "pool_way": "None",
                    "pool_kernel_size": "",
                    "pool_stride": "",
                    "pool_padding": "0"
                },
                "left": "315px",
                "top": "355px"
            },
            "canvas_6": {
                "name": "conv2d_layer",
                "attribute": {
                    "in_channels": "384",
                    "out_channels": "256",
                    "kernel_size": "3",
                    "stride": "1",
                    "padding": "1",
                    "activity": "None",
                    "pool_way": "None",
                    "pool_kernel_size": "3",
                    "pool_stride": "2",
                    "pool_padding": "0"
                },
                "left": "316px",
                "top": "404px"
            },
            "canvas_7": {
                "name": "linear_layer",
                "attribute": {
                    "in_channels": "256",
                    "out_channels": "4096"
                },
                "left": "316px",
                "top": "541px"
            },
            "canvas_8": {
                "name": "linear_layer",
                "attribute": {
                    "in_channels": "4096",
                    "out_channels": "4096"
                },
                "left": "318px",
                "top": "672px"
            },
            "canvas_9": {
                "name": "linear_layer",
                "attribute": {
                    "in_channels": "4096",
                    "out_channels": "1000"
                },
                "left": "319px",
                "top": "827px"
            },
            "canvas_10": {
                "name": "element_wise_add_layer",
                "attribute": {
                    "element_wise_add_layer": "true"
                },
                "left": "91px",
                "top": "830px"
            }
        },
        "nets_conn": [
            {
                "source": {
                    "id": "canvas_1",
                    "anchor_position": "Bottom"
                },
                "target": {
                    "id": "canvas_2",
                    "anchor_position": "Top"
                }
            },
            {
                "source": {
                    "id": "canvas_2",
                    "anchor_position": "Bottom"
                },
                "target": {
                    "id": "canvas_3",
                    "anchor_position": "Top"
                }
            },
            {
                "source": {
                    "id": "canvas_4",
                    "anchor_position": "Bottom"
                },
                "target": {
                    "id": "canvas_5",
                    "anchor_position": "Top"
                }
            },
            {
                "source": {
                    "id": "canvas_5",
                    "anchor_position": "Bottom"
                },
                "target": {
                    "id": "canvas_6",
                    "anchor_position": "Top"
                }
            },
            {
                "source": {
                    "id": "canvas_3",
                    "anchor_position": "Bottom"
                },
                "target": {
                    "id": "canvas_4",
                    "anchor_position": "Top"
                }
            },
             {
                 "source": {
                     "id": "canvas_1",
                     "anchor_position": "Left"
                 },
                "target": {
                    "id": "canvas_10",
                    "anchor_position": "Top"
                }
             },
            {"source": {
                "id": "canvas_6",
                "anchor_position": "Bottom"
            },
            "target": {
                "id": "canvas_7",
                "anchor_position": "Top"
            }
            },
            {
                "source": {
                    "id": "canvas_7",
                    "anchor_position": "Bottom"
                },
                "target": {
                    "id": "canvas_8",
                    "anchor_position": "Top"
                }
            },
            {
                "source": {
                    "id": "canvas_8",
                    "anchor_position": "Bottom"
                },
                "target": {
                    "id": "canvas_9",
                    "anchor_position": "Top"
                }
            }
        ],
        "static": {
            "epoch": "1",
            "learning_rate": "0.5",
            "batch_size": "1"
        }
    }
    
    res = NeuralNetwork.translate.ops.main_func(data)
    self.assertEqual(res, result)

測試矩陣

測試矩陣 功能測試 頁面測試
測試瀏覽器 測試環境(瀏覽器版本) 組件拖拽 組件刪除 組件連線 參數輸入 點擊事件(組件、按鈕、連接)下拉框選擇 報錯狀況 註冊登陸 保存模型 查看模型 刪除模型 生成代碼 代碼下載 主頁面 聯繫咱們頁面 幫助頁面 代碼生成頁面 頁面切換
chrome 74.0.3729.131 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 縮小查看時側邊欄會與正文重疊 正常 正常
火狐 67.0(64位) 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 側邊欄居中 正常 正常
edge 42.17134.1.0 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 側邊欄居中 正常 正常
UC 6.2.4098.3 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 側邊欄與正文重疊 正常 正常
Opera 60.0.3255.95 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 縮小查看時側邊欄與正文重疊 正常 正常
搜狗 8.5.10.30358 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 縮小查看時側邊欄與正文重疊 正常 正常
獵豹 6.5.115.18552 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 正常 縮小查看時側邊欄與正文重疊 正常 正常

壓力測試

經過badboy + jmeter的方式,對網站進行壓力測試,設置併發數爲100,對用戶登陸查看模型,查看幫助文檔等進行測試。

Beta版本的出口條件

在Beta階段,咱們的目標是在以前的基礎上,加入註冊登陸功能,讓用戶保存本身的工做成果,不用重複搭建模型或者在緊急時保存當前進度;而且支持了更多的網絡層,用戶能夠搭建更多樣的模型。所以,咱們將這一版本的出口條件設置爲:

實現用戶的註冊登陸,登陸以後對以前保存的模型的增刪改查;能夠利用新增的網絡層結合以前的網絡層搭建出更多的模型,而且支持對生成代碼文件的下載

目前項目的核心功能就是支持註冊登陸,而且用戶能夠經過組件的拖拽、連線、配置參數搭建模型,經過模型能生成相應的代碼而且支持下載,用戶登陸以後還能夠保存、修改及刪除本身搭建的模型。在Beta版本中,咱們針對Alpha版本對模型的單一支持與不能實時修改等作了改進,完成了一個基本完善的產品,可用性及用戶體驗方面都有了很大提高。在接下來的版本中,咱們會更多地花時間去豐富產品內容、提高用戶體驗。

秉承敏捷開發的原則,在達到出口條件的基礎上,爲了提高用戶體驗,咱們對首頁頁面作了美化,還對幫助文檔作了相應調整,優化了幫助界面,而且細化了各個方面的介紹,爲用戶提供更精確的操做步驟,此外咱們在幫助文檔中提供了幾個經典模型的搭建,裏面有咱們提供的一些模型的例子,用戶能夠查看學習。

雖然已達到了預約的目標,可是這一版本仍是存在一些問題的,好比註冊時不能使用中文名或者一些特殊字符、頁面的UI不夠美觀等,這些都是影響產品總體表現地問題所在。

在你們的共同努力下,完成了Beta版本預期的主要目標。在此基礎上,通過你們的討論,在接下來的版本中,咱們列出了幾個目標:

  • 將各個組件的參數框,調整至右邊的參數菜單(類draw.io)
  • 增長複製組件的功能
  • 反饋功能
  • 添加新手引導功能
  • 完善生成的代碼,補充註釋,幫助用戶理解須要修改的地方以及修改的方法

接下來的時間裏,咱們會繼續努力,在完成核心功能的基礎上多考慮提高用戶體驗,交付一個儘量實現的最好的產品。

相關文章
相關標籤/搜索