如何使用Selenium C#编写Dynamics 365 CRM通用文件上传测试
实现通用的Dynamics 365 CRM文件上传测试(Selenium C#)
问题描述
我正在用Selenium C#编写Microsoft Dynamics 365 CRM的测试用例,需要实现文件浏览与上传的测试功能,希望代码具备通用性,让任何人无需使用我的本地文件路径即可运行该代码。
现有代码
ContactPage.cs
public ContactsPage UploadDocumentContact(string iRType) { WaitUntilElementIsVisible(uploadDocuments); Click(uploadDocuments); Wait(10); WaitUntilElementIsVisible(dontAllow_btn); Click(dontAllow_btn); WaitUntilElementIsVisible(browse_btn); Click(browse_btn); return this; }
UploadDocumentSteps.cs
[When(@"Upload document from ""([^""]*)""")] public void WhenCreateIllustrationRequestFrom(string IRType) { switch (IRType.ToUpper()) { case Data.Accounts: accountsPage = new AccountsPage(driver).OpenIRAccount(); break; case Data.Investor: contactsPage = new ContactsPage(driver).OpenInvestorContact(); break; case Data.Locations: locationsPage = new LocationsPage(driver).OpenExistingLocation(); break; case Data.Cases: casesPage = new CasesPage(driver).SearchForCase(); break; throw new Exception($"{IRType} type is not found..."); } accountsPage = new AccountsPage(driver).UploadDocumentAccount(IRType); contactsPage = new ContactsPage(driver).UploadDocumentContact(IRType); locationsPage = new LocationsPage(driver).UploadDocumentLocation(IRType); casesPage = new CasesPage(driver).UploadDocumentCase(IRType); }
Feature文件
Scenario Outline: Verify Upload Document Given User navigates to CRM application with valid credentials When User navigates to "<page>" page And Upload document from "<IRType>" Then Document should be Uploaded successfully Examples: | page | IRType | | Accounts | Accounts | | Contacts | Investor | | Locations | Locations | | Cases | Cases |
解决方案
核心思路
- 使用嵌入式资源文件:将测试用文件嵌入到项目中,编译后随程序集分发,无需依赖本地路径。
- 绕过系统文件对话框:直接通过Selenium的
SendKeys给文件输入框传递路径,避免系统级对话框的兼容性问题。 - 重构代码减少冗余:提取通用逻辑,避免重复实例化页面和执行无效操作。
具体实现步骤
1. 添加嵌入式测试文件
- 将测试用文件(如
TestDocument.pdf)添加到项目中(可创建Resources文件夹统一存放)。 - 右键文件 → 属性 → 设置“生成操作”为嵌入的资源。
2. 编写文件上传辅助类
创建FileUploadHelper.cs,用于从嵌入式资源提取临时文件路径:
using System; using System.IO; using System.Reflection; public static class FileUploadHelper { public static string GetEmbeddedTestFilePath(string resourceFullName) { var assembly = Assembly.GetExecutingAssembly(); using (var resourceStream = assembly.GetManifestResourceStream(resourceFullName)) { if (resourceStream == null) throw new FileNotFoundException($"未找到嵌入式资源:{resourceFullName}"); // 生成临时文件路径 var tempFileName = $"{Guid.NewGuid()}{Path.GetExtension(resourceFullName)}"; var tempFilePath = Path.Combine(Path.GetTempPath(), tempFileName); // 将嵌入式资源写入临时文件 using (var fileStream = new FileStream(tempFilePath, FileMode.Create)) { resourceStream.CopyTo(fileStream); } return tempFilePath; } } }
3. 修改页面上传逻辑(以ContactPage为例)
去掉点击浏览按钮的操作,直接定位文件输入框并传入临时文件路径:
public ContactsPage UploadDocumentContact(string iRType) { WaitUntilElementIsVisible(uploadDocuments); Click(uploadDocuments); WaitUntilElementIsVisible(dontAllow_btn); Click(dontAllow_btn); // 定位Dynamics 365的文件上传输入框(需根据实际页面调整选择器) var fileInputElement = driver.FindElement(By.CssSelector("input[type='file']")); // 获取嵌入式测试文件路径(替换为你的命名空间+文件路径) var testFilePath = FileUploadHelper.GetEmbeddedTestFilePath("CRMTest.Resources.TestDocument.pdf"); // 直接传入路径,绕过系统对话框 fileInputElement.SendKeys(testFilePath); // 等待上传完成(根据页面实际的成功提示元素调整) WaitUntilElementIsVisible(uploadSuccessIndicator); // 可选:测试完成后删除临时文件 File.Delete(testFilePath); return this; }
4. 重构步骤代码
修正UploadDocumentSteps.cs中的冗余操作,每个分支仅处理对应页面:
[When(@"Upload document from ""([^""]*)""")] public void WhenCreateIllustrationRequestFrom(string IRType) { switch (IRType.ToUpper()) { case Data.Accounts: accountsPage = new AccountsPage(driver).OpenIRAccount(); accountsPage.UploadDocumentAccount(IRType); break; case Data.Investor: contactsPage = new ContactsPage(driver).OpenInvestorContact(); contactsPage.UploadDocumentContact(IRType); break; case Data.Locations: locationsPage = new LocationsPage(driver).OpenExistingLocation(); locationsPage.UploadDocumentLocation(IRType); break; case Data.Cases: casesPage = new CasesPage(driver).SearchForCase(); casesPage.UploadDocumentCase(IRType); break; default: throw new Exception($"{IRType} 类型未找到..."); } }
注意事项
- 嵌入式资源名称:需确保
resourceFullName是项目命名空间+文件所在路径+文件名,例如CRMTest.Resources.TestDocument.pdf。 - 元素定位:Dynamics 365的文件输入框可能隐藏,若
SendKeys无效,可先通过JavaScript设置元素可见:IJavaScriptExecutor js = (IJavaScriptExecutor)driver; js.ExecuteScript("arguments[0].style.display = 'block';", fileInputElement); - 临时文件清理:建议在测试的
[AfterScenario]钩子中统一清理临时文件,避免磁盘占用。
内容的提问来源于stack exchange,提问作者Manko
相关产品推荐
相关产品推荐

