[TOC]
## **一、自定義admin的actions**
需要有專門的審批員來審批新資產,對資產的合法性、健全性、可用性等更多方面進行審核,如果沒有問題,那么就批準上線。
<br />
批準上線這一操作是通過admin的自定義actions來實現的。
Django的admin默認有一個delete操作的action,所有在admin中的模型都有這個action,更多的就需要我們自己編寫了。

修改`/assets/admin.py`的代碼,新的代碼如下:
~~~
from django.contrib import admin
# Register your models here.
from assets import models
from assets import asset_handler
class NewAssetAdmin(admin.ModelAdmin):
list_display = ['asset_type', 'sn', 'model', 'manufacturer', 'c_time', 'm_time']
list_filter = ['asset_type', 'manufacturer', 'c_time']
search_fields = ('sn',)
actions = ['approve_selected_new_assets']
def approve_selected_new_assets(self, request, queryset):
# 獲得被打鉤的checkbox對應的資產
selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
success_upline_number = 0
for asset_id in selected:
obj = asset_handler.ApproveAsset(request, asset_id)
ret = obj.asset_upline()
if ret:
success_upline_number += 1
# 頂部綠色提示信息
self.message_user(request, "成功批準 %s 條新資產上線!" % success_upline_number)
approve_selected_new_assets.short_description = "批準選擇的新資產"
class AssetAdmin(admin.ModelAdmin):
list_display = ['asset_type', 'name', 'status', 'approved_by', 'c_time', "m_time"]
admin.site.register(models.Asset, AssetAdmin)
admin.site.register(models.Server)
admin.site.register(models.StorageDevice)
admin.site.register(models.SecurityDevice)
admin.site.register(models.BusinessUnit)
admin.site.register(models.Contract)
admin.site.register(models.CPU)
admin.site.register(models.Disk)
admin.site.register(models.EventLog)
admin.site.register(models.IDC)
admin.site.register(models.Manufacturer)
admin.site.register(models.NetworkDevice)
admin.site.register(models.NIC)
admin.site.register(models.RAM)
admin.site.register(models.Software)
admin.site.register(models.Tag)
admin.site.register(models.NewAssetApprovalZone, NewAssetAdmin)
~~~
說明:
* 通過`actions = ['approve_selected_new_assets']`定義當前模型的新acitons列表;
* `approve_selected_new_assets()`方法包含具體的動作邏輯;
* 自定義的action接收至少三個參數,第一個是self,第二個是request即請求,第三個是被選中的數據對象集合queryset。
* 首先通過`request.POST.getlist()`方法獲取被打鉤的checkbox對應的資產;
* 注意:django3.0后,`ACTION_CHECKBOX_NAME`的位置發生了改變。所以需要改成`admin.helpers.ACTION_CHECKBOX_NAME`或者`'_selected_action'`。
* 可能同時有多個資產被選擇,所以這是個批量操作,需要進行循環;
* selected是一個包含了被選中資產的id值的列表;
* 對于每一個資產,創建一個`asset_handler.ApproveAsset()`的實例,然后調用實例的`asset_upline()`方法,并獲取返回值。如果返回值為True,說明該資產被成功批準,那么`success_upline_number`變量+1,保存成功批準的資產數;
* 最后,在admin中給與提示信息。
* `approve_selected_new_assets.short_description = "批準選擇的新資產"`用于在admin界面中為action提供中文顯示。你可以嘗試去掉這條,看看效果。
<br />
重新啟動CMDB,進入admin的待審批資產區,查看上方的acitons動作條,如下所示:

<br />
## **二、創建測試用例**
由于沒有真實的服務器供測試,這里需要手動創建一些虛假的服務器用例,方便后面的使用和展示。
首先,將先前的所有資產條目全部從admin中刪除,確保數據庫內沒有任何數據。
然后,在Client/bin/目錄下新建一個`report_assets`腳本,其內容如下:
<br />
<details>
<summary>report_assets</summary>
```
# -*- coding:utf-8 -*-
import json
import urllib.request
import urllib.parse
import os
import sys
BASE_DIR = os.path.dirname(os.getcwd())
# 設置工作目錄,使得包和模塊能夠正常導入
sys.path.append(BASE_DIR)
from conf import settings
def update_test(data):
"""
創建測試用例
:return:
"""
# 將數據打包到一個字典內,并轉換為json格式
data = {"asset_data": json.dumps(data)}
# 根據settings中的配置,構造url
url = "http://%s:%s%s" % (settings.Params['server'], settings.Params['port'], settings.Params['url'])
print('正在將數據發送至: [%s] ......' % url)
try:
# 使用Python內置的urllib.request庫,發送post請求。
# 需要先將數據進行封裝,并轉換成bytes類型
data_encode = urllib.parse.urlencode(data).encode()
response = urllib.request.urlopen(url=url, data=data_encode, timeout=settings.Params['request_timeout'])
print("\033[31;1m發送完畢!\033[0m ")
message = response.read().decode()
print("返回結果:%s" % message)
except Exception as e:
message = "發送失敗"
print("\033[31;1m發送失敗,%s\033[0m" % e)
if __name__ == '__main__':
windows_data = {
"os_type": "Windows",
"os_release": "7 64bit 6.1.7601 ",
"os_distribution": "Microsoft",
"asset_type": "server",
"cpu_count": 2,
"cpu_model": "Intel(R) Core(TM) i5-2300 CPU @ 2.80GHz",
"cpu_core_count": 8,
"ram": [
{
"slot": "A1",
"capacity": 8,
"model": "Physical Memory",
"manufacturer": "kingstone ",
"sn": "456"
},
],
"manufacturer": "Intel",
"model": "P67X-UD3R-B3",
"wake_up_type": 6,
"sn": "00426-OEM-8992662-111111",
"physical_disk_driver": [
{
"iface_type": "unknown",
"slot": 0,
"sn": "3830414130423230343234362020202020202020",
"model": "KINGSTON SV100S264G ATA Device",
"manufacturer": "(標準磁盤驅動器)",
"capacity": 128
},
{
"iface_type": "SATA",
"slot": 1,
"sn": "383041413042323023234362020102020202020",
"model": "KINGSTON SV100S264G ATA Device",
"manufacturer": "(標準磁盤驅動器)",
"capacity": 2048
},
],
"nic": [
{
"mac": "14:CF:22:FF:48:34",
"model": "[00000011] Realtek RTL8192CU Wireless LAN 802.11n USB 2.0 Network Adapter",
"name": 11,
"ip_address": "192.168.1.110",
"net_mask": [
"255.255.255.0",
"64"
]
},
{
"mac": "0A:01:27:00:00:00",
"model": "[00000013] VirtualBox Host-Only Ethernet Adapter",
"name": 13,
"ip_address": "192.168.56.1",
"net_mask": [
"255.255.255.0",
"64"
]
},
{
"mac": "14:CF:22:FF:48:34",
"model": "[00000017] Microsoft Virtual WiFi Miniport Adapter",
"name": 17,
"ip_address": "",
"net_mask": ""
},
{
"mac": "14:CF:22:FF:48:34",
"model": "Intel Adapter",
"name": 17,
"ip_address": "192.1.1.1",
"net_mask": ""
},
]
}
linux_data = {
"asset_type": "server",
"manufacturer": "innotek GmbH",
"sn": "00001",
"model": "VirtualBox",
"uuid": "E8DE611C-4279-495C-9B58-502B6FCED076",
"wake_up_type": "Power Switch",
"os_distribution": "Ubuntu",
"os_release": "Ubuntu 16.04.3 LTS",
"os_type": "Linux",
"cpu_count": "2",
"cpu_core_count": "4",
"cpu_model": "Intel(R) Core(TM) i5-2300 CPU @ 2.80GHz",
"ram": [
{
"slot": "A1",
"capacity": 8,
}
],
"ram_size": 3.858997344970703,
"nic": [],
"physical_disk_driver": [
{
"model": "VBOX HARDDISK",
"size": "50",
"sn": "VBeee1ba73-09085302"
}
]
}
update_test(linux_data)
update_test(windows_data)
```
</details>
<br />
該腳本的作用很簡單,人為虛構了兩臺服務器(一臺windows,一臺Linux)的信息,并發送給CMDB。單獨執行該腳本,在admin的新資產待審批區可以看到添加了兩條新資產信息。
<br />
要添加更多的資產,只需修改腳本中`windows_data`和`linux_data`的數據即可。但是要注意的是,如果不修改sn,那么會變成資產數據更新,而不是增加新資產,這一點一定要注意。
<br />
OK,我們再加兩條資產,這樣就變成四個實例了。

<br />
## **三、批準資產上線**
有已經忍不住點擊‘執行’命令的請舉手!
是不是出現了錯誤?
~~~
AttributeError at /admin/assets/newassetapprovalzone/
module 'assets.asset_handler' has no attribute 'ApproveAsset'
~~~
這是必然的,因為還沒有寫如何上線的代碼啊!
在`/assets/asset_handler.py`中添加下面的代碼:
<br />
<details>
<summary>/assets/asset_handler.py</summary>
```
def log(log_type, msg=None, asset=None, new_asset=None, request=None):
"""
記錄日志
"""
event = models.EventLog()
if log_type == "upline":
event.name = "%s <%s> : 上線" % (asset.name, asset.sn)
event.asset = asset
event.detail = "資產成功上線!"
event.user = request.user
elif log_type == "approve_failed":
event.name = "%s <%s> : 審批失敗" % (new_asset.asset_type, new_asset.sn)
event.new_asset = new_asset
event.detail = "審批失敗!\n%s" % msg
event.user = request.user
# 更多日志類型.....
event.save()
class ApproveAsset:
"""
審批資產并上線。
"""
def __init__(self, request, asset_id):
self.request = request
self.new_asset = models.NewAssetApprovalZone.objects.get(id=asset_id)
self.data = json.loads(self.new_asset.data)
def asset_upline(self):
# 為以后的其它類型資產擴展留下接口
func = getattr(self, "_%s_upline" % self.new_asset.asset_type)
ret = func()
return ret
def _server_upline(self):
# 在實際的生產環境中,下面的操作應該是原子性的整體事務,任何一步出現異常,所有操作都要回滾。
asset = self._create_asset() # 創建一條資產并返回資產對象。注意要和待審批區的資產區分開。
try:
self._create_manufacturer(asset) # 創建廠商
self._create_server(asset) # 創建服務器
self._create_CPU(asset) # 創建CPU
self._create_RAM(asset) # 創建內存
self._create_disk(asset) # 創建硬盤
self._create_nic(asset) # 創建網卡
self._delete_original_asset() # 從待審批資產區刪除已審批上線的資產
except Exception as e:
asset.delete()
log('approve_failed', msg=e, new_asset=self.new_asset, request=self.request)
print(e)
return False
else:
# 添加日志
log("upline", asset=asset, request=self.request)
print("新服務器上線!")
return True
def _create_asset(self):
"""
創建資產并上線
:return:
"""
# 利用request.user自動獲取當前管理人員的信息,作為審批人添加到資產數據中。
asset = models.Asset.objects.create(asset_type=self.new_asset.asset_type,
name="%s: %s" % (self.new_asset.asset_type, self.new_asset.sn),
sn=self.new_asset.sn,
approved_by=self.request.user,
)
return asset
def _create_manufacturer(self, asset):
"""
創建廠商
:param asset:
:return:
"""
# 判斷廠商數據是否存在。如果存在,看看數據庫里是否已經有該廠商,再決定是獲取還是創建。
m = self.new_asset.manufacturer
if m:
manufacturer_obj, _ = models.Manufacturer.objects.get_or_create(name=m)
asset.manufacturer = manufacturer_obj
asset.save()
def _create_server(self, asset):
"""
創建服務器
:param asset:
:return:
"""
models.Server.objects.create(asset=asset,
model=self.new_asset.model,
os_type=self.new_asset.os_type,
os_distribution=self.new_asset.os_distribution,
os_release=self.new_asset.os_release,
)
def _create_CPU(self, asset):
"""
創建CPU.
教程這里對發送過來的數據采取了最大限度的容忍,
實際情況下你可能還要對數據的完整性、合法性、數據類型進行檢測,
根據不同的檢測情況,是被動接收,還是打回去要求重新收集,請自行決定。
這里的業務邏輯非常復雜,不可能面面俱到。
:param asset:
:return:
"""
cpu = models.CPU.objects.create(asset=asset)
cpu.cpu_model = self.new_asset.cpu_model
cpu.cpu_count = self.new_asset.cpu_count
cpu.cpu_core_count = self.new_asset.cpu_core_count
cpu.save()
def _create_RAM(self, asset):
"""
創建內存。通常有多條內存
:param asset:
:return:
"""
ram_list = self.data.get('ram')
if not ram_list: # 萬一一條內存數據都沒有
return
for ram_dict in ram_list:
if not ram_dict.get('slot'):
raise ValueError("未知的內存插槽!") # 使用虛擬機的時候,可能無法獲取內存插槽,需要你修改此處的邏輯。
ram = models.RAM()
ram.asset = asset
ram.slot = ram_dict.get('slot')
ram.sn = ram_dict.get('sn')
ram.model = ram_dict.get('model')
ram.manufacturer = ram_dict.get('manufacturer')
ram.capacity = ram_dict.get('capacity', 0)
ram.save()
def _create_disk(self, asset):
"""
存儲設備種類多,還有Raid情況,需要根據實際情況具體解決。
這里只以簡單的SATA硬盤為例子。可能有多塊硬盤。
:param asset:
:return:
"""
disk_list = self.data.get('physical_disk_driver')
if not disk_list: # 一條硬盤數據都沒有
return
for disk_dict in disk_list:
if not disk_dict.get('sn'):
raise ValueError("未知sn的硬盤!") # 根據sn確定具體某塊硬盤。
disk = models.Disk()
disk.asset = asset
disk.sn = disk_dict.get('sn')
disk.model = disk_dict.get('model')
disk.manufacturer = disk_dict.get('manufacturer'),
disk.slot = disk_dict.get('slot')
disk.capacity = disk_dict.get('capacity', 0)
iface = disk_dict.get('interface_type')
if iface in ['SATA', 'SAS', 'SCSI', 'SSD', 'unknown']:
disk.interface_type = iface
disk.save()
def _create_nic(self, asset):
"""
創建網卡。可能有多個網卡,甚至虛擬網卡。
:param asset:
:return:
"""
nic_list = self.data.get("nic")
if not nic_list:
return
for nic_dict in nic_list:
if not nic_dict.get('mac'):
raise ValueError("網卡缺少mac地址!")
if not nic_dict.get('model'):
raise ValueError("網卡型號未知!")
nic = models.NIC()
nic.asset = asset
nic.name = nic_dict.get('name')
nic.model = nic_dict.get('model')
nic.mac = nic_dict.get('mac')
nic.ip_address = nic_dict.get('ip_address')
if nic_dict.get('net_mask'):
if len(nic_dict.get('net_mask')) > 0:
nic.net_mask = nic_dict.get('net_mask')[0]
nic.save()
def _delete_original_asset(self):
"""
這里的邏輯是已經審批上線的資產,就從待審批區刪除。
也可以設置為修改成已審批狀態但不刪除,只是在管理界面特別處理,不讓再次審批,灰色顯示。
不過這樣可能導致待審批區越來越大。
:return:
"""
self.new_asset.delete()
```
</details>
<br />
核心就是增加了一個記錄日志的log()函數以及審批資產的ApproveAsset類。
log()函數很簡單,根據日志類型的不同,保存日志需要的各種信息,比如日志名稱、關聯的資產對象、日志詳細內容和審批人員等等。所有的日志都被保存在數據庫中,可以在admin中查看。
對于關鍵的ApproveAsset類,說明如下:
* 初始化方法接收reqeust和待審批資產的id;
* 分別提前獲取資產對象和所有數據data;
* `asset_upline()`是入口方法,通過反射,獲取一個類似`_server_upline`的方法。之所以這么做,是為后面的網絡設別、安全設備、存儲設備等更多類型資產的審批留下擴展接口。本教程里只實現了服務器類型資產的審批方法,更多的請自行完善,過程基本類似。
`_server_upline()`是服務器類型資產上線的核心方法:
* 它首先新建了一個Asset資產對象(注意要和待審批區的資產區分開);
* 然后利用該對象,分別創建了對應的廠商、服務器、CPU、內存、硬盤和網卡,并刪除待審批區的對應資產;
* 在實際的生產環境中,上面的操作應該是原子性的整體事務,任何一步出現異常,所有操作都要回滾;
* 如果任何一步出現錯誤,上面的操作全部撤銷,也就是`asset.delete()`。記錄錯誤日志,返回False;
* 如果沒問題,那么記錄正確日志,返回True。
<br />
對于`_create_asset(self)`方法,利用`request.user`自動獲取當前管理人員的信息,作為審批人添加到資產數據中。
<br />
對于`_create_manufacturer(self, asset)`方法,先判斷廠商數據是否存在,再決定是獲取還是創建。
<br />
對于`_create_CPU(self, asset)`等方法,教程這里對數據采取了最大限度的容忍,實際情況下你可能還要對數據的完整性、合法性、數據類型進行檢測,根據不同的檢測情況,是被動接收,還是打回去要求重新收集,請自行決定。這里的業務邏輯非常復雜,不可能面面俱到。后面的內存、硬盤和網卡也是一樣的。
<br />
對于`_delete_original_asset(self)`方法,這里的邏輯是已經審批上線的資產,就從待審批區刪除。也可以設置為修改成已審批狀態但不刪除,只是在管理界面特別處理,不讓再次審批,灰色顯示,不過這樣可能導致待審批區越來越大。
- Linux
- Linux 文件權限概念
- 重點總結
- Linux 文件與目錄管理
- 2.1 文件與目錄管理
- 2.2 文件內容查閱
- 文件與文件系統的壓縮,打包與備份
- 3.1 Linux 系統常見的壓縮指令
- 3.2 打包指令: tar
- vi/vim 程序編輯器
- 4.1 vi 的使用
- 4.2 vim編輯器刪除一行或者多行內容
- 進程管理
- 5.1 常用命令使用技巧
- 5.2 進程管理
- 系統服務 (daemons)
- 6.1 通過 systemctl 管理服務
- Linux 系統目錄結構
- Linux yum命令
- linux系統查看、修改、更新系統時間(自動同步網絡時間)
- top linux下的任務管理器
- Linux基本配置
- CentOS7開啟防火墻
- CentOS 使用yum安裝 pip
- strace 命令
- Linux下設置固定IP地址
- 查看Linux磁盤及內存占用情況
- Mysql
- 關系數據庫概述
- 數據庫技術
- 數據庫基礎語句
- 查詢語句(--重點--)
- 約束
- 嵌套查詢(子查詢)
- 表emp
- MySQL數據庫練習
- 01.MySQL數據庫練習數據
- 02.MySQL數據庫練習題目
- 03.MySQL數據庫練習-答案
- Mysql遠程連接數據庫
- Python
- python基礎
- Python3中字符串、列表、數組的轉換方法
- python字符串
- python安裝、pip基本用法、變量、輸入輸出、流程控制、循環
- 運算符及優先級、數據類型及常用操作、深淺拷貝
- 虛擬環境(virtualenv)
- 網絡編程
- TCP/IP簡介
- TCP編程
- UDP編程
- 進程和線程
- 訪問數據庫
- 使用SQLite
- 使用MySQL
- Web開發
- HTML簡介
- Python之日志處理(logging模塊)
- 函數式編程
- 高階函數
- python報錯解決
- 啟動Python時報“ImportError: No module named site”錯誤
- python實例
- 01- 用python解決數學題
- 02- 冒泡排序
- 03- 郵件發送(smtplib)
- Django
- 01 Web應用
- Django3.2 教程
- Django簡介
- Django環境安裝
- 第一個Django應用
- Part 1:請求與響應
- Part 2:模型與后臺
- Part 3:視圖和模板
- Part 4:表單和類視圖
- Part 5:測試
- Part 6:靜態文件
- Part 7:自定義admin
- 第一章:模型層
- 實戰一:基于Django3.2可重用登錄與注冊系統
- 1. 搭建項目環境
- 2. 設計數據模型
- 3. admin后臺
- 4. url路由和視圖
- 5. 前端頁面設計
- 6. 登錄視圖
- 7. Django表單
- 8. 圖片驗證碼
- 9. session會話
- 10. 注冊視圖
- 實戰二:Django3.2之CMDB資產管理系統
- 1.項目需求分析
- 2.模型設計
- 3.數據收集客戶端
- 4.收集Windows數據
- 5.Linux下收集數據
- 6.新資產待審批區
- 7.審批新資產
- django 快速搭建blog
- imooc-Django全棧項目開發實戰
- redis
- 1.1 Redis簡介
- 1.2 安裝
- 1.3 配置
- 1.4 服務端和客戶端命令
- 1.5 Redis命令
- 1.5.1 Redis命令
- 1.5.2 鍵(Key)
- 1.5.3 字符串(string)
- 1.5.4 哈希(Hash)
- 1.5.5 列表(list)
- 1.5.6 集合(set)
- 1.5.7 有序集合(sorted set)
- Windows
- Win10安裝Ubuntu子系統
- win10遠程桌面身份驗證錯誤,要求的函數不受支持
- hm軟件測試
- 02 linux基本命令
- Linux終端命令格式
- Linux基本命令(一)
- Linux基本命令(二)
- 02 數據庫
- 數據庫簡介
- 基本概念
- Navicat使用
- SQL語言
- 高級
- 03 深入了解軟件測試
- day01
- 04 python基礎
- 語言基礎
- 程序中的變量
- 程序的輸出
- 程序中的運算符
- 數據類型基礎
- 數據序列
- 數據類型分類
- 字符串
- 列表
- 元組
- 字典
- 列表與元組的區別詳解
- 函數
- 案例綜合應用
- 列表推導式
- 名片管理系統
- 文件操作
- 面向對象基礎(一)
- 面向對象基礎(二)
- 異常、模塊
- 05 web自動化測試
- Day01
- Day02
- Day03
- Day04
- Day05
- Day06
- Day07
- Day08
- 06 接口自動化測試
- 軟件測試面試大全2020
- 第一章 測試理論
- 軟件測試面試
- 一、軟件基礎知識
- 二、網絡基礎知識
- 三、數據庫
- SQL學生表 — 1
- SQL學生表 — 2
- SQL查詢 — 3
- SQL經典面試題 — 4
- 四、linux
- a. linux常用命令
- 五、自動化測試
- 自動化測試
- python 筆試題
- selenium面試題
- 如何判斷一個頁面上元素是否存在?
- 如何提高腳本的穩定性?
- 如何定位動態元素?
- 如何通過子元素定位父元素?
- 如果截取某一個元素的圖片,不要截取全部圖片
- 平常遇到過哪些問題?如何解決的
- 一個元素明明定位到了,點擊無效(也沒報錯),如果解決?
- selenium中隱藏元素如何定位?(hidden、display: none)
- 六、接口測試
- 接口測試常規面試題
- 接口自動化面試題
- json和字典dict的區別?
- 測試的數據你放在哪?
- 什么是數據驅動,如何參數化?
- 下個接口請求參數依賴上個接口的返回數據
- 依賴于登錄的接口如何處理?
- 依賴第三方的接口如何處理
- 不可逆的操作,如何處理,比如刪除一個訂單這種接口如何測試
- 接口產生的垃圾數據如何清理
- 一個訂單的幾種狀態如何全部測到,如:未處理,處理中,處理失敗,處理成功
- python如何連接數據庫操作?
- 七、App測試
- 什么是activity?
- Activity生命周期?
- Android四大組件
- app測試和web測試有什么區別?
- android和ios測試區別?
- app出現ANR,是什么原因導致的?
- App出現crash原因有哪些?
- app對于不穩定偶然出現anr和crash時候你是怎么處理的?
- app的日志如何抓取?
- logcat查看日志步驟
- 你平常會看日志嗎, 一般會出現哪些異常
- 抓包工具
- fiddler
- Wireshark
- 安全/滲透測試
- 安全性測試都包含哪些內容?
- 開放性思維題
- 面試題
- 字節測試面試
- 一、計算機網絡
- 二、操作系統
- 三、數據庫
- 四、數據結構與算法
- 五、Python
- 六、Linux
- 七、測試用例
- 八、智力/場景題
- 九、開放性問題
- python3_收集100+練習題(面試題)
- python3_100道題目答案
- 接口測試
- 接口測試實例_01
- python+requests接口自動化測試框架實例詳解
- 性能測試
- 性能測試流程
- 性能測試面試題
- 如何編寫性能測試場景用例
- 性能測試:TPS和QPS的區別
- jmeter
- jmeter安裝配置教程
- Jmeter性能測試 入門
- PyCharm
- 快捷工具
- 1-MeterSphere
- 一、安裝和升級
- 2- MobaXterm 教程
- 3-fiddler抓包
- 4-Xshell
- Xshell的安裝和使用
- Xshell遠程連接失敗怎么解決
- 5-Vmware
- Vmware提示以獨占方式鎖定此配置文件失敗
- Windows10徹底卸載VMWare虛擬機步驟
- VM ware無法關機,虛擬機繁忙
- VMware虛擬機下載與安裝
- 解決VM 與 Device/Credential Guard 不兼容。在禁用 Device/Credential Guard 后,可以運行 VM 的方法
- VMware虛擬機鏡像克隆與導入
- 6-WPS
- 1.WPS文檔里的批注怎么刪除
- 2.wps表格中設置圖表的坐標
- 3. wps快速繪制數學交集圖
- 7-MongoDB
- Win10安裝配置MongoDB
- Navicat 15.x for MongoDB安裝破解教程
- Apache
- apache層的賬戶權限控制,以及apache黑名單白名單過濾功能
- HTTP / HTTPS協議
- HTTP協議詳解
- 代理
- 狀態碼詳解
- HTTPS詳解
- Selenium3+python3
- (A) selenium
- selenium自動化環境搭建(Windows10)
- 火狐firebug和firepath插件安裝方法(最新)
- 元素定位工具和方法
- Selenium3+python3自動化
- 新手學習selenium路線圖---學前篇
- 1-操作瀏覽器基本方法
- 2-八種元素定位方法
- 3-CSS定位語法
- 4-登錄案例
- 5-定位一組元素find_elements
- 6-操作元素(鍵盤和鼠標事件)
- 7-多窗口、句柄(handle)
- 8-iframe
- 9-select下拉框
- 10-alert\confirm\prompt
- 11-JS處理滾動條
- 12-單選框和復選框(radiobox、checkbox)
- 13-js處理日歷控件(修改readonly屬性)
- 14-js處理內嵌div滾動條
- 15-table定位
- 16-js處理多窗口
- 17-文件上傳(send_keys)
- 18-獲取百度輸入聯想詞
- 19-處理瀏覽器彈窗
- 20-獲取元素屬性
- 21-判斷元素存在
- 22-爬頁面源碼(page_source)
- 23-顯式等待(WebDriverWait)
- 24-關于面試的題
- 25-cookie相關操作
- 26-判斷元素(expected_conditions)
- 27-判斷title(title_is)
- 28-元素定位參數化(find_element)
- 29-18種定位方法(find_elements)
- 30- js解決click失效問題
- 31- 判斷彈出框存在(alert_is_present)
- 32- 登錄方法(參數化)
- 33- 判斷文本(text_to_be_present_in_element)
- 34- unittest簡介
- 35- unittest執行順序
- 36- unittest之裝飾器(@classmethod)
- 37- unittest之斷言(assert)
- 38- 捕獲異常(NoSuchElementException)
- 39- 讀取Excel數據(xlrd)
- 40- 數據驅動(ddt)
- 41- 異常后截圖(screenshot)
- 42- jenkins持續集成環境搭建
- 43- Pycharm上python和unittest兩種運行方式
- 44- 定位的坑:class屬性有空格
- 45- 只截某個元素的圖
- 46- unittest多線程執行用例
- 47- unittest多線程生成報告(BeautifulReport)
- 48- 多線程啟動多個不同瀏覽器
- (B) python3+selenium3實現web UI功能自動化測試框架
- (C) selenium3常見報錯處理
- 書籍
- (D)Selenium3自動化測試實戰--基于Python語
- 第4章 WebDriver API
- 4.1 從定位元素開始
- 4.2 控制瀏覽器
- 4.3 WebDriver 中的常用方法
- 4.4 鼠標操作
- 4.5 鍵盤操作
- 4.6 獲得驗證信息
- 4.7 設置元素等待
- 4.8 定位一組元素
- 4.9 多表單切換
- 4.10 多窗口切換
- 4.11 警告框處理
- 4.12 下拉框處理
- 4.13 上傳文件
- 4.14 下載文件
- 4.15 操作cookie
- 4.16 調用JavaScript
- 4.17 處理HTML5視頻播放
- 4.18 滑動解鎖
- 4.19 窗口截圖
- 第5章 自動化測試模型
- 5.3 模塊化與參數化
- 5.4 讀取數據文件
- 第6章 unittest單元測試框架
- 6.1 認識unittest