付费下载
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、S e l eni um 自动化测试用例设计注意事项UI元素映射元素验证等待加载日志记录结果收集Selenium 自动化测试用例设计注意事项(一)自动化测试设计简介我们在本章提供的信息,对自动化测试领域的新人和经验丰富的老手都是有用的。本篇中描述最常见的自动化测试类型,还描 述了可以增强您的自动化测试套件可维护性和扩展性的设计模式”还没有使用这些技术的、有经验的自动化测试工程师会对这些技术更加感兴趣。测试类型您应该测试应用程序中的哪些部分?这取决于您的项目的各种影响因素:用户的期望,时间期限,项目经理设置的优先事项等 等。但是,一旦项目边界定义完成,作为测试工程师,你必须做出要测试什么的决定。
2、web应用测为了对 Web应用的测试类型进行分类,我们在这里创建了一些术语。这些术语并不意味着标准,但是这些概念对 试来说非常典型。测试静态内容静态内容测试是最简单的测试,用于验证静态的、不变化的UI元素的存在性。例如:T每个页面都有其预期的页面标题?这可以用来验证链接指向一个预期的页面。T应用程序的主页包含一个应该在页面顶部的图片吗?T网站的每一个页面是否都包含一个页脚区域来显示公司的联系方式,隐私政策,以及商标信息?T每一页的标题文本都使用的 <h1>标签吗?每个页面有正确的头部文本内吗?您可能需要或也可能不需要对页面内容进行自动化测试。如果您的网页内容是不易受到影响手工对内容
3、进行测试就足够了。果,例如您的应用文件的位置被移动,内容测试就非常有价值。测试链接Web站点的一个常见错误为的失效的链接或链接指向无效页。链接测试涉及点各个链接和验证预期的页面是否存在。如果静 态链接不经常更改,手动测试就足够。但是,如果你的网页设计师经常改变链接,或者文件不时被重定向,链接测试应该实现自动 化。?功能测试在您的应用程序中,需要测试应用的特定功能,需要一些类型的用户输入,并返回某种类型的结果。通常一个功能测试将涉及 多个页面,一个基于表单的输入页面,其中包含若干输入字段、提交和”取消操作,以及一个或多个响应页面。用户输入可以通过文本输入域,复选框,下拉列表,或任何其他的浏览器所
4、支持的输入。功能测试通常是需要自动化测试的最复杂的测试类型,但也通常是最重要的。典型的测试是登录,注册网站账户,用户帐户操 作,帐户设置变化,复杂的数据检索操作等等。功能测试通常对应着您的应用程序的描述应用特性或设计的使用场景。测试动态元素HTML标记的ids通常一个网页元素都有一个唯一的标识符,用于唯一地定位该网页中的元素。通常情况下,唯一标识符用性或name属性来实现。这些标识符可以是一个静态的,即不变的、字符串常量。它们也可以是动态生产值,在每个页面实例上都 是变化的。例如,有些 Web服务器可能在一个页面实例上命名所显示的文件为doc3861 ,并在其他页面实力上显示为doc6148,
5、这取决于用户在检索的 文档'验证文件是否存在的测试脚本,可能无法找到不变的识别码来定位该文件。通常情况下,具有变化 的标识符的动态元素存在于基于用户操作的结果页面上,然而,显然这取决于Web应用程序。下面是一个例子。<in putid="addForm:_ID74:_ID75:0:_ID79:0:?checkBox"t yp e="checkbox"value="true'7>这是一个HTML标记的复选框,ID将可能是一个其ID(addForm:_ID74:_ID75:0:_ID79:0:checkBox)是一个动态
6、生成的值。这个页面下次被打开时,复选框的不同的值。Ajax的测试RSS 源,Ajax 驱Ajax是一种支持动态改变用户界面元素的技术。页面元素可以动态更改,但不需要浏览器重新载入页面,如动画,其他实时数据更新等等。Ajax有不计其数的更新网页上的元素的方法。但是了解AJAX的最简单的方式,可以这样想,在动的应用程序中,数据可以从应用服务器检索,然后显示在页面上,而不需重新加载整个页面。只有一小部分的页面,或者只有元 素本身被重新加载。验证结果断言assert与验证verify什么时候使用断言命令,什么时候使用验证命令?这取决于你。差别在于在检查失败时,你想让测试程序做什么。你想让测试 终止,还
7、是想继续而只简单地记录检查失败?这需要权衡。如果您使用的断言,测试将在检查失败时停止,并不运行任何后续的检查。有时候,也许是经常的,这是你想要 的。如果测试失败,你会立刻知道测试没有通过。TestNG和JUnit等测试引擎提供在开发测试脚本时常用的插件,可以方便地标记那些测试为失败的测试。优点:你可以直截了当地看到检查是否通过。缺点:当检查失败,后续的检查不会被执行,无法收集那 些检查的结果状态。TestNG和JUnit得到反馈。您将如果您运行的是数以百计的测试,相比之下,验证命令将不会终止测试。如果您的测试只使用验证,可以得到保证是一假设没有意外的异常一测试会被执行完毕, 而不管是否发现缺陷
8、。缺点:你必须做更多的工作,以检查您的测试结果。也就是说,你不会从 需要在打印输出控制台或日志文件中查看结果。每次运行测试,你都需要花时间去查看结果输出每个都有它自己的日志,这将耗费时间。及时得到反馈会更合适,因此断言通常比验证更常使用。权衡:assertTextPresent , assertElementPresent 和 assertText您现在应该熟悉这些命令及使用它们的机制。如果没有,请参阅相关章节。在构建你的测试时,你需要决定T只检查在页面上的文本吗? (verify/assertText Present)HTML标记相关。(verify/assertT只检查是否在页面上存在HT
9、ML元素吗?即文本,图像,或其他没被检查的内容,只要和Element Present )assertText ,因为这是最严格的类型检查点。您可以随后更改或文本的不符合都会导致测试失败。也许你的网页设计师经常改T需要同时检查元素和它的文本内容?(verify/assertText没有正确的答案。这取决于您的测试要求。如有疑问,请使用 它,但至少你不会遗漏任何潜在的故障。Verify/assertText是最特殊的测试类型。HTML元素(标签)变页面面,而你不希望在他们改变页面时,你的测试失败,因为这是期望中的周期性变更。但是,假如你仍然需要检查的页面上的 东西,如段落、标题文本或图像。在这种情
10、况下,您可以使用verify/assertElement Present。这将确保一个特定类型的元素存在(如果使用XPath,可以确保它相对页面内其他对象的存在)。但你不关心的内容是什么,你只关心某个特定的元素,比方说,一 个图片在一个特定的位置。随着时间的推移和经验的积累,如何决定使用还是非常简单的。定位元素的策略选择一个定位策略有多种方式选择页面上的对象。但面对这些定位类型,如何权衡呢?回想一下,我们定位一个对象的方式:T元素的IDT元素的 name属性TXPath语句T通过一个链接的文本T文档对象模型(DOM使用元素的ID或name定位符,在测试执行方面来说,是最有效的方式。也让你的测试
11、代码更具可读性,如果在页面源代码中的ID或name属性被友好命名的话。XPath语句需要更长的时间来处理,因为浏览器必须运行它的XPath处理器。在InternetExp lorer7 ,XPath 出了名的慢。使用链接的文本进行定位是很方便的,并运行起来也不错。这种技术只适用于链接。另外,如果链接文本很可能会经常改变, 使用va标签定位元素将是更好的选择。不过,有时你必须使用 XPath定位。如果一个页面元素没有一个ID或者name属性,除了 XPath定位没得选择。(DOMt位器不再普遍使用,因为,XPath可以做得更好。dome位器只简单地为遗留测试而存在)。相对使用ID或name属性定
12、位,使用 XPath进行定位有一个独特的优势。使用XPath ( DOM中,你可以找到页面上相对于其他对象的一个对象。例如,如果有一个链接必须存在vdiv标签里的第二个段落内,您可以使用XPath进行定位。使用ID和name属性定位,你只能得出它们存在指定的页面,而不知具体的页面位置。如果你必须测试显示公司标志的图像出现在页面顶部的头部 分,XPath定位可能是更好的选择。定位动态元素正如前面测试类型部分所述,动态元素的页面标识在不同的页面实例上市不同的。例如,vaclass="button"id="adminHomeForm"onclick="
13、;returnoamSubmitForm('adminHomeForm',?'adminHomeForm:_lD38');"href="#">ViewArchivedAllocationEventsv/a>这个HTML锚标记定义了一个ID属性为“ adminHomeForm按钮。和大部分 HTMl#签相比,这是一个相当复杂的锚标记,但它仍 然是一个静态标签。每次页面被浏览器加载时,HTML将保持不变。它的ID在所有的页面实例里保持不变,也就是说,页面被展示时,这个UI元素总是有同样的标识符。所以,点击此按钮的测试脚本(
14、SeleniumServer )如下所示:selenium.click("adminHomeForm");HTML然而,你的应用程序,可能生成动态的HTML标识符。在不同的网页实例中,标识符发生改变。例如,一个动态的页面的元素可能会是这个样子:<in putid="addForm:_ID74:_ID75:0:_ID79:0:checkBox"ty pe="checkbox"name="addForm:_ID74:_ID75:0:_ID79:0: checkBox"value="true"/
15、>这是一个复选框,id和name属性都是addForm:_ID74:_ID75:0:_ID79:0:checkBox。在这种情况下,使用标准的定位,测试脚本应该是这样子的:selenium.click("addForm:_ID74:_ID75:0:_ID79:0:checkBox");elementno对于动态生成的标识符,这种做法行不通。下一次页面加载时,标识符将是一个不同的值,执行上述脚本会遇到“tfound "错误。要更正该问题,一个简单的解决办法是使用XPath定位替代ID定位器。因此,对于该复选框,可以简单地使用selenium.click(&qu
16、ot;/i npu t");XPath语句。或者,如果它不是在页面上的第一个文本输入域,尝试一个更详细的selenium.click('7/in put3");selenium.click("/div/p 2/in pu t3");ID,然后再使用它,例但是,如果你确实需要使用ID来定位元素,可以换一种不同的解决方案。您可以先捕捉到网站的这个如:Stnngcheckboxids?=selenium.getAIIFields();/Collectalli npu tIDso np age.?for(stringcheckboxid:checkbox
17、ids)?if(checkboxid.contains("addForm")?selenium.click(ex pectedText);?如果页面上只有一个复选框的ID文本为“expectedText "时,这种方法工作。定位Ajax元素定位、验证 AJAX元素的最好的方式是使用Selenium2.0webdriver 的API,它专门解决 Selenium1.0测试AJAX元素的一些限制。WebDriver用来实现定位的 By对在Selenim2.0中,可以使用 waitfor ()方法来等待一个页面元素变得可用。该参数是一个 象。这是 WebDriver的章
18、节中详细解释。在Selenium1.0 (Selenium-RC的)中,要做到这一点需要编写更多的编码,但它并不难。首先检查元素,如果它存在,等待 预定义的时间段,然后再重新检查。这在循环内执行,如果超过一个预定的超时,元素不存在则终止循环。让我们考虑页面上实现 AJAX效果的一个链接(链接=ajaxLink ),可以使用循环处理:/Lo opi nitialization.for(intsecond=0;second+)?/Iflo opi sreached60secondsthenbreakthelo op.?if(second>=60)break;?/Searchforel
19、ement"link=ajaxLink"andifavailablethenbreaklo op.?tryif(selenium.isElement Present("link=ajaxLink")break;catch(Exce ptione)?/ Pausefor1second.?Thread.slee p(1000);这当然不是唯一的解决办法。Ajax是一个共同的话题,在用户论坛上,查找一下之前的讨论,看看别人是如何做的。封装Selenium调用Selenium方法的与任何编程一样,你需要使用工具函数来处理在测试代码中重复的函数。避免重复的方法之一
20、是封装常用的 调用。例如,测试时经常点击页面上的元素,等待页面加载。selenium.click(elementLocator);selenium.waitFor PageToLoad(wait Period);为了不重复上述代码,你可以写一个包装方法实现这两个功能。/*?*ClicksandWaitsforpagetoload.?*?*p aramelementLocator?*p aramwait Period?*/P ublicvoidclickAndWait(StnngelementLocator,Stnngwait Period"?selenium.click(elemen
21、tLocator);?selenium.waitForPageToLoad(wait Period);判断元素存在的“安全操作”另一种常见的封装 Selenium的方法,在执行进一步操作前检查页面上的元素存在性。这有时被称为“安全操作”。例如,下 面的方法可用于实现一个依赖期望的元素存在的安全操作。/*?*Selenum-RC-Clicksonelementonlyifitisavailableo np age.?*?*p aramelementLocator?*/p ublicvoidsafeClick(StnngelementLocator)?if(selenium.isElement P
22、resent(elementLocator)?selenium.click(elementLocator);?/UsingtheTestNGA PIforlogging?Re porter.log("Element:"+elementLocato 叶",isnotavailableon page-"?+selenium.getLocation();?上述例子使用的是 Selenium1.0API , Selenium2.0同样支持安全操作。/*?*Selenium-WebDnver-Clicksonelementonlyifitisavailableo
23、np age.?*?*p aramelementLocator?*/p ublicvoidsafeClick(StringelementLocator)?WebElementwebElement=getDnver().findElement(By.XXXX(elementLocator);?if(webElement!=null)?selenium.click(elementLocator);?else?/UsingtheTestNGA PIforlogging?Re porter.log("Element:"+elementLocato 叶",isnotavai
24、lableon page-"?+getDnver().getUri();?在第二个例子中,xxxx方法是一个占位符,可以用元素定位方法进行替换。使用安全方法取决于测试开发人员的决定。因此,如果测试需要继续执行,即使知道页面上一些元素没有发现,这时可以使用安全方法,并发送一条缺少元素的消息到日志文件。这基本上等于实现了带报告机制的验证,而不是一个失败就终止执行的断言。 但是,如果元素必须在页面上出现,以便能够执行进一步的操作(如一个门户网站主页上的登录按钮),这时安全方法技术不应该 被使用。Selenium 自动化测试用例设计注意事项(二)UI映射一个UI映射是一种机制,它存储所有的定
25、位器的测试套件在一个地方,方便修改脚本,然后使用UI地图定位以被测试的元件。基本上,UI地图是一个存储库的测试脚本对象,对应于被测试的应用程序的UI元素的路径标识符或改变在 AUT。测试UI元素。是什么让一个UI地图有帮助吗?其主要目的是测试脚本的管理更加容易。当定位需要编辑,有一个中央位置轻松地找到对象,而不是通过搜索测试脚本代码。此外,它允许改变的标识符在一个地方,而不是在多个地方,以使更改在测试脚本,或为此事,在 多个测试脚本。总之,一个UI地图有两个显着的优点。 UI对象使用一个集中的位置,而不是让他们分散在整个脚本。这使得脚本维护更高效。 神秘的HTML标识符和名称可以被赋予了更多的
26、人类可读的名字,提高测试脚本的可读性。考虑下面很难理解的测试代码(Java语言)。P ublicvoidtestNew()throwsExce ption?selenium.ty pe("loginForm:tbUsername","xxxxxxxx");?selenium.click("loginForm:btnLogin");?selenium.click("adminHomeForm:_activitynew");?selenium.waitForPageToLoad("30000");?
27、selenium.click("addEditEventForm:_IDcancel");?selenium.waitForPageToLoad("30000");?selenium.click("adminHomeForm:_activityold");?selenium.waitForPageToLoad("30000");该代码很难被那些不熟悉待测应用(AUT )页面源代码的人理解。即使是待测应用的固定用户可能也很难理解这段脚本代码的作用。一个更好的脚本可能是:p ublicvoidtestNew()thro
28、wsExce ption?selenium.t yp e(admin.usemame,"xxxxxxxx");?selenium.click(admin.loginbutton);?selenium.waitForPageToLoad("30000");?selenium.waitForPageToLoad("30000");?selenium.waitForPageToLoad("30000");使用备注和空格换行、再加上UI映射标识,下面的代码更加易读:p ublicvoidtestNew()throwsExc
29、e ption? Op ena ppurl.? provideadminusername.?selenium.t yp e(admin.username,"xxxxxxxx");?/ClickonLoginbutton.?selenium.click(admin.loginbutton);?/ClickonCreateNewEventbutton.?selenium.waitForPageToLoad("30000");?/ClickonCancelbutton.?selenium.waitForPageToLoad("30000")
30、;?/ClickonViewOldEventsbutton.?selenium.waitForPageToLoad("30000");有多种方法可以实现 UI映射。可以创建一个类或结构体来存储字符串变量,每个变量存储一个定位信息。或者,使用一个文 本文件来存储键值对。在 Java中,一个包含键值对的属性property文件可能是最好的方法。考虑如下属性文件perties,为上述代码例子中的UI元素指定了 “别名":adm in. user name=log inFo rm:tbUser name admi n.l og in butt on=adm
31、i nHo meForm:_activityold其中定位信息还是指向页面的HTML对象,但我们在测试脚本和 UI元素之间引入一层抽象层。测试类从属性文件中读取定位信息,从而实现UI映射。页面对象设计模式页面对象设计模式,可以提高自动化测试脚本的维护性、减少代码重复,越发流行。页面对象是一个面向对象的类,作为待测应用对外提供的接口。测试代码在需要和UI页面交互时,使用此页面对象类的方法。这样做的好处是,如果UI页面发生变化,测试代码本身并不需要改变,只需要改变相应的页面对象的代码。为适应新UI页面的所有更改,都位于一个地方。页面对象设计模式具有以下优点:1、测试代码和页面相关的代码,比如页面元
32、素定位信息(若使用 UI映射,也包括定位信息的应用),页面布局等,完全分离;2、可以维护单一的储存库来存储页面提供的服务或操作,而不是把他们分散在测试代码中。在这两种情况下,这使得任何由于UI界面变化导致的修改,都可以在一个地方进行修改。关于该技术的更多有用信息,可以在众多的博客上找到。我们也鼓励读者去阅读更多。许多人写这样的设计模式和超出本用户指南的范围,可以提供有用的提示。不 过,为了让你开始,我们将举例说明页面对象的一个简单的例子。首先,考虑一个例子,典型的自动化测试,不使用页面对象。/*?*Testsloginfeature?*/p ublicclassLogin? publicvoi
33、dtestLogin()?selenium.ty pe("in pu tBox","testUser");?se|enium.ty pe(" password","mysu persecret password");?selenium.click("sign-in");?selenium.waitForPageToLoad(" PageWait Period");?Assert.assertTrue(selenium.isElement Present("co mp
34、 osebutton").?"Loginwasunsuccessful");?这种方法有两个问题。UI改变了1、没有分离测试代码和待测应用的定位器(在这个例子中是ID );两者都交织在一个单一方法中。如果待测应用它的标识,布局,或登录输入和处理的方式变化,测试代码本身必须改变。2、ID定位信息分散在多个测试代码中,所有的测试不得不使用此登录页面。使用页面对象技术,上述测试代码可以按如下方式重写,为登录页面的页面对象例子:/*?*P ageObjectenca psulatestheSign-i np age.?*/p ublicclassSign InP age?
35、 privateSeleniumselenium;? publicSignIn Page(Seleniumselenium)?this.selenium=selenium;?if(!selenium.getTitle().equals("Signin page")?thrownewlllegalStateExce ption("Thisisnotsigni np age,current pageis:"?+selenium.getLocation();?/*?*Loginasvaliduser?*?* p aramuserName?* param pas
36、sword?*returnHome Pageobject?*/? publicHome PageloginValidUser(StringuserName,String password" ?selenium.t yp e("usernamefield",userName);?selenium.ty pe(" passwordfield", password);?selenium.click("sign-in");?se|enium.waitForPageToLoad("wait Period");?re
37、turnnewHome Page(selenium);?主页的页面对象可能会是这个样子:/*?*P ageObjectenca psulatestheHome Page?*/p ublicclassHome Page? privateSeleniumselenium;? publicHome Page(Seleniumselenium)?if(!selenium.getTitle().equals("Home Pageofloggedinuser")?thrownewlllegalStateExce ption("ThisisnotHome Pageoflogge
38、dinuser,current page"+?"is:"+selenium.getLocation();? publicHome Pagemanage Profile()? pageenca psulationtomanage profilefunctionality?returnnewHome Page(selenium);?/*Moremethodsofferingtheservicesre presentedbyHome Page?ofLoggedUser.Thesemethodsinturnmightreturnm oreP ageObjects?fore
39、xa mpl eclickonCo mpo semailbuttoncouldreturnCo mp oseMailclassobject*/现在,使用上述两个页面对象的登录测试代码,如下所示。/*?*Testsloginfeature?*/P ublicclassTestLogin? publicvoidtestLogin()?SignIn Pagesignin Page=newSignln Page(selenium);?Home Pagehome Page=signln Page.loginValidUser("userName"," password&qu
40、ot;);?Assert.assertTrue(selenium.isElement Present("co mp osebutton").?"Loginwasunsuccessful");?但也有一些基本的规则以保证得到测试代码具有所需的可维护性。怎么样使用页面对象进行设计有很大的灵活性,身不应该被验证或断言。这应该是测试的一部分,并应始终在测试代码中去验证或断言,而不要放在页面对象内。页面对象将包含页面对象本页面展现,方法的形式表示页面提供的服务,但不需要包含应该在测试代码中维护的代码。唯一的应该存在页面对象中的验证方法是,验证页面、页面上的重要元素
41、,被正确的加载。这这个验证应该在页面初始化时进行。在上面的例子中,SignIn Page和Home Page的构造函数检查了期望的页面是否可用,是否准备好接受测试代码的请求。 页面对象并不一定要代表整个页面。页面对象设计模式可用于表示页面上组件。在待测应用上的一个页面若有多个组件,每个 组件对应一个页面对象可以提高可维护性。在测试时,还会遇到其他的测试设计模式。有些人用一个页面工厂模式来实例化页面对象。讨论所有的这些测试模式,超出了 本文档的的范围。在这里,我们只为大家介绍概念,使读者知道这些东西可以些什么。正如前面提到的,很多人都在博客上讨论这个话题,我们鼓励读者搜索这些话题。数据驱动测试数
42、据驱动测试是指相同的测试(或测试集)可以使用不同的数据多次执行。这些数据集往往来自外部文件,如CSV文件,文本文件,或者是从数据库加载。数据驱动测试是一种常用的自动化测试技术,使用不同的输入对应用程序进行多次验证。当测试被针 对不同的数据进行设计时,所输入的数据就可以扩展,基本上不需要修改测试代码就可以进行更多的测试。#CollectionofStnngvaluessource=op en("i npu t_file.txt","r")values=source.readlines()source.close()#ExecuteForlo op fore
43、achStringinthevaluesarrayforsearchinvalues:?sel. op en("/")?sel.ty pe("q",search)?sel.click("btnG")?sel.waitForPageToLoad("30000")?self.failUnless(sel.is_text_ present("Results*for"+search)上面的Python代码打开一个文本文件,这个文件每行包含不同的搜索字符串。然后代码保存字符串到一个字符串数组,对数值 进行遍历,使用搜
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 19691-2026地理标志产品质量要求狗牯脑茶
- T/ZJSEE 0027-2024氢储能电站运行维护安全导则
- T/ISEAA 009-2024信息安全技术 网络安全等级保护区块链安全测评扩展要求
- T/CMEAS 081-2026医疗机构药品集中带量采购管理规范
- T/CASME 2090-2025陆上风力发电场土地利用效率评估规范
- T/CSHE 0004-2022水库温室气体净排放量评估技术导则
- GB/T 19866-2026焊接工艺规程及评定的一般原则
- AI在华文教育中的应用
- PHP企业面试笔试真题(含详细答案解析)
- 制鞋车间胶粘剂防毒通风方案
- GB/T 48666-2026电子病历版式文档技术要求
- 2024NOGG临床指南:骨质疏松的预防和治疗
- 郭舒湲色彩基础课件
- 《机械制图》电子教材
- 2025年新媒体传播与营销考试试题及答案
- 安全生产考核巡查办法全文
- 职业技术学院宿舍门禁系统使用管理制度
- 中国移动 校招笔试题目及答案
- 铁路旅客运输服务铁路旅客运输服务质量规范76课件
- 孕早期保健知识教学课件
- 骨科常用药物相关知识
评论
0/150
提交评论